openlp-core team mailing list archive
-
openlp-core team
-
Mailing list archive
-
Message #02426
[Merge] lp:~j-corwin/openlp/present into lp:openlp
Jonathan Corwin has proposed merging lp:~j-corwin/openlp/present into lp:openlp.
Requested reviews:
OpenLP Core (openlp-core)
Related bugs:
#598361 AttributeError: 'NoneType' object has no attribute 'isPaused'
https://bugs.launchpad.net/bugs/598361
Common thumbnail folder for all presentation types, and create icons/thumbnails when presentation is added to media manager.
--
https://code.launchpad.net/~j-corwin/openlp/present/+merge/29659
Your team OpenLP Core is requested to review the proposed merge of lp:~j-corwin/openlp/present into lp:openlp.
=== modified file 'openlp/core/lib/__init__.py'
--- openlp/core/lib/__init__.py 2010-07-03 13:26:29 +0000
+++ openlp/core/lib/__init__.py 2010-07-11 20:27:44 +0000
@@ -174,6 +174,8 @@
"""
preview = QtGui.QImage(image)
if not preview.isNull():
+ if(preview.width() == width and preview.height == height):
+ return preview
preview = preview.scaled(width, height, QtCore.Qt.KeepAspectRatio,
QtCore.Qt.SmoothTransformation)
realw = preview.width()
=== modified file 'openlp/core/lib/mediamanageritem.py'
--- openlp/core/lib/mediamanageritem.py 2010-07-10 01:01:14 +0000
+++ openlp/core/lib/mediamanageritem.py 2010-07-11 20:27:44 +0000
@@ -379,14 +379,17 @@
"""
Validates to see if the file still exists or thumbnail is up to date
"""
- if os.path.exists(file):
+ if not os.path.exists(file):
+ return False
+ if os.path.exists(thumb):
filedate = os.stat(file).st_mtime
thumbdate = os.stat(thumb).st_mtime
#if file updated rebuild icon
if filedate > thumbdate:
self.iconFromFile(file, thumb)
- return True
- return False
+ else:
+ self.iconFromFile(file, thumb)
+ return True
def iconFromFile(self, file, thumb):
"""
=== modified file 'openlp/plugins/presentations/lib/impresscontroller.py'
--- openlp/plugins/presentations/lib/impresscontroller.py 2010-07-05 22:17:14 +0000
+++ openlp/plugins/presentations/lib/impresscontroller.py 2010-07-11 20:27:44 +0000
@@ -1,411 +1,468 @@
-# -*- 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 #
-###############################################################################
-
-# OOo API documentation:
-# http://api.openoffice.org/docs/common/ref/com/sun/star/presentation/XSlideShowController.html
-# http://wiki.services.openoffice.org/wiki/Documentation/DevGuide/ProUNO/Basic/Getting_Information_about_UNO_Objects#Inspecting_interfaces_during_debugging
-# http://docs.go-oo.org/sd/html/classsd_1_1SlideShow.html
-# http://www.oooforum.org/forum/viewtopic.phtml?t=5252
-# http://wiki.services.openoffice.org/wiki/Documentation/DevGuide/Working_with_Presentations
-# http://mail.python.org/pipermail/python-win32/2008-January/006676.html
-# http://www.linuxjournal.com/content/starting-stopping-and-connecting-openoffice-python
-# http://nxsy.org/comparing-documents-with-openoffice-and-python
-
-import logging
-import os
-import time
-
-from openlp.core.lib import resize_image
-
-if os.name == u'nt':
- from win32com.client import Dispatch
- import pywintypes
-else:
- try:
- import uno
- from com.sun.star.beans import PropertyValue
- uno_available = True
- except ImportError:
- uno_available = False
-
-from PyQt4 import QtCore
-
-from presentationcontroller import PresentationController, PresentationDocument
-
-log = logging.getLogger(__name__)
-
-class ImpressController(PresentationController):
- """
- Class to control interactions with Impress presentations.
- It creates the runtime environment, loads and closes the presentation as
- well as triggering the correct activities based on the users input
- """
- log.info(u'ImpressController loaded')
-
- def __init__(self, plugin):
- """
- Initialise the class
- """
- log.debug(u'Initialising')
- PresentationController.__init__(self, plugin, u'Impress')
- self.supports = [u'.odp']
- self.alsosupports = [u'.ppt', u'.pps', u'.pptx', u'.ppsx']
- self.process = None
- self.desktop = None
-
- def check_available(self):
- """
- Impress is able to run on this machine
- """
- log.debug(u'check_available')
- if os.name == u'nt':
- return self.get_com_servicemanager() is not None
- else:
- return uno_available
-
- def start_process(self):
- """
- Loads a running version of OpenOffice in the background.
- It is not displayed to the user but is available to the UNO interface
- when required.
- """
- log.debug(u'start process Openoffice')
- if os.name == u'nt':
- self.manager = self.get_com_servicemanager()
- self.manager._FlagAsMethod(u'Bridge_GetStruct')
- self.manager._FlagAsMethod(u'Bridge_GetValueObject')
- else:
- # -headless
- cmd = u'openoffice.org -nologo -norestore -minimized -invisible -nofirststartwizard -accept="socket,host=localhost,port=2002;urp;"'
- self.process = QtCore.QProcess()
- self.process.startDetached(cmd)
- self.process.waitForStarted()
-
- def get_uno_desktop(self):
- log.debug(u'get UNO Desktop Openoffice')
- ctx = None
- loop = 0
- log.debug(u'get UNO Desktop Openoffice - getComponentContext')
- context = uno.getComponentContext()
- log.debug(u'get UNO Desktop Openoffice - createInstaneWithContext - '
- u'UnoUrlResolver')
- resolver = context.ServiceManager.createInstanceWithContext(
- u'com.sun.star.bridge.UnoUrlResolver', context)
- while ctx is None and loop < 3:
- try:
- log.debug(u'get UNO Desktop Openoffice - resolve')
- ctx = resolver.resolve(u'uno:socket,host=localhost,port=2002;'
- u'urp;StarOffice.ComponentContext')
- except:
- log.exception(u'Unable to find running instance ')
- self.start_process()
- loop += 1
- try:
- self.manager = ctx.ServiceManager
- log.debug(u'get UNO Desktop Openoffice - createInstanceWithContext'
- u' - Desktop')
- desktop = self.manager.createInstanceWithContext(
- "com.sun.star.frame.Desktop", ctx )
- return desktop
- except:
- log.exception(u'Failed to get UNO desktop')
- return None
-
- def get_com_desktop(self):
- log.debug(u'get COM Desktop OpenOffice')
- return self.manager.createInstance(u'com.sun.star.frame.Desktop')
-
- def get_com_servicemanager(self):
- log.debug(u'get_com_servicemanager openoffice')
- try:
- return Dispatch(u'com.sun.star.ServiceManager')
- except pywintypes.com_error:
- log.exception(u'Failed to get COM service manager')
- return None
-
- def kill(self):
- """
- Called at system exit to clean up any running presentations
- """
- log.debug(u'Kill OpenOffice')
- 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')
- else:
- try:
- desktop.terminate()
- log.debug(u'OpenOffice killed')
- except:
- log.exception(u'Failed to terminate OpenOffice')
-
- def add_doc(self, name):
- log.debug(u'Add Doc OpenOffice')
- doc = ImpressDocument(self, name)
- self.docs.append(doc)
- return doc
-
-class ImpressDocument(PresentationDocument):
- def __init__(self, controller, presentation):
- log.debug(u'Init Presentation OpenOffice')
- PresentationDocument.__init__(self, controller, presentation)
- self.document = None
- self.presentation = None
- self.control = None
-
- def load_presentation(self):
- """
- Called when a presentation is added to the SlideController.
- It builds the environment, starts communcations with the background
- OpenOffice task started earlier. If OpenOffice is not present is is
- started. Once the environment is available the presentation is loaded
- and started.
-
- ``presentation``
- The file name of the presentatios to the run.
- """
- log.debug(u'Load Presentation OpenOffice')
- #print "s.dsk1 ", self.desktop
- if os.name == u'nt':
- desktop = self.controller.get_com_desktop()
- if desktop is None:
- self.controller.start_process()
- desktop = self.controller.get_com_desktop()
- url = u'file:///' + self.filepath.replace(u'\\', u'/').replace(
- u':', u'|').replace(u' ', u'%20')
- else:
- desktop = self.controller.get_uno_desktop()
- url = uno.systemPathToFileUrl(self.filepath)
- if desktop is None:
- return
- self.desktop = desktop
- #print "s.dsk2 ", self.desktop
- properties = []
- properties.append(self.create_property(u'Minimized', True))
- properties = tuple(properties)
- try:
- self.document = desktop.loadComponentFromURL(url, u'_blank',
- 0, properties)
- except:
- log.exception(u'Failed to load presentation')
- return
- self.presentation = self.document.getPresentation()
- self.presentation.Display = \
- self.controller.plugin.renderManager.screens.current_display + 1
- self.control = None
- self.create_thumbnails()
-
- def create_thumbnails(self):
- """
- Create thumbnail images for presentation
- """
- log.debug(u'create thumbnails OpenOffice')
- if self.check_thumbnails():
- return
- if os.name == u'nt':
- thumbdir = u'file:///' + self.thumbnailpath.replace(
- u'\\', u'/').replace(u':', u'|').replace(u' ', u'%20')
- else:
- thumbdir = uno.systemPathToFileUrl(self.thumbnailpath)
- props = []
- props.append(self.create_property(u'FilterName', u'impress_png_Export'))
- props = tuple(props)
- doc = self.document
- pages = doc.getDrawPages()
- for idx in range(pages.getCount()):
- page = pages.getByIndex(idx)
- doc.getCurrentController().setCurrentPage(page)
- 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 - 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')
- else:
- prop = PropertyValue()
- prop.Name = name
- prop.Value = value
- return prop
-
- def close_presentation(self):
- """
- Close presentation and clean up objects
- Triggered by new object being added to SlideController or OpenLP
- being shutdown
- """
- log.debug(u'close Presentation OpenOffice')
- if self.document:
- if self.presentation:
- try:
- self.presentation.end()
- self.presentation = None
- self.document.dispose()
- except:
- #We tried!
- pass
- self.document = None
- self.controller.remove_doc(self)
-
- def is_loaded(self):
- log.debug(u'is loaded OpenOffice')
- #print "is_loaded "
- if self.presentation is None or self.document is None:
- #print "no present or document"
- return False
- try:
- if self.document.getPresentation() is None:
- #print "no getPresentation"
- return False
- except:
- return False
- return True
-
- def is_active(self):
- log.debug(u'is active OpenOffice')
- #print "is_active "
- if not self.is_loaded():
- #print "False "
- return False
- #print "self.con ", self.control
- if self.control is None:
- return False
- return True
-
- def unblank_screen(self):
- log.debug(u'unblank screen OpenOffice')
- return self.control.resume()
-
- def blank_screen(self):
- log.debug(u'blank screen OpenOffice')
- self.control.blankScreen(0)
-
- def is_blank(self):
- """
- Returns true if screen is blank
- """
- log.debug(u'is blank OpenOffice')
- if self.control:
- return self.control.isPaused()
- else:
- return False
-
- def stop_presentation(self):
- log.debug(u'stop presentation OpenOffice')
- # deactivate should hide the screen according to docs, but doesn't
- #self.control.deactivate()
- self.presentation.end()
- self.control = None
-
- def start_presentation(self):
- log.debug(u'start presentation OpenOffice')
- if self.control is None or not self.control.isRunning():
- self.presentation.start()
- # start() returns before the getCurrentComponent is ready.
- # Try for 5 seconds
- i = 1
- while self.desktop.getCurrentComponent() is None and i < 50:
- time.sleep(0.1)
- i = i + 1
- self.control = \
- self.desktop.getCurrentComponent().Presentation.getController()
- else:
- self.control.activate()
- self.goto_slide(1)
-
- def get_slide_number(self):
- return self.control.getCurrentSlideIndex() + 1
-
- def get_slide_count(self):
- return self.document.getDrawPages().getCount()
-
- def goto_slide(self, slideno):
- self.control.gotoSlideIndex(slideno-1)
-
- def next_step(self):
- """
- Triggers the next effect of slide on the running presentation
- """
- self.control.gotoNextEffect()
-
- def previous_step(self):
- """
- Triggers the previous slide on the running presentation
- """
- self.control.gotoPreviousSlide()
-
- def get_slide_text(self, slide_no):
- """
- Returns the text on the slide
-
- ``slide_no``
- The slide the text is required for, starting at 1
- """
- doc = self.document
- pages = doc.getDrawPages()
- text = ''
- page = pages.getByIndex(slide_no - 1)
- for idx in range(page.getCount()):
- shape = page.getByIndex(idx)
- 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
-
- ``slide_no``
- The slide the notes are required for, starting at 1
- """
- doc = self.document
- pages = doc.getDrawPages()
- text = ''
- page = pages.getByIndex(slide_no - 1)
- notes = page.getNotesPage()
- for idx in range(notes.getCount()):
- shape = notes.getByIndex(idx)
- if shape.supportsService("com.sun.star.drawing.Text"):
- text += shape.getString() + '\n'
- return text
-
+# -*- 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 #
+###############################################################################
+
+# OOo API documentation:
+# http://api.openoffice.org/docs/common/ref/com/sun/star/presentation/XSlideShowController.html
+# http://wiki.services.openoffice.org/wiki/Documentation/DevGuide/ProUNO/Basic/Getting_Information_about_UNO_Objects#Inspecting_interfaces_during_debugging
+# http://docs.go-oo.org/sd/html/classsd_1_1SlideShow.html
+# http://www.oooforum.org/forum/viewtopic.phtml?t=5252
+# http://wiki.services.openoffice.org/wiki/Documentation/DevGuide/Working_with_Presentations
+# http://mail.python.org/pipermail/python-win32/2008-January/006676.html
+# http://www.linuxjournal.com/content/starting-stopping-and-connecting-openoffice-python
+# http://nxsy.org/comparing-documents-with-openoffice-and-python
+
+import logging
+import os
+import time
+
+from openlp.core.lib import resize_image
+
+if os.name == u'nt':
+ from win32com.client import Dispatch
+ import pywintypes
+else:
+ try:
+ import uno
+ from com.sun.star.beans import PropertyValue
+ uno_available = True
+ except ImportError:
+ uno_available = False
+
+from PyQt4 import QtCore
+
+from presentationcontroller import PresentationController, PresentationDocument
+
+log = logging.getLogger(__name__)
+
+class ImpressController(PresentationController):
+ """
+ Class to control interactions with Impress presentations.
+ It creates the runtime environment, loads and closes the presentation as
+ well as triggering the correct activities based on the users input
+ """
+ log.info(u'ImpressController loaded')
+
+ def __init__(self, plugin):
+ """
+ Initialise the class
+ """
+ log.debug(u'Initialising')
+ PresentationController.__init__(self, plugin, u'Impress')
+ self.supports = [u'.odp']
+ self.alsosupports = [u'.ppt', u'.pps', u'.pptx', u'.ppsx']
+ self.process = None
+ self.desktop = None
+ self.manager = None
+
+ def check_available(self):
+ """
+ Impress is able to run on this machine
+ """
+ log.debug(u'check_available')
+ if os.name == u'nt':
+ return self.get_com_servicemanager() is not None
+ else:
+ return uno_available
+
+ def start_process(self):
+ """
+ Loads a running version of OpenOffice in the background.
+ It is not displayed to the user but is available to the UNO interface
+ when required.
+ """
+ log.debug(u'start process Openoffice')
+ if os.name == u'nt':
+ self.manager = self.get_com_servicemanager()
+ self.manager._FlagAsMethod(u'Bridge_GetStruct')
+ self.manager._FlagAsMethod(u'Bridge_GetValueObject')
+ else:
+ # -headless
+ cmd = u'openoffice.org -nologo -norestore -minimized -invisible -nofirststartwizard -accept="socket,host=localhost,port=2002;urp;"'
+ self.process = QtCore.QProcess()
+ self.process.startDetached(cmd)
+ self.process.waitForStarted()
+
+ def get_uno_desktop(self):
+ """
+ On non-Windows platforms, use Uno. Get the OpenOffice desktop
+ which will be used to manage impress
+ """
+ log.debug(u'get UNO Desktop Openoffice')
+ ctx = None
+ loop = 0
+ log.debug(u'get UNO Desktop Openoffice - getComponentContext')
+ context = uno.getComponentContext()
+ log.debug(u'get UNO Desktop Openoffice - createInstaneWithContext - '
+ u'UnoUrlResolver')
+ resolver = context.ServiceManager.createInstanceWithContext(
+ u'com.sun.star.bridge.UnoUrlResolver', context)
+ while ctx is None and loop < 3:
+ try:
+ log.debug(u'get UNO Desktop Openoffice - resolve')
+ ctx = resolver.resolve(u'uno:socket,host=localhost,port=2002;'
+ u'urp;StarOffice.ComponentContext')
+ except:
+ log.exception(u'Unable to find running instance ')
+ self.start_process()
+ loop += 1
+ try:
+ self.manager = ctx.ServiceManager
+ log.debug(u'get UNO Desktop Openoffice - createInstanceWithContext'
+ u' - Desktop')
+ desktop = self.manager.createInstanceWithContext(
+ "com.sun.star.frame.Desktop", ctx )
+ return desktop
+ except:
+ log.exception(u'Failed to get UNO desktop')
+ return None
+
+ def get_com_desktop(self):
+ """
+ On Windows platforms, use COM. Return the desktop object which
+ will be used to manage Impress
+ """
+ log.debug(u'get COM Desktop OpenOffice')
+ if not self.manager:
+ return None
+ return self.manager.createInstance(u'com.sun.star.frame.Desktop')
+
+ def get_com_servicemanager(self):
+ """
+ Return the OOo service manager for windows
+ """
+ log.debug(u'get_com_servicemanager openoffice')
+ try:
+ return Dispatch(u'com.sun.star.ServiceManager')
+ except pywintypes.com_error:
+ log.exception(u'Failed to get COM service manager')
+ return None
+
+ def kill(self):
+ """
+ Called at system exit to clean up any running presentations
+ """
+ log.debug(u'Kill OpenOffice')
+ 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')
+ else:
+ try:
+ desktop.terminate()
+ log.debug(u'OpenOffice killed')
+ except:
+ log.exception(u'Failed to terminate OpenOffice')
+
+ def add_doc(self, name):
+ """
+ Called when a new Impress document is opened
+ """
+ log.debug(u'Add Doc OpenOffice')
+ doc = ImpressDocument(self, name)
+ self.docs.append(doc)
+ return doc
+
+class ImpressDocument(PresentationDocument):
+ """
+ Class which holds information and controls a single presentation
+ """
+
+ def __init__(self, controller, presentation):
+ """
+ Constructor, store information about the file and initialise
+ """
+ log.debug(u'Init Presentation OpenOffice')
+ PresentationDocument.__init__(self, controller, presentation)
+ self.document = None
+ self.presentation = None
+ self.control = None
+
+ def load_presentation(self):
+ """
+ Called when a presentation is added to the SlideController.
+ It builds the environment, starts communcations with the background
+ OpenOffice task started earlier. If OpenOffice is not present is is
+ started. Once the environment is available the presentation is loaded
+ and started.
+
+ ``presentation``
+ The file name of the presentatios to the run.
+ """
+ log.debug(u'Load Presentation OpenOffice')
+ #print "s.dsk1 ", self.desktop
+ if os.name == u'nt':
+ desktop = self.controller.get_com_desktop()
+ if desktop is None:
+ self.controller.start_process()
+ desktop = self.controller.get_com_desktop()
+ url = u'file:///' + self.filepath.replace(u'\\', u'/').replace(
+ u':', u'|').replace(u' ', u'%20')
+ else:
+ desktop = self.controller.get_uno_desktop()
+ url = uno.systemPathToFileUrl(self.filepath)
+ if desktop is None:
+ return False
+ self.desktop = desktop
+ properties = []
+ properties.append(self.create_property(u'Minimized', True))
+ properties = tuple(properties)
+ try:
+ self.document = desktop.loadComponentFromURL(url, u'_blank',
+ 0, properties)
+ except:
+ log.exception(u'Failed to load presentation')
+ return False
+ self.presentation = self.document.getPresentation()
+ self.presentation.Display = \
+ self.controller.plugin.renderManager.screens.current_display + 1
+ self.control = None
+ self.create_thumbnails()
+ return True
+
+ def create_thumbnails(self):
+ """
+ Create thumbnail images for presentation
+ """
+ log.debug(u'create thumbnails OpenOffice')
+ if self.check_thumbnails():
+ return
+ if os.name == u'nt':
+ thumbdirurl = u'file:///' + self.get_temp_folder().replace(
+ u'\\', u'/').replace(u':', u'|').replace(u' ', u'%20')
+ else:
+ thumbdirurl = uno.systemPathToFileUrl(self.get_temp_folder())
+ props = []
+ props.append(self.create_property(u'FilterName', u'impress_png_Export'))
+ props = tuple(props)
+ doc = self.document
+ pages = doc.getDrawPages()
+ if not os.path.isdir(self.get_temp_folder()):
+ os.makedirs(self.get_temp_folder())
+ for idx in range(pages.getCount()):
+ page = pages.getByIndex(idx)
+ doc.getCurrentController().setCurrentPage(page)
+ urlpath = u'%s/%s.png' % (thumbdirurl, unicode(idx + 1))
+ path = os.path.join(self.get_temp_folder(),
+ unicode(idx + 1) + u'.png')
+ try:
+ doc.storeToURL(urlpath, props)
+ self.convert_thumbnail(path, idx + 1)
+ if os.path.exists(path):
+ os.remove(path)
+ except:
+ log.exception(u'%s - Unable to store openoffice preview' % path)
+
+ def create_property(self, name, value):
+ """
+ Create an OOo style property object which are passed into some
+ Uno methods
+ """
+ log.debug(u'create property OpenOffice')
+ if os.name == u'nt':
+ prop = self.controller.manager.\
+ Bridge_GetStruct(u'com.sun.star.beans.PropertyValue')
+ else:
+ prop = PropertyValue()
+ prop.Name = name
+ prop.Value = value
+ return prop
+
+ def close_presentation(self):
+ """
+ Close presentation and clean up objects
+ Triggered by new object being added to SlideController or OpenLP
+ being shutdown
+ """
+ log.debug(u'close Presentation OpenOffice')
+ if self.document:
+ if self.presentation:
+ try:
+ self.presentation.end()
+ self.presentation = None
+ self.document.dispose()
+ except:
+ #We tried!
+ pass
+ self.document = None
+ self.controller.remove_doc(self)
+
+ def is_loaded(self):
+ """
+ Returns true if a presentation is loaded
+ """
+ log.debug(u'is loaded OpenOffice')
+ #print "is_loaded "
+ if self.presentation is None or self.document is None:
+ #print "no present or document"
+ return False
+ try:
+ if self.document.getPresentation() is None:
+ #print "no getPresentation"
+ return False
+ except:
+ return False
+ return True
+
+ def is_active(self):
+ """
+ Returns true if a presentation is active and running
+ """
+ log.debug(u'is active OpenOffice')
+ #print "is_active "
+ if not self.is_loaded():
+ #print "False "
+ return False
+ #print "self.con ", self.control
+ if self.control is None:
+ return False
+ return True
+
+ def unblank_screen(self):
+ """
+ Unblanks the screen
+ """
+ log.debug(u'unblank screen OpenOffice')
+ return self.control.resume()
+
+ def blank_screen(self):
+ """
+ Blanks the screen
+ """
+ log.debug(u'blank screen OpenOffice')
+ self.control.blankScreen(0)
+
+ def is_blank(self):
+ """
+ Returns true if screen is blank
+ """
+ log.debug(u'is blank OpenOffice')
+ if self.control:
+ return self.control.isPaused()
+ else:
+ return False
+
+ def stop_presentation(self):
+ """
+ Stop the presentation, remove from screen
+ """
+ log.debug(u'stop presentation OpenOffice')
+ # deactivate should hide the screen according to docs, but doesn't
+ #self.control.deactivate()
+ self.presentation.end()
+ self.control = None
+
+ def start_presentation(self):
+ """
+ Start the presentation from the beginning
+ """
+ log.debug(u'start presentation OpenOffice')
+ if self.control is None or not self.control.isRunning():
+ self.presentation.start()
+ # start() returns before the getCurrentComponent is ready.
+ # Try for 5 seconds
+ i = 1
+ while self.desktop.getCurrentComponent() is None and i < 50:
+ time.sleep(0.1)
+ i = i + 1
+ self.control = \
+ self.desktop.getCurrentComponent().Presentation.getController()
+ else:
+ self.control.activate()
+ self.goto_slide(1)
+
+ def get_slide_number(self):
+ """
+ Return the current slide number on the screen, from 1
+ """
+ return self.control.getCurrentSlideIndex() + 1
+
+ def get_slide_count(self):
+ """
+ Return the total number of slides
+ """
+ return self.document.getDrawPages().getCount()
+
+ def goto_slide(self, slideno):
+ """
+ Go to a specific slide (from 1)
+ """
+ self.control.gotoSlideIndex(slideno-1)
+
+ def next_step(self):
+ """
+ Triggers the next effect of slide on the running presentation
+ """
+ self.control.gotoNextEffect()
+
+ def previous_step(self):
+ """
+ Triggers the previous slide on the running presentation
+ """
+ self.control.gotoPreviousSlide()
+
+ def get_slide_text(self, slide_no):
+ """
+ Returns the text on the slide
+
+ ``slide_no``
+ The slide the text is required for, starting at 1
+ """
+ doc = self.document
+ pages = doc.getDrawPages()
+ text = ''
+ page = pages.getByIndex(slide_no - 1)
+ for idx in range(page.getCount()):
+ shape = page.getByIndex(idx)
+ 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
+
+ ``slide_no``
+ The slide the notes are required for, starting at 1
+ """
+ doc = self.document
+ pages = doc.getDrawPages()
+ text = ''
+ page = pages.getByIndex(slide_no - 1)
+ notes = page.getNotesPage()
+ for idx in range(notes.getCount()):
+ shape = notes.getByIndex(idx)
+ if shape.supportsService("com.sun.star.drawing.Text"):
+ text += shape.getString() + '\n'
+ return text
+
=== modified file 'openlp/plugins/presentations/lib/mediaitem.py'
--- openlp/plugins/presentations/lib/mediaitem.py 2010-07-08 09:14:00 +0000
+++ openlp/plugins/presentations/lib/mediaitem.py 2010-07-11 20:27:44 +0000
@@ -35,9 +35,13 @@
log = logging.getLogger(__name__)
-# We have to explicitly create separate classes for each plugin
-# in order for DnD to the Service manager to work correctly.
class PresentationListView(BaseListWithDnD):
+ """
+ Class for the list of Presentations
+
+ We have to explicitly create separate classes for each plugin
+ in order for DnD to the Service manager to work correctly.
+ """
def __init__(self, parent=None):
self.PluginName = u'Presentations'
BaseListWithDnD.__init__(self, parent)
@@ -45,11 +49,14 @@
class PresentationMediaItem(MediaManagerItem):
"""
This is the Presentation media manager item for Presentation Items.
- It can present files using Openoffice
+ It can present files using Openoffice and Powerpoint
"""
log.info(u'Presentations Media Item loaded')
def __init__(self, parent, icon, title, controllers):
+ """
+ Constructor. Setup defaults
+ """
self.controllers = controllers
self.PluginNameShort = u'Presentation'
self.pluginNameVisible = translate('PresentationPlugin.MediaItem',
@@ -63,6 +70,9 @@
self.message_listener = MessageListener(self)
def retranslateUi(self):
+ """
+ The name of the plugin media displayed in UI
+ """
self.OnNewPrompt = translate('PresentationPlugin.MediaItem',
'Select Presentation(s)')
self.Automatic = translate('PresentationPlugin.MediaItem',
@@ -80,12 +90,18 @@
'Presentations (%s)' % fileType)
def requiredIcons(self):
+ """
+ Set which icons the media manager tab should show
+ """
MediaManagerItem.requiredIcons(self)
self.hasFileIcon = True
self.hasNewIcon = False
self.hasEditIcon = False
def addEndHeaderBar(self):
+ """
+ Display custom media manager items for presentations
+ """
self.PresentationWidget = QtGui.QWidget(self)
sizePolicy = QtGui.QSizePolicy(
QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
@@ -109,15 +125,13 @@
self.pageLayout.addWidget(self.PresentationWidget)
def initialise(self):
- self.servicePath = os.path.join(
- AppLocation.get_section_data_path(self.settingsSection),
- u'thumbnails')
+ """
+ Populate the media manager tab
+ """
self.listView.setIconSize(QtCore.QSize(88, 50))
- if not os.path.exists(self.servicePath):
- os.mkdir(self.servicePath)
list = SettingsManager.load_list(
self.settingsSection, u'presentations')
- self.loadList(list)
+ self.loadList(list, True)
for item in self.controllers:
#load the drop down selection
if self.controllers[item].enabled:
@@ -126,7 +140,12 @@
self.DisplayTypeComboBox.insertItem(0, self.Automatic)
self.DisplayTypeComboBox.setCurrentIndex(0)
- def loadList(self, list):
+ def loadList(self, list, initialLoad=False):
+ """
+ Add presentations into the media manager
+ This is called both on initial load of the plugin to populate with
+ existing files, and when the user adds new files via the media manager
+ """
currlist = self.getFileList()
titles = []
for file in currlist:
@@ -136,40 +155,43 @@
continue
filename = os.path.split(unicode(file))[1]
if titles.count(filename) > 0:
- QtGui.QMessageBox.critical(
- self, translate('PresentationPlugin.MediaItem',
- 'File exists'),
+ if not initialLoad:
+ QtGui.QMessageBox.critical(
+ self, translate('PresentationPlugin.MediaItem',
+ 'File exists'),
translate('PresentationPlugin.MediaItem',
'A presentation with that filename already exists.'),
- QtGui.QMessageBox.Ok)
+ QtGui.QMessageBox.Ok)
+ continue
+ controller_name = self.findControllerByType(filename)
+ if controller_name:
+ controller = self.controllers[controller_name]
+ doc = controller.add_doc(unicode(file))
+ thumb = os.path.join(doc.get_thumbnail_folder(), u'icon.png')
+ preview = doc.get_thumbnail_path(1, True)
+ if not preview and not initialLoad:
+ doc.load_presentation()
+ preview = doc.get_thumbnail_path(1, True)
+ doc.close_presentation()
+ if preview and self.validate(preview, thumb):
+ icon = build_icon(thumb)
+ else:
+ icon = build_icon(u':/general/general_delete.png')
else:
- icon = None
- for controller in self.controllers:
- thumbPath = os.path.join(
- AppLocation.get_section_data_path(
- self.settingsSection),
- u'thumbnails', controller, filename)
- thumb = os.path.join(thumbPath, u'slide1.png')
- preview = os.path.join(
- AppLocation.get_section_data_path(
- self.settingsSection),
- controller, u'thumbnails', filename, u'slide1.png')
- if os.path.exists(preview):
- if os.path.exists(thumb):
- if self.validate(preview, thumb):
- icon = build_icon(thumb)
- else:
- icon = build_icon(
- u':/general/general_delete.png')
- else:
- os.makedirs(thumbPath)
- icon = self.iconFromFile(preview, thumb)
- if not icon:
+ if initialLoad:
icon = build_icon(u':/general/general_delete.png')
- item_name = QtGui.QListWidgetItem(filename)
- item_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(file))
- item_name.setIcon(icon)
- self.listView.addItem(item_name)
+ else:
+ QtGui.QMessageBox.critical(
+ self, translate('PresentationPlugin.MediaItem',
+ 'Unsupported file'),
+ translate('PresentationPlugin.MediaItem',
+ 'This type of presentation is not supported'),
+ QtGui.QMessageBox.Ok)
+ continue
+ item_name = QtGui.QListWidgetItem(filename)
+ item_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(file))
+ item_name.setIcon(icon)
+ self.listView.addItem(item_name)
def onDeleteClick(self):
"""
@@ -184,8 +206,6 @@
for item in items:
filepath = unicode(item.data(
QtCore.Qt.UserRole).toString())
- #not sure of this has errors
- #John please can you look at .
for cidx in self.controllers:
doc = self.controllers[cidx].add_doc(filepath)
doc.presentation_deleted()
@@ -196,6 +216,11 @@
self.settingsSection, self.getFileList())
def generateSlideData(self, service_item, item=None):
+ """
+ Load the relevant information for displaying the presentation
+ in the slidecontroller. In the case of powerpoints, an image
+ for each slide
+ """
items = self.listView.selectedIndexes()
if len(items) > 1:
return False
@@ -213,20 +238,27 @@
controller = self.controllers[service_item.shortname]
(path, name) = os.path.split(filename)
doc = controller.add_doc(filename)
- if doc.get_slide_preview_file(1) is None:
+ if doc.get_thumbnail_path(1, True) is None:
doc.load_presentation()
i = 1
- img = doc.get_slide_preview_file(i)
+ img = doc.get_thumbnail_path(i, True)
while img:
service_item.add_from_command(path, name, img)
i = i + 1
- img = doc.get_slide_preview_file(i)
+ img = doc.get_thumbnail_path(i, True)
doc.close_presentation()
return True
else:
return False
def findControllerByType(self, filename):
+ """
+ Determine the default application controller to use for the selected
+ file type. This is used if "Automatic" is set as the preferred
+ controller. Find the first (alphabetic) enabled controller which
+ "supports" the extension. If none found, then look for a controller
+ which "alsosupports" it instead.
+ """
filetype = os.path.splitext(filename)[1]
if not filetype:
return None
=== modified file 'openlp/plugins/presentations/lib/messagelistener.py'
--- openlp/plugins/presentations/lib/messagelistener.py 2010-06-25 20:20:03 +0000
+++ openlp/plugins/presentations/lib/messagelistener.py 2010-07-11 20:27:44 +0000
@@ -41,17 +41,28 @@
log.info(u'Controller loaded')
def __init__(self, live):
+ """
+ Constructor
+ """
self.is_live = live
self.doc = None
log.info(u'%s controller loaded' % live)
def add_handler(self, controller, file, is_blank):
+ """
+ Add a handler, which is an instance of a presentation and
+ slidecontroller combination. If the slidecontroller has a display
+ then load the presentation.
+ """
log.debug(u'Live = %s, add_handler %s' % (self.is_live, file))
self.controller = controller
if self.doc is not None:
self.shutdown()
self.doc = self.controller.add_doc(file)
- self.doc.load_presentation()
+ if not self.doc.load_presentation():
+ # Display error message to user
+ # Inform slidecontroller that the action failed?
+ return
if self.is_live:
self.doc.start_presentation()
if is_blank:
@@ -60,6 +71,10 @@
self.doc.slidenumber = 0
def activate(self):
+ """
+ Active the presentation, and show it on the screen.
+ Use the last slide number.
+ """
log.debug(u'Live = %s, activate' % self.is_live)
if self.doc.is_active():
return
@@ -71,6 +86,9 @@
self.doc.goto_slide(self.doc.slidenumber)
def slide(self, slide):
+ """
+ Go to a specific slide
+ """
log.debug(u'Live = %s, slide' % self.is_live)
if not self.is_live:
return
@@ -152,6 +170,9 @@
#self.timer.stop()
def blank(self):
+ """
+ Instruct the controller to blank the presentation
+ """
log.debug(u'Live = %s, blank' % self.is_live)
if not self.is_live:
return
@@ -162,6 +183,9 @@
self.doc.blank_screen()
def stop(self):
+ """
+ Instruct the controller to stop and hide the presentation
+ """
log.debug(u'Live = %s, stop' % self.is_live)
if not self.is_live:
return
@@ -172,6 +196,9 @@
self.doc.stop_presentation()
def unblank(self):
+ """
+ Instruct the controller to unblank the presentation
+ """
log.debug(u'Live = %s, unblank' % self.is_live)
if not self.is_live:
return
@@ -246,6 +273,9 @@
controller.add_handler(self.controllers[self.handler], file, is_blank)
def slide(self, message):
+ """
+ React to the message to move to a specific slide
+ """
is_live = message[1]
slide = message[2]
if is_live:
@@ -254,6 +284,9 @@
self.preview_handler.slide(slide)
def first(self, message):
+ """
+ React to the message to move to the first slide
+ """
is_live = message[1]
if is_live:
self.live_handler.first()
@@ -261,6 +294,9 @@
self.preview_handler.first()
def last(self, message):
+ """
+ React to the message to move to the last slide
+ """
is_live = message[1]
if is_live:
self.live_handler.last()
@@ -268,6 +304,9 @@
self.preview_handler.last()
def next(self, message):
+ """
+ React to the message to move to the next animation/slide
+ """
is_live = message[1]
if is_live:
self.live_handler.next()
@@ -275,6 +314,9 @@
self.preview_handler.next()
def previous(self, message):
+ """
+ React to the message to move to the previous animation/slide
+ """
is_live = message[1]
if is_live:
self.live_handler.previous()
@@ -282,6 +324,10 @@
self.preview_handler.previous()
def shutdown(self, message):
+ """
+ React to message to shutdown the presentation. I.e. end the show
+ and close the file
+ """
is_live = message[1]
if is_live:
Receiver.send_message(u'maindisplay_show')
@@ -290,19 +336,34 @@
self.preview_handler.shutdown()
def hide(self, message):
+ """
+ React to the message to show the desktop
+ """
is_live = message[1]
if is_live:
self.live_handler.stop()
def blank(self, message):
+ """
+ React to the message to blank the display
+ """
is_live = message[1]
if is_live:
self.live_handler.blank()
def unblank(self, message):
+ """
+ React to the message to unblank the display
+ """
is_live = message[1]
if is_live:
self.live_handler.unblank()
def timeout(self):
+ """
+ The presentation may be timed or might be controlled by the
+ application directly, rather than through OpenLP. Poll occassionally
+ to check which slide is currently displayed so the slidecontroller
+ view can be updated
+ """
self.live_handler.poll()
=== modified file 'openlp/plugins/presentations/lib/powerpointcontroller.py'
--- openlp/plugins/presentations/lib/powerpointcontroller.py 2010-07-05 22:17:14 +0000
+++ openlp/plugins/presentations/lib/powerpointcontroller.py 2010-07-11 20:27:44 +0000
@@ -97,13 +97,23 @@
self.process = None
def add_doc(self, name):
+ """
+ Called when a new powerpoint document is opened
+ """
log.debug(u'Add Doc PowerPoint')
doc = PowerpointDocument(self, name)
self.docs.append(doc)
return doc
class PowerpointDocument(PresentationDocument):
+ """
+ Class which holds information and controls a single presentation
+ """
+
def __init__(self, controller, presentation):
+ """
+ Constructor, store information about the file and initialise
+ """
log.debug(u'Init Presentation Powerpoint')
PresentationDocument.__init__(self, controller, presentation)
self.presentation = None
@@ -111,22 +121,23 @@
def load_presentation(self):
"""
Called when a presentation is added to the SlideController.
- It builds the environment, starts communcations with the background
- OpenOffice task started earlier. If OpenOffice is not present is is
- started. Once the environment is available the presentation is loaded
- and started.
+ Opens the PowerPoint file using the process created earlier
``presentation``
The file name of the presentations to run.
"""
log.debug(u'LoadPresentation')
- if not self.controller.process.Visible:
+ if not self.controller.process or not self.controller.process.Visible:
self.controller.start_process()
- self.controller.process.Presentations.Open(self.filepath, False, False,
- True)
+ try:
+ self.controller.process.Presentations.Open(self.filepath, False,
+ False, True)
+ except pywintypes.com_error:
+ return False
self.presentation = self.controller.process.Presentations(
self.controller.process.Presentations.Count)
self.create_thumbnails()
+ return True
def create_thumbnails(self):
"""
@@ -139,8 +150,8 @@
"""
if self.check_thumbnails():
return
- self.presentation.Export(os.path.join(self.thumbnailpath, ''), 'png',
- 320, 240)
+ self.presentation.Export(os.path.join(self.get_thumbnail_folder(), ''),
+ 'png', 320, 240)
def close_presentation(self):
"""
@@ -298,4 +309,4 @@
shape = shapes(idx + 1)
if shape.HasTextFrame:
text += shape.TextFrame.TextRange.Text + '\n'
- return text
\ No newline at end of file
+ return text
=== modified file 'openlp/plugins/presentations/lib/pptviewcontroller.py'
--- openlp/plugins/presentations/lib/pptviewcontroller.py 2010-07-02 22:18:54 +0000
+++ openlp/plugins/presentations/lib/pptviewcontroller.py 2010-07-11 20:27:44 +0000
@@ -93,13 +93,22 @@
self.docs[0].close_presentation()
def add_doc(self, name):
+ """
+ Called when a new powerpoint document is opened
+ """
log.debug(u'Add Doc PPTView')
doc = PptviewDocument(self, name)
self.docs.append(doc)
return doc
class PptviewDocument(PresentationDocument):
+ """
+ Class which holds information and controls a single presentation
+ """
def __init__(self, controller, presentation):
+ """
+ Constructor, store information about the file and initialise
+ """
log.debug(u'Init Presentation PowerPoint')
PresentationDocument.__init__(self, controller, presentation)
self.presentation = None
@@ -117,17 +126,31 @@
The file name of the presentations to run.
"""
log.debug(u'LoadPresentation')
- #if self.pptid >= 0:
- # self.close_presentation()
rendermanager = self.controller.plugin.renderManager
rect = rendermanager.screens.current[u'size']
rect = RECT(rect.x(), rect.y(), rect.right(), rect.bottom())
filepath = str(self.filepath.replace(u'/', u'\\'))
+ if not os.path.isdir(self.get_temp_folder()):
+ os.makedirs(self.get_temp_folder())
self.pptid = self.controller.process.OpenPPT(filepath, None, rect,
- str(os.path.join(self.thumbnailpath,
- self.controller.thumbnailprefix)))
- if self.pptid:
+ str(self.get_temp_folder()) + '\\slide')
+ if self.pptid >= 0:
+ self.create_thumbnails()
self.stop_presentation()
+ return True
+ else:
+ return False
+
+ def create_thumbnails(self):
+ """
+ PPTviewLib creates large BMP's, but we want small PNG's for consistency.
+ Convert them here.
+ """
+ if self.check_thumbnails():
+ return
+ for idx in range(self.get_slide_count()):
+ path = u'%s\\slide%s.bmp' % (self.get_temp_folder(), unicode(idx + 1))
+ self.convert_thumbnail(path, idx + 1)
def close_presentation(self):
"""
@@ -224,17 +247,3 @@
"""
self.controller.process.PrevStep(self.pptid)
- def get_slide_preview_file(self, slide_no):
- """
- Returns an image path containing a preview for the requested slide
-
- ``slide_no``
- The slide an image is required for, starting at 1
- """
- path = os.path.join(self.thumbnailpath,
- self.controller.thumbnailprefix + unicode(slide_no) + u'.bmp')
- if os.path.isfile(path):
- return path
- else:
- return None
-
=== modified file 'openlp/plugins/presentations/lib/presentationcontroller.py'
--- openlp/plugins/presentations/lib/presentationcontroller.py 2010-06-10 13:28:41 +0000
+++ openlp/plugins/presentations/lib/presentationcontroller.py 2010-07-11 20:27:44 +0000
@@ -29,7 +29,7 @@
from PyQt4 import QtCore
-from openlp.core.lib import Receiver
+from openlp.core.lib import Receiver, resize_image
from openlp.core.utils import AppLocation
log = logging.getLogger(__name__)
@@ -63,6 +63,13 @@
``plugin``
The presentationplugin object
+ ``supports``
+ The primary native file types this application supports
+
+ ``alsosupports``
+ Other file types the application can import, although not necessarily
+ the first choice due to potential incompatibilities
+
**Hook Functions**
``kill()``
@@ -109,12 +116,16 @@
QtCore.Qt.Checked
else:
self.enabled = False
- self.thumbnailroot = os.path.join(
+ self.temp_folder = os.path.join(
+ AppLocation.get_section_data_path(self.settings_section), name)
+ self.thumbnail_folder = os.path.join(
AppLocation.get_section_data_path(self.settings_section),
- name, u'thumbnails')
- self.thumbnailprefix = u'slide'
- if not os.path.isdir(self.thumbnailroot):
- os.makedirs(self.thumbnailroot)
+ u'thumbnails')
+ self.thumbnail_prefix = u'slide'
+ if not os.path.isdir(self.thumbnail_folder):
+ os.makedirs(self.thumbnail_folder)
+ if not os.path.isdir(self.temp_folder):
+ os.makedirs(self.temp_folder)
def check_available(self):
"""
@@ -208,14 +219,19 @@
``previous_step()``
Triggers the previous slide on the running presentation
- ``get_slide_preview_file(slide_no)``
+ ``get_thumbnail_path(slide_no, check_exists)``
Returns a path to an image containing a preview for the requested slide
"""
def __init__(self, controller, name):
+ """
+ Constructor for the PresentationController class
+ """
self.slidenumber = 0
self.controller = controller
- self.store_filename(name)
+ self.filepath = name
+ if not os.path.isdir(self.get_thumbnail_folder()):
+ os.mkdir(self.get_thumbnail_folder())
def load_presentation(self):
"""
@@ -224,9 +240,10 @@
``presentation``
The file name of the presentations to the run.
-
+
+ Returns False if the file could not be opened
"""
- pass
+ return False
def presentation_deleted(self):
"""
@@ -234,33 +251,37 @@
a file, e.g. thumbnails
"""
try:
- shutil.rmtree(self.thumbnailpath)
+ shutil.rmtree(self.get_thumbnail_folder())
+ shutil.rmtree(self.get_temp_folder())
except OSError:
log.exception(u'Failed to delete presentation controller files')
- def store_filename(self, presentation):
- """
- Set properties for the filename and thumbnail paths
- """
- self.filepath = presentation
- self.filename = self.get_file_name(presentation)
- self.thumbnailpath = self.get_thumbnail_path(presentation)
- if not os.path.isdir(self.thumbnailpath):
- os.mkdir(self.thumbnailpath)
-
- 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))
+ def get_file_name(self):
+ """
+ Return just the filename of the presention, without the directory
+ """
+ return os.path.split(self.filepath)[1]
+
+ def get_thumbnail_folder(self):
+ """
+ The location where thumbnail images will be stored
+ """
+ return os.path.join(
+ self.controller.thumbnail_folder, self.get_file_name())
+
+ def get_temp_folder(self):
+ """
+ The location where thumbnail images will be stored
+ """
+ return os.path.join(
+ self.controller.temp_folder, self.get_file_name())
def check_thumbnails(self):
"""
Returns true if the thumbnail images look to exist and are more
recent than the powerpoint
"""
- lastimage = self.get_slide_preview_file(self.get_slide_count())
+ lastimage = self.get_thumbnail_path(self.get_slide_count(), True)
if not (lastimage and os.path.isfile(lastimage)):
return False
imgdate = os.stat(lastimage).st_mtime
@@ -350,16 +371,27 @@
"""
pass
- def get_slide_preview_file(self, slide_no):
+ def convert_thumbnail(self, file, idx):
+ """
+ Convert the slide image the application made to a standard 320x240
+ .png image.
+ """
+ if self.check_thumbnails():
+ return
+ if os.path.isfile(file):
+ img = resize_image(file, 320, 240)
+ img.save(self.get_thumbnail_path(idx, False))
+
+ def get_thumbnail_path(self, slide_no, check_exists):
"""
Returns an image path containing a preview for the requested slide
``slide_no``
The slide an image is required for, starting at 1
"""
- path = os.path.join(self.thumbnailpath,
- self.controller.thumbnailprefix + unicode(slide_no) + u'.png')
- if os.path.isfile(path):
+ path = os.path.join(self.get_thumbnail_folder(),
+ self.controller.thumbnail_prefix + unicode(slide_no) + u'.png')
+ if os.path.isfile(path) or not check_exists:
return path
else:
return None
=== modified file 'openlp/plugins/presentations/lib/presentationtab.py'
--- openlp/plugins/presentations/lib/presentationtab.py 2010-06-21 18:28:36 +0000
+++ openlp/plugins/presentations/lib/presentationtab.py 2010-07-11 20:27:44 +0000
@@ -32,10 +32,16 @@
PresentationsTab is the Presentations settings tab in the settings dialog.
"""
def __init__(self, title, controllers):
+ """
+ Constructor
+ """
self.controllers = controllers
SettingsTab.__init__(self, title)
def setupUi(self):
+ """
+ Create the controls for the settings tab
+ """
self.setObjectName(u'PresentationTab')
self.tabTitleVisible = translate('PresentationPlugin.PresentationTab',
'Presentations')
@@ -89,6 +95,9 @@
self.PresentationLayout.addWidget(self.PresentationRightWidget)
def retranslateUi(self):
+ """
+ Make any translation changes
+ """
self.VerseDisplayGroupBox.setTitle(
translate('PresentationPlugin.PresentationTab',
'Available Controllers'))
@@ -100,6 +109,9 @@
translate('PresentationPlugin.PresentationTab', 'available')))
def load(self):
+ """
+ Load the settings.
+ """
for key in self.controllers:
controller = self.controllers[key]
if controller.available:
@@ -109,6 +121,9 @@
QtCore.QVariant(0)).toInt()[0])
def save(self):
+ """
+ Save the settings.
+ """
for key in self.controllers:
controller = self.controllers[key]
checkbox = self.PresenterCheckboxes[controller.name]
=== modified file 'openlp/plugins/presentations/presentationplugin.py'
--- openlp/plugins/presentations/presentationplugin.py 2010-07-10 01:01:14 +0000
+++ openlp/plugins/presentations/presentationplugin.py 2010-07-11 20:27:44 +0000
@@ -33,9 +33,17 @@
log = logging.getLogger(__name__)
class PresentationPlugin(Plugin):
+ """
+ This plugin allowed a Presentation to be opened, controlled and displayed
+ on the output display. The plugin controls third party applications such
+ as OpenOffice.org Impress, Microsoft PowerPoint and the PowerPoint viewer
+ """
log = logging.getLogger(u'PresentationPlugin')
def __init__(self, plugin_helpers):
+ """
+ PluginPresentation constructor.
+ """
log.debug(u'Initialised')
self.controllers = {}
Plugin.__init__(self, u'Presentations', u'1.9.2', plugin_helpers)
@@ -51,6 +59,10 @@
return PresentationTab(self.name, self.controllers)
def initialise(self):
+ """
+ Initialise the plugin. Determine which controllers are enabled
+ are start their processes.
+ """
log.info(u'Presentations Initialising')
Plugin.initialise(self)
self.insertToolboxItem()
@@ -59,6 +71,10 @@
self.controllers[controller].start_process()
def finalise(self):
+ """
+ Finalise the plugin. Ask all the enabled presentation applications
+ to close down their applications and release resources.
+ """
log.info(u'Plugin Finalise')
#Ask each controller to tidy up
for key in self.controllers:
@@ -75,6 +91,10 @@
self, self.icon, self.name, self.controllers)
def registerControllers(self, controller):
+ """
+ Register each presentation controller (Impress, PPT etc) and
+ store for later use
+ """
self.controllers[controller.name] = controller
def checkPreConditions(self):
@@ -109,9 +129,12 @@
return False
def about(self):
+ """
+ Return information about this plugin
+ """
about_text = translate('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.')
- return about_text
\ No newline at end of file
+ return about_text
Follow ups