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

Proposed by Jonathan Corwin
Status: Merged
Merged at revision: not available
Proposed branch: lp:~j-corwin/openlp/present
Merge into: lp:openlp
Diff against target: 262 lines
4 files modified
openlp/plugins/presentations/lib/impresscontroller.py (+39/-9)
openlp/plugins/presentations/lib/powerpointcontroller.py (+20/-4)
openlp/plugins/presentations/lib/pptviewcontroller.py (+5/-7)
openlp/plugins/presentations/lib/presentationcontroller.py (+22/-1)
To merge this branch: bzr merge lp:~j-corwin/openlp/present
Reviewer Review Type Date Requested Status
Raoul Snyman Approve
Tim Bentley Approve
Review via email: mp+13030@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Jonathan Corwin (j-corwin) wrote :

Create images for each presentation slide, for display in the slide controller.
(Note currently created each time ppt is loaded, I will make only create as necessary in a future commit)

Revision history for this message
Tim Bentley (trb143) wrote :

Looks good. Did better than me with Impress as I could not fathom out the previews.

review: Approve
Revision history for this message
Raoul Snyman (raoul-snyman) wrote :

Looks good to me too.

Just some info: in v1.x when a presentation is "loaded" initially (via the media manager),
that is when the previews are generated. I don't know how we'd be able to detect when a
slide or a presentation has changed, but perhaps we should copy the presentation into a
"cache" directory (the Linux XDG system provides a cache dir, we can create one on Mac OS X
and Windows) and then, as per v1.x, use a "refresh" system if a person wants to reload
their presentation after it has changed.

review: Approve
Revision history for this message
Jonathan Corwin (j-corwin) wrote :

The pptviewlib (which creates preview images on behalf of the client, doing lots of off-screen window grabbing stuff) checks the date of the ppt and compares it to the date of the preview images, and if the ppt is newer then it recreates the images. I was thinking of doing something similar for the others but also create a manual re-load option too.

