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
1=== modified file 'openlp/plugins/presentations/lib/impresscontroller.py'
2--- openlp/plugins/presentations/lib/impresscontroller.py 2009-10-03 19:18:59 +0000
3+++ openlp/plugins/presentations/lib/impresscontroller.py 2009-10-07 23:20:22 +0000
4@@ -33,6 +33,7 @@
5 from win32com.client import Dispatch
6 else:
7 import uno
8+ from com.sun.star.beans import PropertyValue
9
10 from PyQt4 import QtCore
11
12@@ -104,19 +105,23 @@
13 The file name of the presentatios to the run.
14 """
15 log.debug(u'LoadPresentation')
16+ self.store_filename(presentation)
17 if os.name == u'nt':
18 desktop = self.get_com_desktop()
19 url = u'file:///' + presentation.replace(u'\\', u'/').replace(u':', u'|').replace(u' ', u'%20')
20+ thumbdir = u'file:///' + self.thumbnailpath.replace(
21+ u'\\', u'/').replace(u':', u'|').replace(u' ', u'%20')
22 else:
23 desktop = self.get_uno_desktop()
24 url = uno.systemPathToFileUrl(presentation)
25+ thumbdir = uno.systemPathToFileUrl(self.thumbnailpath)
26 if desktop is None:
27 return
28 try:
29 properties = []
30- properties = tuple(properties)
31- self.document = desktop.loadComponentFromURL(
32- url, "_blank", 0, properties)
33+ properties = tuple(properties)
34+ doc = desktop.loadComponentFromURL(url, u'_blank', 0, properties)
35+ self.document = doc
36 self.presentation = self.document.getPresentation()
37 self.presentation.Display = self.plugin.render_manager.current_display + 1
38 self.presentation.start()
39@@ -124,6 +129,22 @@
40 desktop.getCurrentComponent().Presentation.getController()
41 except:
42 log.exception(u'Failed to load presentation')
43+ return
44+ props = []
45+ if os.name == u'nt':
46+ prop = self.manager.Bridge_GetStruct(u'com.sun.star.beans.PropertyValue')
47+ else:
48+ prop = PropertyValue()
49+ prop.Name = u'FilterName'
50+ prop.Value = u'impress_png_Export'
51+ props.append(prop)
52+ props = tuple(props)
53+ pages = doc.getDrawPages()
54+ for idx in range(pages.getCount()):
55+ page = pages.getByIndex(idx)
56+ doc.getCurrentController().setCurrentPage(page)
57+ doc.storeToURL(thumbdir + u'/' + self.thumbnailprefix +
58+ unicode(idx+1) + u'.png', props)
59
60 def get_uno_desktop(self):
61 log.debug(u'getUNODesktop')
62@@ -139,8 +160,8 @@
63 self.startOpenoffice()
64 loop += 1
65 try:
66- smgr = ctx.ServiceManager
67- desktop = smgr.createInstanceWithContext(
68+ self.manager = ctx.ServiceManager
69+ desktop = self.manager.createInstanceWithContext(
70 "com.sun.star.frame.Desktop", ctx )
71 return desktop
72 except:
73@@ -150,8 +171,10 @@
74 def get_com_desktop(self):
75 log.debug(u'getCOMDesktop')
76 try:
77- smgr = self.get_com_servicemanager()
78- desktop = smgr.createInstance( "com.sun.star.frame.Desktop")
79+ self.manager = self.get_com_servicemanager()
80+ self.manager._FlagAsMethod(u'Bridge_GetStruct')
81+ self.manager._FlagAsMethod(u'Bridge_GetValueObject')
82+ desktop = self.manager.createInstance(u'com.sun.star.frame.Desktop')
83 return desktop
84 except:
85 log.exception(u'Failed to get COM desktop')
86@@ -160,7 +183,7 @@
87 def get_com_servicemanager(self):
88 log.debug(u'get_com_servicemanager')
89 try:
90- return Dispatch("com.sun.star.ServiceManager")
91+ return Dispatch(u'com.sun.star.ServiceManager')
92 except:
93 log.exception(u'Failed to get COM service manager')
94 return None
95@@ -224,5 +247,12 @@
96 """
97 self.controller.gotoPreviousSlide()
98
99- # def get_slide_preview_file(self, slide_no):
100+ def get_slide_preview_file(self, slide_no):
101+ """
102+ Returns an image path containing a preview for the requested slide
103
104+ ``slide_no``
105+ The slide an image is required for, starting at 1
106+ """
107+ return os.path.join(self.thumbnailpath,
108+ self.thumbnailprefix + slide_no + u'.png')
109
110=== modified file 'openlp/plugins/presentations/lib/powerpointcontroller.py'
111--- openlp/plugins/presentations/lib/powerpointcontroller.py 2009-10-03 19:18:59 +0000
112+++ openlp/plugins/presentations/lib/powerpointcontroller.py 2009-10-07 23:20:22 +0000
113@@ -28,6 +28,7 @@
114 if os.name == u'nt':
115 from win32com.client import Dispatch
116 import _winreg
117+ import win32ui
118
119 from presentationcontroller import PresentationController
120
121@@ -52,7 +53,7 @@
122 PresentationController.__init__(self, plugin, u'Powerpoint')
123 self.process = None
124 self.presentation = None
125-
126+
127 def check_available(self):
128 """
129 PowerPoint is able to run on this machine
130@@ -102,9 +103,14 @@
131 ``presentation``
132 The file name of the presentations to run.
133 """
134- self.filename = presentation
135+ log.debug(u'LoadPresentation')
136+ self.store_filename(presentation)
137 self.process.Presentations.Open(presentation, False, False, True)
138 self.presentation = self.process.Presentations(self.process.Presentations.Count)
139+ self.presentation.Export(os.path.join(self.thumbnailpath, '')
140+ , 'png', 600, 480)
141+ # self.presentation.Slides[n].Copy()
142+ # thumbnail = QClipboard.image()
143 self.start_presentation()
144
145 def close_presentation(self):
146@@ -156,8 +162,8 @@
147 self.presentation.SlideShowWindow.View.GotoSlide(1)
148 rendermanager = self.plugin.render_manager
149 rect = rendermanager.screen_list[rendermanager.current_display][u'size']
150- dpi = 96 # This assumption is good some of the time, but not
151- # all, but I don't know how to get the screen DPI yet
152+ #SlideShowWindow measures its size/position by points, not pixels
153+ dpi = win32ui.GetActiveWindow().GetDC().GetDeviceCaps(88)
154 self.presentation.SlideShowWindow.Top = rect.y() * 72 / dpi
155 self.presentation.SlideShowWindow.Height = rect.height() * 72 / dpi
156 self.presentation.SlideShowWindow.Left = rect.x() * 72 / dpi
157@@ -192,3 +198,13 @@
158 Triggers the previous slide on the running presentation
159 """
160 self.presentation.SlideShowWindow.View.Previous()
161+
162+ def get_slide_preview_file(self, slide_no):
163+ """
164+ Returns an image path containing a preview for the requested slide
165+
166+ ``slide_no``
167+ The slide an image is required for, starting at 1
168+ """
169+ return os.path.join(self.thumbnailpath,
170+ self.thumbnailprefix + slide_no + u'.png')
171
172=== modified file 'openlp/plugins/presentations/lib/pptviewcontroller.py'
173--- openlp/plugins/presentations/lib/pptviewcontroller.py 2009-09-30 19:26:51 +0000
174+++ openlp/plugins/presentations/lib/pptviewcontroller.py 2009-10-07 23:20:22 +0000
175@@ -49,9 +49,6 @@
176 self.process = None
177 PresentationController.__init__(self, plugin, u'Powerpoint Viewer')
178 self.pptid = None
179- self.thumbnailpath = os.path.join(plugin.config.get_data_path(),
180- u'pptview', u'thumbnails')
181- self.thumbprefix = u'slide'
182
183 def check_available(self):
184 """
185@@ -105,15 +102,16 @@
186 The file name of the presentations to run.
187 """
188 log.debug(u'LoadPresentation')
189+ self.store_filename(presentation)
190 if self.pptid >= 0:
191 self.close_presentation()
192 rendermanager = self.plugin.render_manager
193 rect = rendermanager.screen_list[rendermanager.current_display][u'size']
194 rect = RECT(rect.x(), rect.y(), rect.right(), rect.bottom())
195- filename = str(presentation.replace(u'/', u'\\'));
196+ filepath = str(presentation.replace(u'/', u'\\'));
197 try:
198- self.pptid = self.process.OpenPPT(filename, None, rect,
199- str(self.thumbnailpath))
200+ self.pptid = self.process.OpenPPT(filepath, None, rect,
201+ str(os.path.join(self.thumbnailpath, self.thumbnailprefix)))
202 except:
203 log.exception(u'Failed to load presentation')
204
205@@ -200,5 +198,5 @@
206 The slide an image is required for, starting at 1
207 """
208 return os.path.join(self.thumbnailpath,
209- self.thumbprefix + slide_no + u'.bmp')
210+ self.thumbnailprefix + slide_no + u'.bmp')
211
212
213=== modified file 'openlp/plugins/presentations/lib/presentationcontroller.py'
214--- openlp/plugins/presentations/lib/presentationcontroller.py 2009-10-03 19:18:59 +0000
215+++ openlp/plugins/presentations/lib/presentationcontroller.py 2009-10-07 23:20:22 +0000
216@@ -19,6 +19,7 @@
217 """
218
219 import logging
220+import os
221
222 from PyQt4 import QtCore
223
224@@ -132,6 +133,14 @@
225 name, QtCore.Qt.Unchecked)) == QtCore.Qt.Checked
226 else:
227 self.enabled = False
228+ self.thumbnailroot = os.path.join(plugin.config.get_data_path(),
229+ name, u'thumbnails')
230+ self.thumbnailprefix = u'slide'
231+ try:
232+ os.makedirs(self.thumbnailroot)
233+ except:
234+ pass
235+
236
237 def check_available(self):
238 """
239@@ -159,10 +168,22 @@
240 Loads the presentation and starts it
241
242 ``presentation``
243- The file name of the presentatios to the run.
244+ The file name of the presentations to the run.
245 """
246 pass
247
248+ def store_filename(self, presentation):
249+ """
250+ Set properties for the filename and thumbnail paths
251+ """
252+ self.filepath = presentation
253+ self.filename = os.path.split(presentation)[1]
254+ self.thumbnailpath = os.path.join(self.thumbnailroot, self.filename)
255+ try:
256+ os.mkdir(self.thumbnailpath)
257+ except:
258+ pass
259+
260 def close_presentation(self):
261 """
262 Close presentation and clean up objects