← 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:
    OpenLP Core (openlp-core)


Allow Live and Preview presentations to act independently.
-- 
https://code.launchpad.net/~j-corwin/openlp/present/+merge/20499
Your team OpenLP Core is subscribed to branch lp:openlp.
=== modified file 'openlp/plugins/presentations/lib/impresscontroller.py'
--- openlp/plugins/presentations/lib/impresscontroller.py	2010-02-17 22:57:59 +0000
+++ openlp/plugins/presentations/lib/impresscontroller.py	2010-03-02 23:20:28 +0000
@@ -44,7 +44,7 @@
 
 from PyQt4 import QtCore
 
-from presentationcontroller import PresentationController
+from presentationcontroller import PresentationController,  PresentationDocument
 
 class ImpressController(PresentationController):
     """
@@ -62,11 +62,8 @@
         """
         log.debug(u'Initialising')
         PresentationController.__init__(self, plugin, u'Impress')
-        self.supports= [u'.odp', u'.ppt', u'.pps', u'.pptx', u'.ppsx']
+        self.supports = [u'.odp', u'.ppt', u'.pps', u'.pptx', u'.ppsx']
         self.process = None
-        self.document = None
-        self.presentation = None
-        self.controller = None
         self.desktop = None
 
     def check_available(self):
@@ -99,12 +96,53 @@
             self.process.startDetached(cmd)
             self.process.waitForStarted()
 
+    def get_uno_desktop(self):
+        log.debug(u'get UNO Desktop Openoffice')
+        ctx = None
+        loop = 0
+        context = uno.getComponentContext()
+        resolver = context.ServiceManager.createInstanceWithContext(
+            u'com.sun.star.bridge.UnoUrlResolver', context)
+        while ctx is None and loop < 3:
+            try:
+                ctx = resolver.resolve(u'uno:socket,host=localhost,port=2002;urp;StarOffice.ComponentContext')
+            except:
+                log.exception(u'Unable to find running instance ')
+                self.start_process()
+                loop += 1
+        try:
+            self.manager = ctx.ServiceManager
+            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')
+        try:
+            desktop = self.manager.createInstance(u'com.sun.star.frame.Desktop')
+            return desktop
+        except:
+            log.exception(u'Failed to get COM desktop')
+        return None
+
+    def get_com_servicemanager(self):
+        log.debug(u'get_com_servicemanager openoffice')
+        try:
+            return Dispatch(u'com.sun.star.ServiceManager')
+        except:
+            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')
-        self.close_presentation()
+        for doc in self.docs:
+            doc.close_presentation()
         if os.name != u'nt':
             desktop = self.get_uno_desktop()
             try:
@@ -112,7 +150,23 @@
             except:
                 pass
 
-    def load_presentation(self, presentation):
+    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')
+        self.controller = controller
+        self.document = None
+        self.presentation = None
+        self.control = None
+        self.store_filename(presentation)
+        
+    def load_presentation(self):
         """
         Called when a presentation is added to the SlideController.
         It builds the environment, starts communcations with the background
@@ -124,17 +178,16 @@
         The file name of the presentatios to the run.
         """
         log.debug(u'Load Presentation OpenOffice')
-        self.store_filename(presentation)
         #print "s.dsk1 ", self.desktop
         if os.name == u'nt':
-            desktop = self.get_com_desktop()
+            desktop = self.controller.get_com_desktop()
             if desktop is None:
-                self.start_process()
-                desktop = self.get_com_desktop()
-            url = u'file:///' + presentation.replace(u'\\', u'/').replace(u':', u'|').replace(u' ', u'%20')
+                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.get_uno_desktop()
-            url = uno.systemPathToFileUrl(presentation)
+            desktop = self.controller.get_uno_desktop()
+            url = uno.systemPathToFileUrl(self.filepath)
         if desktop is None:
             return
         self.desktop = desktop
@@ -149,8 +202,8 @@
             log.exception(u'Failed to load presentation')
             return
         self.presentation = self.document.getPresentation()
-        self.presentation.Display = self.plugin.render_manager.screens.current_display + 1
-        self.controller = None
+        self.presentation.Display = self.controller.plugin.render_manager.screens.current_display + 1
+        self.control = None
         self.create_thumbnails()
 
     def create_thumbnails(self):
@@ -173,7 +226,7 @@
         for idx in range(pages.getCount()):
             page = pages.getByIndex(idx)
             doc.getCurrentController().setCurrentPage(page)