They can't easily be created when first added to the media manager at the moment, since at this point they don't know which of the three apps is going to display it (or is capable of opening it), and it is these controllers that create the thumbnails. (Also currently each controller has it's own thumbnails).

In the future we might need to specify which controller a file is going to be opened with when it is first loaded, since if you add both a odp and ppt to a service file, the operator isn't going to want to have to remember to change the default controller between each one.

Revision history for this message
Jonathan Corwin (j-corwin) wrote :

... also, I've never been a big fan of the 1.0 take a copy of the ppt approach, since there have been several times when I've been asked to edit the original ppt at the last minute after I've added it to openlp (as often happens in our church!) and I've forgotton to refresh, so the unedited version ends up going up on the screen to the embarrassment of those affected.

lp:~j-corwin/openlp/present updated
588. By Jonathan Corwin

More Presentation improvements

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'openlp/plugins/presentations/lib/impresscontroller.py'
--- openlp/plugins/presentations/lib/impresscontroller.py 2009-10-03 19:18:59 +0000
+++ openlp/plugins/presentations/lib/impresscontroller.py 2009-10-07 23:20:22 +0000
@@ -33,6 +33,7 @@
33 from win32com.client import Dispatch33 from win32com.client import Dispatch
34else:34else:
35 import uno35 import uno
36 from com.sun.star.beans import PropertyValue
3637
37from PyQt4 import QtCore38from PyQt4 import QtCore
3839
@@ -104,19 +105,23 @@
104 The file name of the presentatios to the run.105 The file name of the presentatios to the run.
105 """106 """
106 log.debug(u'LoadPresentation')107 log.debug(u'LoadPresentation')
108 self.store_filename(presentation)
107 if os.name == u'nt':109 if os.name == u'nt':
108 desktop = self.get_com_desktop()110 desktop = self.get_com_desktop()
109 url = u'file:///' + presentation.replace(u'\\', u'/').replace(u':', u'|').replace(u' ', u'%20')111 url = u'file:///' + presentation.replace(u'\\', u'/').replace(u':', u'|').replace(u' ', u'%20')
112 thumbdir = u'file:///' + self.thumbnailpath.replace(
113 u'\\', u'/').replace(u':', u'|').replace(u' ', u'%20')
110 else:114 else:
111 desktop = self.get_uno_desktop()115 desktop = self.get_uno_desktop()
112 url = uno.systemPathToFileUrl(presentation)116 url = uno.systemPathToFileUrl(presentation)
117 thumbdir = uno.systemPathToFileUrl(self.thumbnailpath)
113 if desktop is None:118 if desktop is None:
114 return119 return
115 try:120 try:
116 properties = []121 properties = []
117 properties = tuple(properties)122 properties = tuple(properties)
118 self.document = desktop.loadComponentFromURL(123 doc = desktop.loadComponentFromURL(url, u'_blank', 0, properties)
119 url, "_blank", 0, properties)124 self.document = doc
120 self.presentation = self.document.getPresentation()125 self.presentation = self.document.getPresentation()
121 self.presentation.Display = self.plugin.render_manager.current_display + 1126 self.presentation.Display = self.plugin.render_manager.current_display + 1
122 self.presentation.start()127 self.presentation.start()
@@ -124,6 +129,22 @@
124 desktop.getCurrentComponent().Presentation.getController()129 desktop.getCurrentComponent().Presentation.getController()
125 except:130 except:
126 log.exception(u'Failed to load presentation')131 log.exception(u'Failed to load presentation')
132 return
133 props = []
134 if os.name == u'nt':
135 prop = self.manager.Bridge_GetStruct(u'com.sun.star.beans.PropertyValue')
136 else:
137 prop = PropertyValue()
138 prop.Name = u'FilterName'
139 prop.Value = u'impress_png_Export'
140 props.append(prop)
141 props = tuple(props)
142 pages = doc.getDrawPages()
143 for idx in range(pages.getCount()):
144 page = pages.getByIndex(idx)
145 doc.getCurrentController().setCurrentPage(page)
146 doc.storeToURL(thumbdir + u'/' + self.thumbnailprefix +
147 unicode(idx+1) + u'.png', props)
127148
128 def get_uno_desktop(self):149 def get_uno_desktop(self):
129 log.debug(u'getUNODesktop')150 log.debug(u'getUNODesktop')
@@ -139,8 +160,8 @@
139 self.startOpenoffice()160 self.startOpenoffice()
140 loop += 1161 loop += 1
141 try:162 try:
142 smgr = ctx.ServiceManager163 self.manager = ctx.ServiceManager
143 desktop = smgr.createInstanceWithContext(164 desktop = self.manager.createInstanceWithContext(
144 "com.sun.star.frame.Desktop", ctx )165 "com.sun.star.frame.Desktop", ctx )
145 return desktop166 return desktop
146 except:167 except:
@@ -150,8 +171,10 @@
150 def get_com_desktop(self):171 def get_com_desktop(self):
151 log.debug(u'getCOMDesktop')172 log.debug(u'getCOMDesktop')
152 try:173 try:
153 smgr = self.get_com_servicemanager()174 self.manager = self.get_com_servicemanager()
154 desktop = smgr.createInstance( "com.sun.star.frame.Desktop")175 self.manager._FlagAsMethod(u'Bridge_GetStruct')
176 self.manager._FlagAsMethod(u'Bridge_GetValueObject')
177 desktop = self.manager.createInstance(u'com.sun.star.frame.Desktop')
155 return desktop178 return desktop
156 except:179 except:
157 log.exception(u'Failed to get COM desktop')180 log.exception(u'Failed to get COM desktop')
@@ -160,7 +183,7 @@
160 def get_com_servicemanager(self):183 def get_com_servicemanager(self):
161 log.debug(u'get_com_servicemanager')184 log.debug(u'get_com_servicemanager')
162 try:185 try:
163 return Dispatch("com.sun.star.ServiceManager")186 return Dispatch(u'com.sun.star.ServiceManager')
164 except:187 except:
165 log.exception(u'Failed to get COM service manager')188 log.exception(u'Failed to get COM service manager')
166 return None189 return None
@@ -224,5 +247,12 @@
224 """247 """
225 self.controller.gotoPreviousSlide()248 self.controller.gotoPreviousSlide()
226249
227 # def get_slide_preview_file(self, slide_no):250 def get_slide_preview_file(self, slide_no):
251 """
252 Returns an image path containing a preview for the requested slide
228253
254 ``slide_no``
255 The slide an image is required for, starting at 1
256 """
257 return os.path.join(self.thumbnailpath,
258 self.thumbnailprefix + slide_no + u'.png')
229259
=== modified file 'openlp/plugins/presentations/lib/powerpointcontroller.py'
--- openlp/plugins/presentations/lib/powerpointcontroller.py 2009-10-03 19:18:59 +0000
+++ openlp/plugins/presentations/lib/powerpointcontroller.py 2009-10-07 23:20:22 +0000
@@ -28,6 +28,7 @@
28if os.name == u'nt':28if os.name == u'nt':
29 from win32com.client import Dispatch29 from win32com.client import Dispatch
30 import _winreg30 import _winreg
31 import win32ui
3132
32from presentationcontroller import PresentationController33from presentationcontroller import PresentationController
3334
@@ -52,7 +53,7 @@
52 PresentationController.__init__(self, plugin, u'Powerpoint')53 PresentationController.__init__(self, plugin, u'Powerpoint')
53 self.process = None54 self.process = None
54 self.presentation = None55 self.presentation = None
5556
56 def check_available(self):57 def check_available(self):
57 """58 """
58 PowerPoint is able to run on this machine59 PowerPoint is able to run on this machine
@@ -102,9 +103,14 @@
102 ``presentation``103 ``presentation``
103 The file name of the presentations to run.104 The file name of the presentations to run.
104 """ 105 """
105 self.filename = presentation106 log.debug(u'LoadPresentation')
107 self.store_filename(presentation)
106 self.process.Presentations.Open(presentation, False, False, True)108 self.process.Presentations.Open(presentation, False, False, True)
107 self.presentation = self.process.Presentations(self.process.Presentations.Count)109 self.presentation = self.process.Presentations(self.process.Presentations.Count)
110 self.presentation.Export(os.path.join(self.thumbnailpath, '')
111 , 'png', 600, 480)
112 # self.presentation.Slides[n].Copy()
113 # thumbnail = QClipboard.image()
108 self.start_presentation()114 self.start_presentation()
109 115
110 def close_presentation(self):116 def close_presentation(self):
@@ -156,8 +162,8 @@
156 self.presentation.SlideShowWindow.View.GotoSlide(1)162 self.presentation.SlideShowWindow.View.GotoSlide(1)
157 rendermanager = self.plugin.render_manager163 rendermanager = self.plugin.render_manager
158 rect = rendermanager.screen_list[rendermanager.current_display][u'size']164 rect = rendermanager.screen_list[rendermanager.current_display][u'size']
159 dpi = 96 # This assumption is good some of the time, but not165 #SlideShowWindow measures its size/position by points, not pixels
160 # all, but I don't know how to get the screen DPI yet166 dpi = win32ui.GetActiveWindow().GetDC().GetDeviceCaps(88)
161 self.presentation.SlideShowWindow.Top = rect.y() * 72 / dpi167 self.presentation.SlideShowWindow.Top = rect.y() * 72 / dpi
162 self.presentation.SlideShowWindow.Height = rect.height() * 72 / dpi168 self.presentation.SlideShowWindow.Height = rect.height() * 72 / dpi
163 self.presentation.SlideShowWindow.Left = rect.x() * 72 / dpi169 self.presentation.SlideShowWindow.Left = rect.x() * 72 / dpi
@@ -192,3 +198,13 @@
192 Triggers the previous slide on the running presentation198 Triggers the previous slide on the running presentation
193 """199 """
194 self.presentation.SlideShowWindow.View.Previous()200 self.presentation.SlideShowWindow.View.Previous()
201
202 def get_slide_preview_file(self, slide_no):
203 """
204 Returns an image path containing a preview for the requested slide
205
206 ``slide_no``
207 The slide an image is required for, starting at 1
208 """
209 return os.path.join(self.thumbnailpath,
210 self.thumbnailprefix + slide_no + u'.png')
195211
=== modified file 'openlp/plugins/presentations/lib/pptviewcontroller.py'
--- openlp/plugins/presentations/lib/pptviewcontroller.py 2009-09-30 19:26:51 +0000
+++ openlp/plugins/presentations/lib/pptviewcontroller.py 2009-10-07 23:20:22 +0000
@@ -49,9 +49,6 @@
49 self.process = None49 self.process = None
50 PresentationController.__init__(self, plugin, u'Powerpoint Viewer')50 PresentationController.__init__(self, plugin, u'Powerpoint Viewer')
51 self.pptid = None51 self.pptid = None
52 self.thumbnailpath = os.path.join(plugin.config.get_data_path(),
53 u'pptview', u'thumbnails')
54 self.thumbprefix = u'slide'
5552
56 def check_available(self):53 def check_available(self):
57 """54 """
@@ -105,15 +102,16 @@
105 The file name of the presentations to run.102 The file name of the presentations to run.
106 """103 """
107 log.debug(u'LoadPresentation')104 log.debug(u'LoadPresentation')
105 self.store_filename(presentation)
108 if self.pptid >= 0:106 if self.pptid >= 0:
109 self.close_presentation()107 self.close_presentation()
110 rendermanager = self.plugin.render_manager108 rendermanager = self.plugin.render_manager
111 rect = rendermanager.screen_list[rendermanager.current_display][u'size']109 rect = rendermanager.screen_list[rendermanager.current_display][u'size']
112 rect = RECT(rect.x(), rect.y(), rect.right(), rect.bottom()) 110 rect = RECT(rect.x(), rect.y(), rect.right(), rect.bottom())
113 filename = str(presentation.replace(u'/', u'\\'));111 filepath = str(presentation.replace(u'/', u'\\'));
114 try:112 try:
115 self.pptid = self.process.OpenPPT(filename, None, rect,113 self.pptid = self.process.OpenPPT(filepath, None, rect,
116 str(self.thumbnailpath))114 str(os.path.join(self.thumbnailpath, self.thumbnailprefix)))
117 except:115 except:
118 log.exception(u'Failed to load presentation')116 log.exception(u'Failed to load presentation')
119117
@@ -200,5 +198,5 @@
200 The slide an image is required for, starting at 1198 The slide an image is required for, starting at 1
201 """199 """
202 return os.path.join(self.thumbnailpath,200 return os.path.join(self.thumbnailpath,
203 self.thumbprefix + slide_no + u'.bmp')201 self.thumbnailprefix + slide_no + u'.bmp')
204202
205203
=== modified file 'openlp/plugins/presentations/lib/presentationcontroller.py'
--- openlp/plugins/presentations/lib/presentationcontroller.py 2009-10-03 19:18:59 +0000
+++ openlp/plugins/presentations/lib/presentationcontroller.py 2009-10-07 23:20:22 +0000
@@ -19,6 +19,7 @@
19"""19"""
2020
21import logging21import logging
22import os
2223
23from PyQt4 import QtCore24from PyQt4 import QtCore
2425
@@ -132,6 +133,14 @@
132 name, QtCore.Qt.Unchecked)) == QtCore.Qt.Checked133 name, QtCore.Qt.Unchecked)) == QtCore.Qt.Checked
133 else:134 else:
134 self.enabled = False135 self.enabled = False
136 self.thumbnailroot = os.path.join(plugin.config.get_data_path(),
137 name, u'thumbnails')
138 self.thumbnailprefix = u'slide'
139 try:
140 os.makedirs(self.thumbnailroot)
141 except:
142 pass
143
135144
136 def check_available(self):145 def check_available(self):
137 """146 """
@@ -159,10 +168,22 @@
159 Loads the presentation and starts it168 Loads the presentation and starts it
160169
161 ``presentation``170 ``presentation``
162 The file name of the presentatios to the run.171 The file name of the presentations to the run.
163 """172 """
164 pass173 pass
165174
175 def store_filename(self, presentation):
176 """
177 Set properties for the filename and thumbnail paths
178 """
179 self.filepath = presentation
180 self.filename = os.path.split(presentation)[1]
181 self.thumbnailpath = os.path.join(self.thumbnailroot, self.filename)
182 try:
183 os.mkdir(self.thumbnailpath)
184 except:
185 pass
186
166 def close_presentation(self):187 def close_presentation(self):
167 """188 """
168 Close presentation and clean up objects189 Close presentation and clean up objects