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