-            path = u'%s/%s%s.png'% (thumbdir, self.thumbnailprefix,
+            path = u'%s/%s%s.png'% (thumbdir, self.controller.thumbnailprefix,
                     unicode(idx + 1))
             try:
                 doc.storeToURL(path , props)
@@ -183,53 +236,13 @@
     def create_property(self, name, value):
         log.debug(u'create property OpenOffice')
         if os.name == u'nt':
-            prop = self.manager.Bridge_GetStruct(u'com.sun.star.beans.PropertyValue')
+            prop = self.controller.manager.Bridge_GetStruct(u'com.sun.star.beans.PropertyValue')
         else:
             prop = PropertyValue()
         prop.Name = name
         prop.Value = value
         return prop
 
-    def get_uno_desktop(self):
-        log.debug(u'get UNO Desktop Openoffice')
-        ctx = None
-        loop = 0
-        context = uno.getComponentContext()
-        resolver = context.ServiceManager.createInstanceWithContext(
-            u'com.sun.star.bridge.UnoUrlResolver', context)
-        while ctx is None and loop < 3:
-            try:
-                ctx = resolver.resolve(u'uno:socket,host=localhost,port=2002;urp;StarOffice.ComponentContext')
-            except:
-                log.exception(u'Unable to find running instance ')
-                self.start_process()
-                loop += 1
-        try:
-            self.manager = ctx.ServiceManager
-            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')
-        try:
-            desktop = self.manager.createInstance(u'com.sun.star.frame.Desktop')
-            return desktop
-        except:
-            log.exception(u'Failed to get COM desktop')
-        return None
-
-    def get_com_servicemanager(self):
-        log.debug(u'get_com_servicemanager openoffice')
-        try:
-            return Dispatch(u'com.sun.star.ServiceManager')
-        except:
-            log.exception(u'Failed to get COM service manager')
-            return None
-
     def close_presentation(self):
         """
         Close presentation and clean up objects
@@ -247,6 +260,7 @@
                     #We tried!
                     pass
             self.document = None
+        self.controller.remove_doc(self)
 
     def is_loaded(self):
         log.debug(u'is loaded OpenOffice')
@@ -268,57 +282,57 @@
         if not self.is_loaded():
             #print "False "
             return False
-        #print "self.con ", self.controller
-        if self.controller is None:
+        #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.controller.resume()
+        return self.control.resume()
 
     def blank_screen(self):
         log.debug(u'blank screen OpenOffice')
-        self.controller.blankScreen(0)
+        self.control.blankScreen(0)
 
     def stop_presentation(self):
         log.debug(u'stop presentation OpenOffice')
-        self.controller.deactivate()
+        self.control.deactivate()
 
     def start_presentation(self):
         log.debug(u'start presentation OpenOffice')
-        if self.controller is None or not self.controller.isRunning():
+        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.controller = self.desktop.getCurrentComponent().Presentation.getController()
+            self.control = self.desktop.getCurrentComponent().Presentation.getController()
         else:
-            self.controller.activate()
+            self.control.activate()
             self.goto_slide(1)
 
     def get_slide_number(self):
-        return self.controller.getCurrentSlideIndex() + 1
+        return self.control.getCurrentSlideIndex() + 1
 
     def get_slide_count(self):
         return self.document.getDrawPages().getCount()
 
     def goto_slide(self, slideno):
-        self.controller.gotoSlideIndex(slideno-1)
+        self.control.gotoSlideIndex(slideno-1)
 
     def next_step(self):
        """
        Triggers the next effect of slide on the running presentation
        """
-       self.controller.gotoNextEffect()
+       self.control.gotoNextEffect()
 
     def previous_step(self):
         """
         Triggers the previous slide on the running presentation
         """
-        self.controller.gotoPreviousSlide()
+        self.control.gotoPreviousSlide()
 
     def get_slide_preview_file(self, slide_no):
         """
@@ -328,7 +342,7 @@
         The slide an image is required for, starting at 1
         """
         path = os.path.join(self.thumbnailpath,
-            self.thumbnailprefix + unicode(slide_no) + u'.png')
+            self.controller.thumbnailprefix + unicode(slide_no) + u'.png')
         if os.path.isfile(path):
             return path
         else:

=== modified file 'openlp/plugins/presentations/lib/mediaitem.py'
--- openlp/plugins/presentations/lib/mediaitem.py	2010-02-09 11:20:19 +0000
+++ openlp/plugins/presentations/lib/mediaitem.py	2010-03-02 23:20:28 +0000
@@ -135,7 +135,9 @@
                 self.ConfigSection, self.getFileList())
             filepath = unicode((item.data(QtCore.Qt.UserRole)).toString())
             for cidx in self.controllers:
-                self.controllers[cidx].presentation_deleted(filepath)
+                doc = self.controllers[cidx].add_doc(filepath)
+                doc.presentation_deleted()
+                self.controllers[cidx].remove_doc(doc)
 
     def generateSlideData(self, service_item):
         items = self.ListView.selectedIndexes()
@@ -148,13 +150,14 @@
             bitem = self.ListView.item(item.row())
             filename = unicode((bitem.data(QtCore.Qt.UserRole)).toString())
             (path, name) = os.path.split(filename)
-            controller.store_filename(filename)
-            if controller.get_slide_preview_file(1) is None:
-                controller.load_presentation(filename)
+            doc = controller.add_doc(filename)
+            if doc.get_slide_preview_file(1) is None:
+                doc.load_presentation()
             i = 1
-            img = controller.get_slide_preview_file(i)
+            img = doc.get_slide_preview_file(i)
             while img:
                 service_item.add_from_command(path, name, img)
                 i = i + 1
-                img = controller.get_slide_preview_file(i)
+                img = doc.get_slide_preview_file(i)
+        controller.remove_doc(doc)
         return True

=== modified file 'openlp/plugins/presentations/lib/messagelistener.py'
--- openlp/plugins/presentations/lib/messagelistener.py	2010-02-17 22:57:59 +0000
+++ openlp/plugins/presentations/lib/messagelistener.py	2010-03-02 23:20:29 +0000
@@ -41,37 +41,39 @@
 
     def __init__(self, live):
         self.isLive = live
+        self.doc = None
         log.info(u'%s controller loaded' % live)
 
     def addHandler(self, controller, file):
         log.debug(u'Live = %s, addHandler %s' % (self.isLive, file))
         self.controller = controller
-        if self.controller.is_loaded():
+        if self.doc is not None:
             self.shutdown()
-        self.controller.load_presentation(file)
+        self.doc = self.controller.add_doc(file)
+        self.doc.load_presentation()
         if self.isLive:
-            self.controller.start_presentation()
+            self.doc.start_presentation()
             Receiver.send_message(u'live_slide_hide')
-        self.controller.slidenumber = 0
+        self.doc.slidenumber = 0
 
     def activate(self):
         log.debug(u'Live = %s, activate' % self.isLive)
-        if self.controller.is_active():
+        if self.doc.is_active():
             return
-        if not self.controller.is_loaded():
-            self.controller.load_presentation(self.controller.filepath)
+        if not self.doc.is_loaded():
+            self.doc.load_presentation()
         if self.isLive:
-            self.controller.start_presentation()
-            if self.controller.slidenumber > 1:
-                self.controller.goto_slide(self.controller.slidenumber)
+            self.doc.start_presentation()
+            if self.doc.slidenumber > 1:
+                self.doc.goto_slide(self.doc.slidenumber)
 
     def slide(self, slide, live):
         log.debug(u'Live = %s, slide' % live)
         if not live:
             return
         self.activate()
-        self.controller.goto_slide(int(slide) + 1)
-        self.controller.poll_slidenumber(live)
+        self.doc.goto_slide(int(slide) + 1)
+        self.doc.poll_slidenumber(live)
 
     def first(self):
         """
@@ -81,8 +83,8 @@
         if not self.isLive:
             return
         self.activate()
-        self.controller.start_presentation()
-        self.controller.poll_slidenumber(self.isLive)
+        self.doc.start_presentation()
+        self.doc.poll_slidenumber(self.isLive)
 
     def last(self):
         """
@@ -92,8 +94,8 @@
         if not self.isLive:
             return
         self.activate()
-        self.controller.goto_slide(self.controller.get_slide_count())
-        self.controller.poll_slidenumber(self.isLive)
+        self.doc.goto_slide(self.doc.get_slide_count())
+        self.doc.poll_slidenumber(self.isLive)
 
     def next(self):
         """
@@ -103,8 +105,8 @@
         if not self.isLive:
             return
         self.activate()
-        self.controller.next_step()
-        self.controller.poll_slidenumber(self.isLive)
+        self.doc.next_step()
+        self.doc.poll_slidenumber(self.isLive)
 
     def previous(self):
         """
@@ -114,35 +116,36 @@
         if not self.isLive:
             return
         self.activate()
-        self.controller.previous_step()
-        self.controller.poll_slidenumber(self.isLive)
+        self.doc.previous_step()
+        self.doc.poll_slidenumber(self.isLive)
 
     def shutdown(self):
         """
         Based on the handler passed at startup triggers slide show to shut down
         """
         log.debug(u'Live = %s, shutdown' % self.isLive)
-        self.controller.close_presentation()
-        self.controller.slidenumber = 0
+        self.doc.close_presentation()
+        self.doc = None
+        #self.doc.slidenumber = 0
         #self.timer.stop()
 
     def blank(self):
         if not self.isLive:
             return
-        if not self.controller.is_loaded():
-            return
-        if not self.controller.is_active():
-            return
-        self.controller.blank_screen()
+        if not self.doc.is_loaded():
+            return
+        if not self.doc.is_active():
+            return
+        self.doc.blank_screen()
 
     def unblank(self):
         if not self.isLive:
             return
         self.activate()
-        self.controller.unblank_screen()
+        self.doc.unblank_screen()
 
     def poll(self):
-        self.controller.poll_slidenumber(self.isLive)
+        self.doc.poll_slidenumber(self.isLive)
 
 class MessageListener(object):
     """

=== modified file 'openlp/plugins/presentations/lib/powerpointcontroller.py'
--- openlp/plugins/presentations/lib/powerpointcontroller.py	2010-02-16 22:28:35 +0000
+++ openlp/plugins/presentations/lib/powerpointcontroller.py	2010-03-02 23:20:29 +0000
@@ -31,7 +31,7 @@
     import _winreg
     import win32ui
 
-from presentationcontroller import PresentationController
+from presentationcontroller import PresentationController,  PresentationDocument
 
 # PPT API documentation:
 # http://msdn.microsoft.com/en-us/library/aa269321(office.10).aspx
@@ -52,9 +52,8 @@
         """
         log.debug(u'Initialising')
         PresentationController.__init__(self, plugin, u'Powerpoint')
-        self.supports= [u'.ppt', u'.pps']
+        self.supports = [u'.ppt', u'.pps']
         self.process = None
-        self.presentation = None
 
     def check_available(self):
         """
@@ -97,6 +96,8 @@
             """
             Called at system exit to clean up any running presentations
             """
+            for doc in self.docs:
+                doc.close_presentation()
             if self.process is None:
                 return
             try:
@@ -105,94 +106,110 @@
                 pass
             self.process = None
 
-        def load_presentation(self, presentation):
-            """
-            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 presentations to run.
-            """
-            log.debug(u'LoadPresentation')
-            self.store_filename(presentation)
-            try:
-                if not self.process.Visible:
-                    self.start_process()
-            except:
-                self.start_process()
-            try:
-                self.process.Presentations.Open(presentation, False, False, True)
-            except:
-                return
-            self.presentation = self.process.Presentations(self.process.Presentations.Count)
-            self.create_thumbnails()
-
-        def create_thumbnails(self):
-            """
-            Create the thumbnail images for the current presentation.
-            Note an alternative and quicker method would be do
-                self.presentation.Slides[n].Copy()
-                thumbnail = QApplication.clipboard.image()
-            But for now we want a physical file since it makes
-            life easier elsewhere
-            """
-            if self.check_thumbnails():
-                return
-            self.presentation.Export(os.path.join(self.thumbnailpath, '')
-                                     , 'png', 600, 480)
-
-        def close_presentation(self):
-            """
-            Close presentation and clean up objects
-            Triggerent by new object being added to SlideController orOpenLP
-            being shut down
-            """
-            if self.presentation == None:
-                return
-            try:
-                self.presentation.Close()
-            except:
-                pass
-            self.presentation = None
-
-        def is_active(self):
-            """
-            Returns true if a presentation is currently active
-            """
-            if not self.is_loaded():
-                return False
-            try:
-                if self.presentation.SlideShowWindow == None:
-                    return False
-                if self.presentation.SlideShowWindow.View == None:
-                    return False
-            except:
-                return False
-            return True
-
-        def unblank_screen(self):
-            """
-            Unblanks (restores) the presentationn
-            """
-            self.presentation.SlideShowSettings.Run()
-            self.presentation.SlideShowWindow.View.State = 1
-            self.presentation.SlideShowWindow.Activate()
-
-        def blank_screen(self):
-            """
-            Blanks the screen
-            """
-            self.presentation.SlideShowWindow.View.State = 3
-
-        def stop_presentation(self):
-            """
-            Stops the current presentation and hides the output
-            """
-            self.presentation.SlideShowWindow.View.Exit()
-
+        def add_doc(self, name):
+            log.debug(u'Add Doc PowerPoint')
+            doc = PowerpointDocument(self,  name)
+            self.docs.append(doc)
+            return doc
+
+class PowerpointDocument(PresentationDocument):
+
+    def __init__(self,  controller,  presentation):
+        log.debug(u'Init Presentation Powerpoint')
+        self.presentation = None
+        self.controller = controller
+        self.store_filename(presentation)
+
+    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 presentations to run.
+        """
+        log.debug(u'LoadPresentation')
+        #try:
+        if not self.controller.process.Visible:
+            self.controller.start_process()
+        #except:
+        #   self.controller.start_process()
+        #try:
+        self.controller.process.Presentations.Open(self.filepath, False, False, True)
+        #except:
+        #    return
+        self.presentation = self.controller.process.Presentations(
+            self.controller.process.Presentations.Count)
+        self.create_thumbnails()
+
+    def create_thumbnails(self):
+        """
+        Create the thumbnail images for the current presentation.
+        Note an alternative and quicker method would be do
+            self.presentation.Slides[n].Copy()
+            thumbnail = QApplication.clipboard.image()
+        But for now we want a physical file since it makes
+        life easier elsewhere
+        """
+        if self.check_thumbnails():
+            return
+        self.presentation.Export(os.path.join(self.thumbnailpath, '')
+                                 , 'png', 600, 480)
+
+    def close_presentation(self):
+        """
+        Close presentation and clean up objects
+        Triggerent by new object being added to SlideController orOpenLP
+        being shut down
+        """
+        if self.presentation == None:
+            return
+        try:
+            self.presentation.Close()
+        except:
+            pass
+        self.presentation = None
+        self.controller.remove_doc(self)
+
+    def is_active(self):
+        """
+        Returns true if a presentation is currently active
+        """
+        if not self.controller.is_loaded():
+            return False
+        try:
+            if self.presentation.SlideShowWindow == None:
+                return False
+            if self.presentation.SlideShowWindow.View == None:
+                return False
+        except:
+            return False
+        return True
+
+    def unblank_screen(self):
+        """
+        Unblanks (restores) the presentationn
+        """
+        self.presentation.SlideShowSettings.Run()
+        self.presentation.SlideShowWindow.View.State = 1
+        self.presentation.SlideShowWindow.Activate()
+
+    def blank_screen(self):
+        """
+        Blanks the screen
+        """
+        self.presentation.SlideShowWindow.View.State = 3
+
+    def stop_presentation(self):
+        """
+        Stops the current presentation and hides the output
+        """
+        self.presentation.SlideShowWindow.View.Exit()
+
+    if os.name == u'nt':
         def start_presentation(self):
             """
             Starts a presentation from the beginning
@@ -207,53 +224,53 @@
                     dpi = 96
             self.presentation.SlideShowSettings.Run()
             self.presentation.SlideShowWindow.View.GotoSlide(1)
-            rendermanager = self.plugin.render_manager
+            rendermanager = self.controller.plugin.render_manager
             rect = rendermanager.screens.current[u'size']
             self.presentation.SlideShowWindow.Top = rect.y() * 72 / dpi
             self.presentation.SlideShowWindow.Height = rect.height() * 72 / dpi
             self.presentation.SlideShowWindow.Left = rect.x() * 72 / dpi
             self.presentation.SlideShowWindow.Width = rect.width() * 72 / dpi
 
-        def get_slide_number(self):
-            """
-            Returns the current slide number
-            """
-            return self.presentation.SlideShowWindow.View.CurrentShowPosition
-
-        def get_slide_count(self):
-            """
-            Returns total number of slides
-            """
-            return self.presentation.Slides.Count
-
-        def goto_slide(self, slideno):
-            """
-            Moves to a specific slide in the presentation
-            """
-            self.presentation.SlideShowWindow.View.GotoSlide(slideno)
-
-        def next_step(self):
-            """
-            Triggers the next effect of slide on the running presentation
-            """
-            self.presentation.SlideShowWindow.View.Next()
-
-        def previous_step(self):
-            """
-            Triggers the previous slide on the running presentation
-            """
-            self.presentation.SlideShowWindow.View.Previous()
-
-        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.thumbnailprefix + unicode(slide_no) + u'.png')
-            if os.path.isfile(path):
-                return path
-            else:
-                return None
+    def get_slide_number(self):
+        """
+        Returns the current slide number
+        """
+        return self.presentation.SlideShowWindow.View.CurrentShowPosition
+
+    def get_slide_count(self):
+        """
+        Returns total number of slides
+        """
+        return self.presentation.Slides.Count
+
+    def goto_slide(self, slideno):
+        """
+        Moves to a specific slide in the presentation
+        """
+        self.presentation.SlideShowWindow.View.GotoSlide(slideno)
+
+    def next_step(self):
+        """
+        Triggers the next effect of slide on the running presentation
+        """
+        self.presentation.SlideShowWindow.View.Next()
+
+    def previous_step(self):
+        """
+        Triggers the previous slide on the running presentation
+        """
+        self.presentation.SlideShowWindow.View.Previous()
+
+    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'.png')
+        if os.path.isfile(path):
+            return path
+        else:
+            return None

