← Back to team overview

openlp-core team mailing list archive

[Merge] lp:~j-corwin/openlp/present into lp:openlp

 

Jonathan Corwin has proposed merging lp:~j-corwin/openlp/present into lp:openlp.

Requested reviews:
  Tim Bentley (trb143)
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/29660
Your team OpenLP Core is subscribed to branch 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:55:56 +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:55:56 +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:55:56 +0000
@@ -74,6 +74,7 @@
         self.alsosupports = [u'.ppt', u'.pps', u'.pptx', u'.ppsx']
         self.process = None
         self.desktop = None
+        self.manager = None
 
     def check_available(self):
         """
@@ -104,6 +105,10 @@
             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
@@ -134,10 +139,19 @@
             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')
@@ -171,13 +185,23 @@
                 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
@@ -208,9 +232,8 @@
             desktop = self.controller.get_uno_desktop()
             url = uno.systemPathToFileUrl(self.filepath)
         if desktop is None:
-            return
+            return False
         self.desktop = desktop
-        #print "s.dsk2 ", self.desktop
         properties = []
         properties.append(self.create_property(u'Minimized', True))
         properties = tuple(properties)
@@ -219,12 +242,13 @@
                 0, properties)
         except:
             log.exception(u'Failed to load presentation')
-            return
+            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):
         """
@@ -234,30 +258,36 @@
         if self.check_thumbnails():
             return
         if os.name == u'nt':
-            thumbdir = u'file:///' + self.thumbnailpath.replace(
+            thumbdirurl = u'file:///' + self.get_temp_folder().replace(
                 u'\\', u'/').replace(u':', u'|').replace(u' ', u'%20')
         else:
-            thumbdir = uno.systemPathToFileUrl(self.thumbnailpath)
+            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)
-            path = u'%s/%s%s.png' % (thumbdir, self.controller.thumbnailprefix,
-                    unicode(idx + 1))
+            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(path , props)
-                preview = resize_image(path, 640, 480)
+                doc.storeToURL(urlpath, props)
+                self.convert_thumbnail(path, idx + 1)
                 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):
+        """
+        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.\
@@ -288,6 +318,9 @@
         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:
@@ -302,6 +335,9 @@
         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():
@@ -313,10 +349,16 @@
         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)
 
@@ -331,6 +373,9 @@
             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()
@@ -338,6 +383,9 @@
         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()
@@ -354,12 +402,21 @@
             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):

=== 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:55:56 +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:55:56 +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:55:56 +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:55:56 +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:55:56 +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:55:56 +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:55:56 +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,13 @@
             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