=== modified file 'openlp/plugins/presentations/lib/pptviewcontroller.py'
--- openlp/plugins/presentations/lib/pptviewcontroller.py	2010-02-16 22:28:35 +0000
+++ openlp/plugins/presentations/lib/pptviewcontroller.py	2010-03-02 23:20:29 +0000
@@ -30,7 +30,7 @@
     from ctypes import *
     from ctypes.wintypes import RECT
 
-from presentationcontroller import PresentationController
+from presentationcontroller import PresentationController,  PresentationDocument
 
 class PptviewController(PresentationController):
     """
@@ -49,8 +49,7 @@
         log.debug(u'Initialising')
         self.process = None
         PresentationController.__init__(self, plugin, u'Powerpoint Viewer')
-        self.supports= [u'.ppt', u'.pps']
-        self.pptid = None
+        self.supports = [u'.ppt', u'.pps']
 
     def check_available(self):
         """
@@ -90,123 +89,137 @@
             Called at system exit to clean up any running presentations
             """
             log.debug(u'Kill')
-            self.close_presentation()
-
-        def load_presentation(self, presentation):
-            """
-            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 presentations to run.
-            """
-            log.debug(u'LoadPresentation')
-            self.store_filename(presentation)
-            if self.pptid >= 0:
-                self.close_presentation()
-            rendermanager = self.plugin.render_manager
-            rect = rendermanager.screens.current[u'size']
-            rect = RECT(rect.x(), rect.y(), rect.right(), rect.bottom())
-            filepath = str(presentation.replace(u'/', u'\\'));
-            try:
-                self.pptid = self.process.OpenPPT(filepath, None, rect,
-                    str(os.path.join(self.thumbnailpath, self.thumbnailprefix)))
-                self.stop_presentation()
-            except:
-                log.exception(u'Failed to load presentation')
-
-        def close_presentation(self):
-            """
-            Close presentation and clean up objects
-            Triggerent by new object being added to SlideController orOpenLP
-            being shut down
-            """
-            self.process.ClosePPT(self.pptid)
-            self.pptid = -1
-
-        def is_loaded(self):
-            """
-            Returns true if a presentation is loaded
-            """
-            if self.pptid < 0:
-                return False
-            if self.get_slide_count() < 0:
-                return False
-            return True
-
-        def is_active(self):
-            """
-            Returns true if a presentation is currently active
-            """
-            return self.is_loaded()
-
-        def blank_screen(self):
-            """
-            Blanks the screen
-            """
-            self.process.Blank(self.pptid)
-
-        def unblank_screen(self):
-            """
-            Unblanks (restores) the presentationn
-            """
-            self.process.Unblank(self.pptid)
-
-        def stop_presentation(self):
-            """
-            Stops the current presentation and hides the output
-            """
-            self.process.Stop(self.pptid)
-
-        def start_presentation(self):
-            """
-            Starts a presentation from the beginning
-            """
-            self.process.RestartShow(self.pptid)
-
-        def get_slide_number(self):
-            """
-            Returns the current slide number
-            """
-            return self.process.GetCurrentSlide(self.pptid)
-
-        def get_slide_count(self):
-            """
-            Returns total number of slides
-            """
-            return self.process.GetSlideCount(self.pptid)
-
-        def goto_slide(self, slideno):
-            """
-            Moves to a specific slide in the presentation
-            """
-            self.process.GotoSlide(self.pptid, slideno)
-
-        def next_step(self):
-            """
-            Triggers the next effect of slide on the running presentation
-            """
-            self.process.NextStep(self.pptid)
-
-        def previous_step(self):
-            """
-            Triggers the previous slide on the running presentation
-            """
-            self.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.thumbnailprefix + unicode(slide_no) + u'.bmp')
-            if os.path.isfile(path):
-                return path
-            else:
-                return None
+            for doc in self.docs:
+                doc.close_presentation()
+
+        def add_doc(self, name):
+            log.debug(u'Add Doc PPTView')
+            doc = PptviewDocument(self,  name)
+            self.docs.append(doc)
+            return doc
+
+class PptviewDocument(PresentationDocument):
+
+    def __init__(self,  controller,  presentation):
+        log.debug(u'Init Presentation PowerPoint')
+        self.presentation = None
+        self.pptid = None
+        self.controller = controller
+        self.store_filename(presentation)
+
+    def load_presentation(self):
+        """
+        Called when a presentation is added to the SlideController.
+        It builds the environment, starts communcations with the background
+        PptView task started earlier.  
+
+        ``presentation``
+        The file name of the presentations to run.
+        """
+        log.debug(u'LoadPresentation')
+        #if self.pptid >= 0:
+        #    self.close_presentation()
+        rendermanager = self.controller.plugin.render_manager
+        rect = rendermanager.screens.current[u'size']
+        rect = RECT(rect.x(), rect.y(), rect.right(), rect.bottom())
+        filepath = str(self.filepath.replace(u'/', u'\\'));
+        try:
+            self.pptid = self.controller.process.OpenPPT(filepath, None, rect,
+                str(os.path.join(self.thumbnailpath, self.controller.thumbnailprefix)))
+            self.stop_presentation()
+        except:
+            log.exception(u'Failed to load presentation')
+
+    def close_presentation(self):
+        """
+        Close presentation and clean up objects
+        Triggerent by new object being added to SlideController orOpenLP
+        being shut down
+        """
+        self.controller.process.ClosePPT(self.pptid)
+        self.pptid = -1
+        self.controller.remove_doc(self)
+
+    def is_loaded(self):
+        """
+        Returns true if a presentation is loaded
+        """
+        if self.pptid < 0:
+            return False
+        if self.get_slide_count() < 0:
+            return False
+        return True
+
+    def is_active(self):
+        """
+        Returns true if a presentation is currently active
+        """
+        return self.is_loaded()
+
+    def blank_screen(self):
+        """
+        Blanks the screen
+        """
+        self.controller.process.Blank(self.pptid)
+
+    def unblank_screen(self):
+        """
+        Unblanks (restores) the presentationn
+        """
+        self.controller.process.Unblank(self.pptid)
+
+    def stop_presentation(self):
+        """
+        Stops the current presentation and hides the output
+        """
+        self.controller.process.Stop(self.pptid)
+
+    def start_presentation(self):
+        """
+        Starts a presentation from the beginning
+        """
+        self.controller.process.RestartShow(self.pptid)
+
+    def get_slide_number(self):
+        """
+        Returns the current slide number
+        """
+        return self.controller.process.GetCurrentSlide(self.pptid)
+
+    def get_slide_count(self):
+        """
+        Returns total number of slides
+        """
+        return self.controller.process.GetSlideCount(self.pptid)
+
+    def goto_slide(self, slideno):
+        """
+        Moves to a specific slide in the presentation
+        """
+        self.controller.process.GotoSlide(self.pptid, slideno)
+
+    def next_step(self):
+        """
+        Triggers the next effect of slide on the running presentation
+        """
+        self.controller.process.NextStep(self.pptid)
+
+    def previous_step(self):
+        """
+        Triggers the previous slide on the running presentation
+        """
+        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-02-01 19:42:52 +0000
+++ openlp/plugins/presentations/lib/presentationcontroller.py	2010-03-02 23:20:29 +0000
@@ -35,12 +35,10 @@
     """
     Base class for presentation controllers to inherit from
     Class to control interactions with presentations.
-    It creates the runtime environment, loads and closes the presentation as
-    well as triggering the correct activities based on the users input
-
+    It creates the runtime environment
     To create a new controller, take a copy of this file and name it
     so it ends in controller.py, i.e. foobarcontroller.py
-    Make sure it inhetits PresentationController
+    Make sure it inherits PresentationController
     Then fill in the blanks. If possible try and make sure it loads
     on all platforms, using for example os.name checks, although
     __init__, check_available and presentation_deleted should always work.
@@ -73,48 +71,6 @@
     ``presentation_deleted()``
         Deletes presentation specific files, e.g. thumbnails
 
-    ``load_presentation(presentation)``
-        Load a presentation file
-
-    ``close_presentation()``
-        Close presentation and clean up objects
-
-    ``presentation_loaded()``
-        Returns True if presentation is currently loaded
-
-    ``is_active()``
-        Returns True if a presentation is currently running
-
-    ``blank_screen()``
-        Blanks the screen, making it black.
-
-    ``unblank_screen()``
-        Unblanks the screen, restoring the output
-
-    ``stop_presentation()``
-        Stops the presentation, removing it from the output display
-
-    ``start_presentation()``
-        Starts the presentation from the beginning
-
-    ``get_slide_number()``
-        Returns the current slide number, from 1
-
-    ``get_slide_count()``
-        Returns total number of slides
-
-    ``goto_slide(slide_no)``
-        Jumps directly to the requested slide.
-
-    ``next_step()``
-       Triggers the next effect of slide on the running presentation
-
-    ``previous_step()``
-        Triggers the previous slide on the running presentation
-
-    ``get_slide_preview_file(slide_no)``
-        Returns a path to an image containing a preview for the requested slide
-
     """
     global log
     log = logging.getLogger(u'PresentationController')
@@ -137,10 +93,10 @@
             Name of the application, to appear in the application
         """
         self.supports = []
+        self.docs = []
         self.plugin = plugin
         self.name = name
         self.available = self.check_available()
-        self.slidenumber = 0
         if self.available:
             self.enabled = int(plugin.config.get_config(
                 name, QtCore.Qt.Unchecked)) == QtCore.Qt.Checked
@@ -158,13 +114,6 @@
         """
         return False
 
-    def presentation_deleted(self, presentation):
-        """
-        Cleans up/deletes any controller specific files created for
-        a file, e.g. thumbnails
-        """
-        self.store_filename(presentation)
-        shutil.rmtree(self.thumbnailpath)
 
     def start_process(self):
         """
@@ -180,7 +129,79 @@
         log.debug(u'Kill')
         self.close_presentation()
 
-    def load_presentation(self, presentation):
+    def add_doc(self, name):
+        """
+        Called when a new presentation document is opened
+        """
+        doc = PresentationDocument(self, name)
+        self.docs.append(doc)
+        return doc
+
+    def remove_doc(self, doc):
+        """
+        Called to remove an open document from the collection
+        """
+        log.debug(u'remove_doc Presentation')
+        self.docs.remove(doc)
+  
+
+class PresentationDocument(object):
+    """
+    Base class for presentation documents to inherit from.
+    Loads and closes the presentation as well as triggering the correct 
+    activities based on the users input
+
+    **Hook Functions**
+
+    ``load_presentation(presentation)``
+        Load a presentation file
+
+    ``close_presentation()``
+        Close presentation and clean up objects
+
+    ``presentation_loaded()``
+        Returns True if presentation is currently loaded
+
+    ``is_active()``
+        Returns True if a presentation is currently running
+
+    ``blank_screen()``
+        Blanks the screen, making it black.
+
+    ``unblank_screen()``
+        Unblanks the screen, restoring the output
+
+    ``stop_presentation()``
+        Stops the presentation, removing it from the output display
+
+    ``start_presentation()``
+        Starts the presentation from the beginning
+
+    ``get_slide_number()``
+        Returns the current slide number, from 1
+
+    ``get_slide_count()``
+        Returns total number of slides
+
+    ``goto_slide(slide_no)``
+        Jumps directly to the requested slide.
+
+    ``next_step()``
+       Triggers the next effect of slide on the running presentation
+
+    ``previous_step()``
+        Triggers the previous slide on the running presentation
+
+    ``get_slide_preview_file(slide_no)``
+        Returns a path to an image containing a preview for the requested slide
+
+    """
+    def __init__(self,  controller,  name):
+        self.slidenumber = 0
+        self.controller = controller
+        self.store_filename(name)
+
+    def load_presentation(self):
         """
         Called when a presentation is added to the SlideController.
         Loads the presentation and starts it
@@ -191,16 +212,29 @@
         """
         pass
 
+    def presentation_deleted(self):
+        """
+        Cleans up/deletes any controller specific files created for
+        a file, e.g. thumbnails
+        """
+        shutil.rmtree(self.thumbnailpath)
+
     def store_filename(self, presentation):
         """
         Set properties for the filename and thumbnail paths
         """
         self.filepath = presentation
-        self.filename = os.path.split(presentation)[1]
-        self.thumbnailpath = os.path.join(self.thumbnailroot, self.filename)
+        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 check_thumbnails(self):
         """
         Returns true if the thumbnail images look to exist and are more
@@ -218,10 +252,10 @@
         Close presentation and clean up objects
         Triggered by new object being added to SlideController
         """
-        pass
+        self.controller.delete_doc(self)
 
     def is_active(self):
-        """
+        """ 
         Returns True if a presentation is currently running
         """
         return False


Follow ups