Merge lp:~marmyshev/openlp/presentation into lp:openlp

Proposed by Dmitriy Marmyshev
Status: Superseded
Proposed branch: lp:~marmyshev/openlp/presentation
Merge into: lp:openlp
Diff against target: 945 lines (+821/-5) (has conflicts)
6 files modified
openlp/core/lib/pluginmanager.py (+0/-5)
openlp/plugins/presentations/lib/keynotemaccontroller.py (+362/-0)
openlp/plugins/presentations/lib/powerpointmaccontroller.py (+401/-0)
openlp/plugins/presentations/lib/presentationtab.py (+35/-0)
openlp/plugins/presentations/presentationplugin.py (+12/-0)
scripts/check_dependencies.py (+11/-0)
Text conflict in openlp/plugins/presentations/lib/presentationtab.py
To merge this branch: bzr merge lp:~marmyshev/openlp/presentation
Reviewer Review Type Date Requested Status
matysek (community) Needs Fixing
Andreas Preikschat Pending
Review via email: mp+155063@code.launchpad.net

This proposal supersedes a proposal from 2013-03-21.

This proposal has been superseded by a proposal from 2013-04-01.

Description of the change

Add support to load presentations with PowerPoint and Keynote on Mac OS X.

To post a comment you must log in.
Revision history for this message
Andreas Preikschat (googol-deactivatedaccount) wrote : Posted in a previous version of this proposal

Please don't commit uncommented things. Please remove lines 10+11, 86, 112 and more.

112 + #except pywintypes.com_error:
113 + except:

Don't commit the uncommented line. You should catch the generic exception (I don't know why you commented except pywintypes.com_error out). Also you should log that you cought an exception.

Line 123: Should be openlp_settings = Settings(u'openlp.org', u'OpenLP')
We use u'' for strings. And you missed the space after the comma.

Line 127: You have two spaces there (should be just one)

Line 128 (and some more): Don't use <>, rather use != for inequality.

And please add some more comments. Regards

PS: Unable to test the code here, as I don't have a MAC

review: Needs Fixing
Revision history for this message
Tim Bentley (trb143) wrote : Posted in a previous version of this proposal

Will need to be approved by matysek_

Revision history for this message
matysek (mzibricky) wrote : Posted in a previous version of this proposal

> Will need to be approved by matysek_

I will need to test it.

Could you please add the 'appscript' osx dependency to the following script?

./scripts/check_dependencies.py

Thanks

Revision history for this message
matysek (mzibricky) wrote : Posted in a previous version of this proposal

I tested the branch and trying to load a presentation in openlp. MS powerpoint is started with openlp.

These are the issues I get:
- when the user quits manually powerpoint before exiting openlp - powerpoint is started again after openlp exits.
- when trying to load a ppt presentation - .ppt file is loaded into powerpoint but new presentation item is not added to openlp and I get the following exception:

cat openlp_trace.txt
 --- Exception Traceback ---
Traceback (most recent call last):
  File "/Users/martin/Documents/openlp/bug-836574/openlp/core/lib/mediamanageritem.py", line 334, in onFileClick
    self.validateAndLoad(files)
  File "/Users/martin/Documents/openlp/bug-836574/openlp/core/lib/mediamanageritem.py", line 383, in validateAndLoad
    self.loadList(full_list)
  File "/Users/martin/Documents/openlp/bug-836574/openlp/plugins/presentations/lib/mediaitem.py", line 188, in loadList
    doc.load_presentation()
  File "/Users/martin/Documents/openlp/bug-836574/openlp/plugins/presentations/lib/powerpointmaccontroller.py", line 153, in load_presentation
    self.create_thumbnails()
  File "/Users/martin/Documents/openlp/bug-836574/openlp/plugins/presentations/lib/powerpointmaccontroller.py", line 175, in create_thumbnails
    for filename in os.listdir(temp_dir):
OSError: [Errno 2] No such file or directory: '/Users/martin/Library/Application Support/openlp/Data/presentations/thumbnails/Chapter08.ppt/Chapter08.ppt'

--- System information ---
Platform: Darwin-11.4.2-x86_64-i386-64bit

--- Library Versions ---
Python: 2.7.3
Qt4: 4.8.4
Phonon: 4.6.0
PyQt4: 4.9.6
QtWebkit: 534.34
SQLAlchemy: 0.7.9
SQLAlchemy Migrate: 0.7.2
BeautifulSoup: 3.2.1
lxml: 2.3.2
Chardet: 2.0.1
PyEnchant: 1.6.5
PySQLite: -
Mako: 0.7.3
pyUNO bridge: -

Revision history for this message
matysek (mzibricky) : Posted in a previous version of this proposal
review: Needs Fixing
Revision history for this message
Andreas Preikschat (googol-deactivatedaccount) wrote : Posted in a previous version of this proposal

Just a note: when you are ready with your changes (fixed) which were requested then resubmit your proposal (upper-left corner -> Resubmit proposal). Then the developers know that your code base is again read to be reviewed.

Keep it up :)

Revision history for this message
matysek (mzibricky) wrote : Posted in a previous version of this proposal

Today I tested the r2118 - the temp_dir check and relaunching ppt are fixed.

There are some other issues:

- when opening a presentation the preview of the 1st slide is not generated in openlp. Last time it was created.
- What is the use case scenario when the powerpoint should be started?
  - Should it start directly with openlp when enabled and powerpoint is installed?
  - Or start it later when .ppt file is imported?
  - now it sometimes start with openlp
  - when powerpoint is started with openlp it is put above openlp window and openlp is thus hidden
- powerpoint and openlp icon is not visible in the dock bar - last time there were visible both.
- when a .ppt file is opened and I click on the preview button - powerpoint window takes focus and is put above openlp. But then in openlp i get message like

  "The presentation /Users/martin/Downloads/lecture22.ppt is incomplete, please reload."

Revision history for this message
Dmitriy Marmyshev (marmyshev) wrote : Posted in a previous version of this proposal

Yes, matysek, the work with PPT on Mac OS is really really hard.

There are some other issues with it:
for example, if your are in slideshow mode (with presenter view) and switch
to another app - PPT hide slideshow window from second screen. or if you
send command to PPT "Next slide" or "Go to slide N" the PPT wont do this
until you activate the PPT app.
If you use "full screen" mode (without presenter view) on second screen the
PPT app change global settings of display to "Mirror displays" and after
slideshow exits the PPT app change displays back to "extention" mode.
As it seems, the behavior of PPT will be different then on Windows platform.
I also analyzed other applications (like ProPresenter, Mediashout, new
EasyWorship) they have the same issue. They solve it in two ways:
1st - convert PPT file to its own slide's format and forget about MS PPT
forever.
2nd - use MS PPT app on Mac as launched app from their app - by sending
command (as i do) to MS PPT to start slideshow with .ppt file from service
schedule. and all controlling continuing in MS PPT, after MS PPT finish
slideshow the controlling of second screen returns back to their app.

I think, the best we can do - is the 2nd way.

Almost the same is for Keynote app controller.

So, I want to change the behavior of mac-controllers and then will propose
to merge again.

On Tue, Feb 12, 2013 at 2:03 AM, matysek <email address hidden> wrote:

> Today I tested the r2118 - the temp_dir check and relaunching ppt are
> fixed.
>
> There are some other issues:
>
> - when opening a presentation the preview of the 1st slide is not
> generated in openlp. Last time it was created.
> - What is the use case scenario when the powerpoint should be started?
> - Should it start directly with openlp when enabled and powerpoint is
> installed?
> - Or start it later when .ppt file is imported?
> - now it sometimes start with openlp
> - when powerpoint is started with openlp it is put above openlp window
> and openlp is thus hidden
> - powerpoint and openlp icon is not visible in the dock bar - last time
> there were visible both.
> - when a .ppt file is opened and I click on the preview button -
> powerpoint window takes focus and is put above openlp. But then in openlp i
> get message like
>
> "The presentation /Users/martin/Downloads/lecture22.ppt is incomplete,
> please reload."
> --
> https://code.launchpad.net/~marmyshev/openlp/presentation/+merge/143389
> You are the owner of lp:~marmyshev/openlp/presentation.
>

Revision history for this message
Jonathan Corwin (j-corwin) wrote : Posted in a previous version of this proposal

You may have tried this, but is it possible to re-activate the PowerPoint window prior to sending the commands? There looks to be some "Activate" applescript command to do this?

Revision history for this message
Dmitriy Marmyshev (marmyshev) wrote : Posted in a previous version of this proposal

Yes, now I use "Activate()" command for changing slides in PPT, but this
looks ugly.
This is not understandable for user's mind.

And also Keynote has the same problem as PPT - if you activate another app
during slideshow it hides slideshow window from second screen.

On Wed, Feb 13, 2013 at 2:58 PM, Jonathan Corwin <email address hidden> wrote:

> You may have tried this, but is it possible to re-activate the PowerPoint
> window prior to sending the commands? There looks to be some "Activate"
> applescript command to do this?
> --
> https://code.launchpad.net/~marmyshev/openlp/presentation/+merge/143389
> You are the owner of lp:~marmyshev/openlp/presentation.
>

Revision history for this message
Andreas Preikschat (googol-deactivatedaccount) wrote : Posted in a previous version of this proposal

Any progress on this?

Revision history for this message
Andreas Preikschat (googol-deactivatedaccount) wrote : Posted in a previous version of this proposal

- You have a conflict in 'openlp/plugins/presentations/lib/presentationtab.py'

This
# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
should be
# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
We moved from 80 characters to 120.

Please do not add commented lines (e. g. 207, 221, ...).

review: Needs Fixing
Revision history for this message
Andreas Preikschat (googol-deactivatedaccount) wrote : Posted in a previous version of this proposal

If you need help or have any questions in regard to my comments feel free to ask. :)

Revision history for this message
Andreas Preikschat (googol-deactivatedaccount) wrote : Posted in a previous version of this proposal

Please do not do this:
55 +from appscript import *
rather do
import appscript

59 +
60 +log = logging.getLogger(__name__)
61 +
62 +class KeynoteController(PresentationController)
Before and after the "log = " should be two blank lines

106 + if self.process and len(self.process.slideshows()) > 0:
When dealing with lists do "if not my_list" instead of "if len(my_list) > 0"

387 + text = ''
391 + text += shape.TextFrame.TextRange.Text + '\n'
If not explicit wanted do not use strings; use unicode strings: u''

review: Needs Fixing
Revision history for this message
matysek (mzibricky) wrote :

I'm testing it with macoffice 2011 but:
- the macoffice is not recognized by openl
- all the presentation controllers are greyed out in properties
- in the log there is a text like

2013-03-23 13:22:37,125 presentationplugin INFO Presentations Initialising
2013-03-23 13:22:37,140 openlp.plugins.presentations.lib.keynotemaccontroller DEBUG check_available
2013-03-23 13:22:37,140 openlp.plugins.presentations.lib.impresscontroller DEBUG check_available
2013-03-23 13:22:37,141 openlp.plugins.presentations.lib.powerpointmaccontroller DEBUG check_available
2013-03-23 13:22:37,141 openlp.plugins.presentations.lib.pptviewcontroller DEBUG check_available
2013-03-23 13:22:37,142 openlp.core.ui.mediadockmanager DEBUG Inserting Presentations dock
2013-03-23 13:22:37,145 openlp.plugins.presentations.lib.keynotemaccontroller DEBUG start_process
2013-03-23 13:22:37,146 presentationplugin WARNING Failed to start controller process
2013-03-23 13:22:37,146 openlp.plugins.presentations.lib.powerpointmaccontroller DEBUG start_process
2013-03-23 13:22:37,146 presentationplugin WARNING Failed to start controller process
2013-03-23 13:22:37,148 openlp.core.lib.pluginmanager INFO Initialisation Complete for presentations

review: Needs Information
Revision history for this message
matysek (mzibricky) wrote :

It's probably not working because with our latest style fixes you replaced
  from appscript import *
with
  import appscript

However, you should then also add prefix appscript to the objects you use from that module like

  appscript.app
  appscript.k
  appscript.CantLaunchApplicationError

463 + def check_available(self):
464 + """
465 + PowerPoint is able to run on this machine
466 + """
467 + log.debug(u'check_available')
468 + return True

Is there a better way to check availability of powerpoint than only return true?
- probably try to create process by appscript.app() and catch for error appscript.ApplicationNotFoundError

When I add .ppt file to openlp and click on the 'preview'button I get message like

  'The Presentation file.ppt is incomplete, please reload.'

review: Needs Fixing
lp:~marmyshev/openlp/presentation updated
2122. By Dmitriy Marmyshev

returned back appscript import.

Revision history for this message
Dmitriy Marmyshev (marmyshev) wrote :

I returned back the import. Probably it's temperary.
Please, try all other behaviors of controllers.

lp:~marmyshev/openlp/presentation updated
2123. By Dmitriy Marmyshev

improvements of commands to ppt and keynote applications

2124. By Dmitriy Marmyshev

appscript import fix and keynote create_thumbnails fix

2125. By Dmitriy Marmyshev

HEAD

2126. By Dmitriy Marmyshev

next_step and previous_step fixes

2127. By Dmitriy Marmyshev

activate presentation in firsttimeform and firsttimewizard.

2128. By Dmitriy Marmyshev

logs added.

2129. By Dmitriy Marmyshev

removed commented lines

2130. By Dmitriy Marmyshev

Trunk

2131. By Dmitriy Marmyshev

temp new chreate_thumbnails. Needs to fix

2132. By Dmitriy Marmyshev

Trunk

2133. By Dmitriy Marmyshev

p3 fixes

2134. By Dmitriy Marmyshev

Trunk

2135. By Dmitriy Marmyshev

fixes unicode & bzr eric5 ignore

2136. By Dmitriy Marmyshev

Trunk

2137. By Dmitriy Marmyshev

thumbnail fixes

2138. By Dmitriy Marmyshev

Tests

2139. By Dmitriy Marmyshev

Added check_ver for appscript module

2140. By Dmitriy Marmyshev

Trunk

2141. By Dmitriy Marmyshev

cleanups.

2142. By Dmitriy Marmyshev

Trunk

2143. By Dmitriy Marmyshev

tests fixes

Unmerged revisions

2143. By Dmitriy Marmyshev

tests fixes

2142. By Dmitriy Marmyshev

Trunk

2141. By Dmitriy Marmyshev

cleanups.

2140. By Dmitriy Marmyshev

Trunk

2139. By Dmitriy Marmyshev

Added check_ver for appscript module

2138. By Dmitriy Marmyshev

Tests

2137. By Dmitriy Marmyshev

thumbnail fixes

2136. By Dmitriy Marmyshev

Trunk

2135. By Dmitriy Marmyshev

fixes unicode & bzr eric5 ignore

2134. By Dmitriy Marmyshev

Trunk

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'openlp/core/lib/pluginmanager.py'
2--- openlp/core/lib/pluginmanager.py 2013-03-19 19:43:22 +0000
3+++ openlp/core/lib/pluginmanager.py 2013-04-01 23:08:22 +0000
4@@ -94,11 +94,6 @@
5 present_plugin_dir = os.path.join(self.base_path, 'presentations')
6 log.debug(u'finding plugins in %s at depth %d', unicode(self.base_path), start_depth)
7 for root, dirs, files in os.walk(self.base_path):
8- if sys.platform == 'darwin' and root.startswith(present_plugin_dir):
9- # TODO Presentation plugin is not yet working on Mac OS X.
10- # For now just ignore it. The following code will ignore files from the presentation plugin directory
11- # and thereby never import the plugin.
12- continue
13 for name in files:
14 if name.endswith(u'.py') and not name.startswith(u'__'):
15 path = os.path.abspath(os.path.join(root, name))
16
17=== added file 'openlp/plugins/presentations/lib/keynotemaccontroller.py'
18--- openlp/plugins/presentations/lib/keynotemaccontroller.py 1970-01-01 00:00:00 +0000
19+++ openlp/plugins/presentations/lib/keynotemaccontroller.py 2013-04-01 23:08:22 +0000
20@@ -0,0 +1,362 @@
21+# -*- coding: utf-8 -*-
22+# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
23+
24+###############################################################################
25+# OpenLP - Open Source Lyrics Projection #
26+# --------------------------------------------------------------------------- #
27+# Copyright (c) 2008-2012 Raoul Snyman #
28+# Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
29+# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub, #
30+# Meinert Jordan, Armin Köhler, Eric Ludin, Edwin Lunando, Brian T. Meyer, #
31+# Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias Põldaru, #
32+# Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
33+# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Dave Warnock, #
34+# Frode Woldsund, Martin Zibricky #
35+# --------------------------------------------------------------------------- #
36+# This program is free software; you can redistribute it and/or modify it #
37+# under the terms of the GNU General Public License as published by the Free #
38+# Software Foundation; version 2 of the License. #
39+# #
40+# This program is distributed in the hope that it will be useful, but WITHOUT #
41+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
42+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
43+# more details. #
44+# #
45+# You should have received a copy of the GNU General Public License along #
46+# with this program; if not, write to the Free Software Foundation, Inc., 59 #
47+# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
48+###############################################################################
49+
50+import os
51+import sys
52+import logging
53+import mactypes
54+
55+import appscript
56+
57+from openlp.core.lib import Settings, ScreenList
58+from presentationcontroller import PresentationController, PresentationDocument
59+
60+
61+log = logging.getLogger(__name__)
62+
63+
64+class KeynoteController(PresentationController):
65+ """
66+ Class to control interactions with KeyNote Presentations
67+ It creates the runtime Environment , Loads the and Closes the Presentation
68+ As well as triggering the correct activities based on the users input
69+ """
70+ log.info(u'KeynoteController loaded')
71+
72+ def __init__(self, plugin):
73+ """
74+ Initialise the class
75+ """
76+ log.debug(u'Initialising')
77+ PresentationController.__init__(self, plugin, u'Keynote', KeynoteDocument)
78+ self.supports = [u'key']
79+ self.process = None
80+
81+ def check_available(self):
82+ """
83+ KeyNote is able to run on this machine
84+ """
85+ log.debug(u'check_available')
86+ try:
87+ self.process = appscript.app('Keynote')
88+ except appscript.ApplicationNotFoundError:
89+ return False
90+ self.kill()
91+ return True
92+
93+ def start_process(self):
94+ """
95+ Loads KeyNote process
96+ """
97+ log.debug(u'start_process')
98+ if not self.process or not self.process.isrunning():
99+ self.process = appscript.app('Keynote')
100+ self.process.relaunchmode = 'limited' #'always'
101+ self.process.launch()
102+ self.apply_app_settings()
103+
104+ def kill(self):
105+ """
106+ Called at system exit to clean up any running presentations
107+ """
108+ log.debug(u'Kill Keynote')
109+ while self.docs and self.process.isrunning():
110+ self.docs[0].close_presentation()
111+ if self.process is None or not self.process.isrunning():
112+ return
113+ try:
114+ total = self.process.slideshows()
115+ if self.process and total != appscript.k.missing_value and len(total) > 0:
116+ return
117+ self.process.quit(saving = appscript.k.ask)
118+ except appscript.CantLaunchApplicationError:
119+ pass
120+ self.process = None
121+
122+ def apply_app_settings(self):
123+ """
124+ Apply settings for Keynote
125+ PresentationModeEnableFeedbackDisplay = True if in settings of OpenLP show presenter view = True
126+ PresentationModeUseSecondary = 1 if OpenLP monitor for output = Screen 2
127+ """
128+ openlp_settings = Settings(u'openlp.org',u'OpenLP')
129+ keynote_settings = Settings(u'apple', u'iWork.Keynote')
130+ use_secondary = int(keynote_settings.value(u'PresentationModeUseSecondary'))
131+ monitor = openlp_settings.value( u'general/monitor')
132+ override_position = openlp_settings.value( u'general/override position')
133+ if not override_position and use_secondary != monitor:
134+ keynote_settings.setValue(u'PresentationModeUseSecondary', unicode(monitor))
135+ elif override_position and use_secondary != 0:
136+ keynote_settings.setValue(u'PresentationModeUseSecondary', u'0')
137+ show_presenter_view = openlp_settings.value(self.plugin.settingsSection + u'/show presenter view')
138+ keynote_feedback_display = keynote_settings.value(u'PresentationModeEnableFeedbackDisplay')
139+ if show_presenter_view != keynote_feedback_display:
140+ keynote_settings.setValue(u'PresentationModeEnableFeedbackDisplay', show_presenter_view)
141+ play_well_with_others = keynote_settings.value(u'PresentationModePlayWellWithOthers')
142+ if not play_well_with_others:
143+ keynote_settings.setValue(u'PresentationModePlayWellWithOthers', True)
144+
145+
146+class KeynoteDocument(PresentationDocument):
147+ """
148+ Class which holds information and controls a single presentation
149+ """
150+
151+ def __init__(self, controller, presentation):
152+ """
153+ Constructor, store information about the file and initialise
154+ """
155+ log.debug(u'Init Presentation Keynote')
156+ PresentationDocument.__init__(self, controller, presentation)
157+ self.presentation = None
158+
159+ def load_presentation(self):
160+ """
161+ Called when a presentation is added to the SlideController.
162+ Opens the Keynote file using the process created earlier.
163+ """
164+ log.debug(u'load_presentation')
165+ if not self.controller.process or not self.controller.process.isrunning():
166+ self.controller.start_process()
167+ try:
168+ self.controller.process.open(self.filepath)
169+ except appscript.CommandError:
170+ log.debug(u'Keynote open failed')
171+ return False
172+ slideshows = self.controller.process.slideshows()
173+ for slideshow in slideshows:
174+ path = slideshow.path()
175+ if self.filepath == path:
176+ self.presentation = slideshow
177+ self.create_thumbnails()
178+ return True
179+ self.presentation = None
180+ return False
181+
182+ def create_thumbnails(self):
183+ """
184+ Create the thumbnail images for the current presentation.
185+ """
186+ log.debug(u'create_thumbnails')
187+ if self.check_thumbnails():
188+ return
189+ thumbnail_folder = self.get_thumbnail_folder()
190+ if not os.path.exists(thumbnail_folder):
191+ os.makedirs(thumbnail_folder)
192+ try:
193+ self.controller.process.open(self.filepath)
194+ except appscript.CommandError:
195+ log.debug(u'KeyNote open failed')
196+ return
197+ temp_dir = self.controller.thumbnail_folder
198+ keystroke = os.path.join(temp_dir, u'temp' + self.controller.thumbnail_prefix)
199+ self.controller.process.activate()
200+ appscript.app(u'System Events').processes[u'Keynote'].menu_bars[1].menu_bar_items[3].menus.menu_items[11].click()
201+ appscript.app(u'System Events').processes[u'Keynote'].windows[1].sheets[1].tool_bars.buttons[4].click()
202+ appscript.app(u'System Events').processes[u'Keynote'].windows[1].sheets[1].radio_groups[1].radio_buttons[1].click()
203+ appscript.app(u'System Events').processes[u'Keynote'].windows[1].sheets[1].pop_up_buttons[1].click()
204+ appscript.app(u'System Events').processes[u'Keynote'].windows[1].sheets[1].pop_up_buttons[1]\
205+ .menus.menu_items[2].click()
206+ appscript.app(u'System Events').processes[u'Keynote'].windows[1].sheets[1].buttons[2].click()
207+ appscript.app(u'System Events').processes[u'Keynote'].keystroke(keystroke)
208+ appscript.app(u'System Events').processes[u'Keynote'].key_code(36)
209+ appscript.app(u'System Events').processes[u'Keynote'].windows[1].sheets[1].buttons[1].click()
210+ self.controller.plugin._main_window.activateWindow()
211+ slide_no = 0
212+ for filename in os.listdir(temp_dir):
213+ full_filename = os.path.join(temp_dir, filename)
214+ if not os.path.isfile(full_filename) or not filename.endswith(u'.png') or filename == u'icon.png':
215+ continue
216+ slide_no = slide_no + 1
217+ if not filename.startswith(self.controller.thumbnail_prefix):
218+ path = os.path.join(thumbnail_folder,
219+ self.controller.thumbnail_prefix + unicode(slide_no) + u'.png')
220+ try:
221+ os.rename(full_filename, path)
222+ except:
223+ open(path,'w').write(open(full_filename,'r').read())
224+ os.unlink(full_filename)
225+
226+ def close_presentation(self):
227+ """
228+ Close presentation and clean up objects. This is triggered by a new
229+ object being added to SlideController or OpenLP being shut down.
230+ """
231+ log.debug(u'ClosePresentation')
232+ if self.presentation:
233+ try:
234+ self.presentation.close()
235+ except appscript.CommandError:
236+ pass
237+ self.presentation = None
238+ self.controller.remove_doc(self)
239+
240+ def is_loaded(self):
241+ """
242+ Returns ``True`` if a presentation is loaded.
243+ """
244+ log.debug(u'is_loaded')
245+ try:
246+ if not self.controller.process.isrunning():
247+ return False
248+ windows = self.controller.process.windows()
249+ if len(windows) == 0:
250+ return False
251+ slideshows = self.controller.process.slideshows()
252+ if len(slideshows) == 0:
253+ return False
254+ except:
255+ return False
256+ for slideshow in slideshows:
257+ path = slideshow.path()
258+ if self.filepath == path:
259+ return True
260+ return False
261+
262+ def is_active(self):
263+ """
264+ Returns ``True`` if a presentation is currently active.
265+ """
266+ log.debug(u'is_active')
267+ if not self.is_loaded():
268+ return False
269+ try:
270+ if not self.presentation.playing():
271+ return False
272+ except appscript.CommandError:
273+ return False
274+ return True
275+
276+ def unblank_screen(self):
277+ """
278+ Unblanks (restores) the presentation.
279+ """
280+ log.debug(u'unblank_screen')
281+ if self.is_blank():
282+ slef.presentation.start_presentation()
283+
284+ def blank_screen(self):
285+ """
286+ Blanks the screen.
287+ """
288+ log.debug(u'blank_screen')
289+ self.presentation.stop_slideshow()
290+
291+ def is_blank(self):
292+ """
293+ Returns ``True`` if screen is blank.
294+ """
295+ log.debug(u'is_blank')
296+ if self.is_active():
297+ return not self.presentation.playing()
298+ else:
299+ return False
300+
301+ def stop_presentation(self):
302+ """
303+ Stops the current presentation and hides the output.
304+ """
305+ log.debug(u'stop_presentation')
306+ self.presentation.stop_slideshow()
307+
308+
309+ def start_presentation(self):
310+ """
311+ Starts a presentation from the beginning.
312+ """
313+ log.debug(u'start_presentation')
314+ if not self.is_active():
315+ self.controller.apply_app_settings()
316+ try:
317+ self.presentation.start()
318+ except appscript.CommandError:
319+ return
320+ rect = ScreenList().current[u'size']
321+ top = rect.y()
322+ height = rect.height()
323+ left_position = rect.x()
324+ width = rect.width()
325+ self.controller.process.windows[1].bounds.set([left_position, top, left_position + width, top + height])
326+
327+ def get_slide_number(self):
328+ """
329+ Returns the current slide number.
330+ """
331+ log.debug(u'get_slide_number')
332+ return self.presentation.current_slide().slide_number()
333+
334+ def get_slide_count(self):
335+ """
336+ Returns total number of slides.
337+ """
338+ log.debug(u'get_slide_count')
339+ slides = self.presentation.slides()
340+ return len(slides)
341+
342+ def goto_slide(self, slideno):
343+ """
344+ Moves to a specific slide in the presentation.
345+ """
346+ log.debug(u'goto_slide')
347+ slide = self.presentation.slides()[slideno-1]
348+ self.presentation.show(slide)
349+
350+ def next_step(self):
351+ """
352+ Triggers the next effect of slide on the running presentation.
353+ """
354+ log.debug(u'next_step')
355+ self.presentation.show_next()
356+ if self.get_slide_number() > self.get_slide_count():
357+ self.previous_step()
358+
359+ def previous_step(self):
360+ """
361+ Triggers the previous slide on the running presentation.
362+ """
363+ log.debug(u'previous_step')
364+ self.presentation.show_previous()
365+
366+ def get_slide_text(self, slide_no):
367+ """
368+ Returns the text on the slide.
369+
370+ ``slide_no``
371+ The slide the text is required for, starting at 1.
372+ """
373+ return self.presentation.slides[slide_no].body
374+
375+ def get_slide_notes(self, slide_no):
376+ """
377+ Returns the text on the slide.
378+
379+ ``slide_no``
380+ The slide the notes are required for, starting at 1.
381+ """
382+ return self.presentation.slides[slide_no].notes
383
384=== added file 'openlp/plugins/presentations/lib/powerpointmaccontroller.py'
385--- openlp/plugins/presentations/lib/powerpointmaccontroller.py 1970-01-01 00:00:00 +0000
386+++ openlp/plugins/presentations/lib/powerpointmaccontroller.py 2013-04-01 23:08:22 +0000
387@@ -0,0 +1,401 @@
388+# -*- coding: utf-8 -*-
389+# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
390+
391+###############################################################################
392+# OpenLP - Open Source Lyrics Projection #
393+# --------------------------------------------------------------------------- #
394+# Copyright (c) 2008-2012 Raoul Snyman #
395+# Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
396+# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub, #
397+# Meinert Jordan, Armin Köhler, Eric Ludin, Edwin Lunando, Brian T. Meyer, #
398+# Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias Põldaru, #
399+# Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
400+# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Dave Warnock, #
401+# Frode Woldsund, Martin Zibricky #
402+# --------------------------------------------------------------------------- #
403+# This program is free software; you can redistribute it and/or modify it #
404+# under the terms of the GNU General Public License as published by the Free #
405+# Software Foundation; version 2 of the License. #
406+# #
407+# This program is distributed in the hope that it will be useful, but WITHOUT #
408+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
409+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
410+# more details. #
411+# #
412+# You should have received a copy of the GNU General Public License along #
413+# with this program; if not, write to the Free Software Foundation, Inc., 59 #
414+# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
415+###############################################################################
416+
417+import os
418+import sys
419+import logging
420+import shutil
421+import mactypes
422+
423+import appscript
424+
425+from openlp.core.lib import Settings, ScreenList
426+from presentationcontroller import PresentationController, PresentationDocument
427+
428+
429+log = logging.getLogger(__name__)
430+
431+
432+class PowerpointController(PresentationController):
433+ """
434+ Class to control interactions with PowerPoint Presentations
435+ It creates the runtime Environment , Loads the and Closes the Presentation
436+ As well as triggering the correct activities based on the users input
437+ """
438+ log.info(u'PowerpointController loaded')
439+
440+ def __init__(self, plugin):
441+ """
442+ Initialise the class
443+ """
444+ log.debug(u'Initialising')
445+ PresentationController.__init__(self, plugin, u'Powerpoint', PowerpointDocument)
446+ self.supports = [u'ppt', u'pps', u'pptx', u'ppsx']
447+ self.process = None
448+
449+ def check_available(self):
450+ """
451+ PowerPoint is able to run on this machine
452+ """
453+ log.debug(u'check_available')
454+ try:
455+ self.process = appscript.app(id='com.microsoft.powerpoint')
456+ except appscript.ApplicationNotFoundError:
457+ return False
458+ self.kill()
459+ return True
460+
461+ def start_process(self):
462+ """
463+ Loads PowerPoint process
464+ """
465+ log.debug(u'start_process')
466+ if not self.process or not self.process.isrunning():
467+ self.process = appscript.app(id='com.microsoft.powerpoint')
468+ self.process.relaunchmode = 'limited' #'always'
469+ self.process.launch()
470+ self.apply_app_settings()
471+
472+ def kill(self):
473+ """
474+ Called at system exit to clean up any running presentations
475+ """
476+ log.debug(u'Kill Powerpoint')
477+ while self.docs and self.process.isrunning():
478+ self.docs[0].close_presentation()
479+ if self.process is None or not self.process.isrunning():
480+ return
481+ try:
482+ total = self.process.presentations()
483+ if self.process and total != appscript.k.missing_value and len(total) > 0:
484+ return
485+ self.process.quit(saving = appscript.k.ask)
486+ except appscript.CantLaunchApplicationError:
487+ pass
488+ self.process = None
489+
490+ def apply_app_settings(self):
491+ """
492+ Apply settings for PowerPoint
493+ 14\Options\Options\Save graphics screen heigth = 240
494+ 14\Options\Options\Save graphics screen width = 320
495+ 14\Options\Options\Save only current slide graphics = 0
496+
497+ """
498+ openlp_settings = Settings("openlp.org","OpenLP")
499+ ppt_settings = Settings("Microsoft", "Powerpoint")
500+# use_secondary = int(keynote_settings.value(u'PresentationModeUseSecondary', u''))
501+# monitor = openlp_settings.value( u'general/monitor', 0)
502+# display_on_monitor = openlp_settings.value( u'general/display on monitor', False)
503+# if display_on_monitor and use_secondary != monitor:
504+# keynote_settings.setValue(u'PresentationModeUseSecondary', unicode(monitor))
505+# elif not display_on_monitor and use_secondary > 0:
506+# keynote_settings.setValue(u'PresentationModeUseSecondary', u'0')
507+# show_presenter_view = openlp_settings.value(self.plugin.settingsSection + u'/show presenter view', False)
508+# keynote_feedback_display = keynote_settings.value(u'PresentationModeEnableFeedbackDisplay', False)
509+# if show_presenter_view != keynote_feedback_display:
510+# keynote_settings.setValue(u'PresentationModeEnableFeedbackDisplay', show_presenter_view)
511+
512+
513+class PowerpointDocument(PresentationDocument):
514+ """
515+ Class which holds information and controls a single presentation
516+ """
517+
518+ def __init__(self, controller, presentation):
519+ """
520+ Constructor, store information about the file and initialise
521+ """
522+ log.debug(u'Init Presentation Powerpoint')
523+ PresentationDocument.__init__(self, controller, presentation)
524+ self.presentation = None
525+
526+ def load_presentation(self):
527+ """
528+ Called when a presentation is added to the SlideController.
529+ Opens the PowerPoint file using the process created earlier.
530+ """
531+ log.debug(u'load_presentation')
532+ if not self.controller.process or not self.controller.process.isrunning():
533+ self.controller.start_process()
534+ try:
535+ self.controller.process.open(self.filepath)
536+ except appscript.CommandError:
537+ log.debug(u'PPT open failed')
538+ return False
539+ presentations = self.controller.process.presentations()
540+ for presentation in presentations:
541+ full_name = presentation.full_name()
542+ full_name = full_name.replace(u'Macintosh HD', u'')
543+ full_name = full_name.replace(u':', u'/')
544+ if self.filepath == full_name:
545+ self.presentation = presentation
546+ self.create_thumbnails()
547+ return True
548+ return False
549+
550+ def create_thumbnails(self):
551+ """
552+ Create the thumbnail images for the current presentation.
553+ """
554+ log.debug(u'create_thumbnails')
555+ if self.check_thumbnails():
556+ return
557+ thumbnail_folder = self.get_thumbnail_folder()
558+ self.presentation.save(in_ = thumbnail_folder, as_ = appscript.k.save_as_PNG)
559+ slide_no = 0
560+ temp_dir = os.path.join(thumbnail_folder, self.get_file_name())
561+ if not os.path.isdir(temp_dir):
562+# log.debug(u'create_thumbnails failed')
563+ temp_dir = thumbnail_folder
564+ for filename in os.listdir(temp_dir):
565+ full_filename = os.path.join(temp_dir, filename)
566+ if not os.path.isfile(full_filename) or not filename.endswith(u'.png') or filename == u'icon.png':
567+ continue
568+ slide_no = slide_no + 1
569+ if not filename.startswith(self.controller.thumbnail_prefix):
570+ path = os.path.join(thumbnail_folder,
571+ self.controller.thumbnail_prefix + unicode(slide_no) + u'.png')
572+ try:
573+ os.rename(full_filename, path)
574+ except:
575+ open(path,'w').write(open(full_filename,'r').read())
576+ os.unlink(full_filename)
577+ if temp_dir != thumbnail_folder:
578+ try:
579+ shutil.rmtree(temp_dir)
580+ except:
581+ pass
582+
583+ def close_presentation(self):
584+ """
585+ Close presentation and clean up objects. This is triggered by a new
586+ object being added to SlideController or OpenLP being shut down.
587+ """
588+ log.debug(u'ClosePresentation')
589+ if self.presentation:
590+ try:
591+ self.presentation.close()
592+ except appscript.CommandError:
593+ pass
594+ self.presentation = None
595+ self.controller.remove_doc(self)
596+
597+ def is_loaded(self):
598+ """
599+ Returns ``True`` if a presentation is loaded.
600+ """
601+ log.debug(u'is_loaded')
602+ try:
603+ if not self.controller.process.isrunning():
604+ return False
605+ if len(self.controller.process.document_windows()) == 0:
606+ return False
607+ presentations = self.controller.process.presentations()
608+ if len(presentations) == 0:
609+ return False
610+ except:
611+ return False
612+ for presentation in presentations:
613+ full_name = presentation.full_name()
614+ full_name = full_name.replace(u'Macintosh HD', u'')
615+ full_name = full_name.replace(u':', u'/')
616+ if self.filepath == full_name:
617+ return True
618+ return False
619+
620+ def is_active(self):
621+ """
622+ Returns ``True`` if a presentation is currently active.
623+ """
624+ log.debug(u'is_active')
625+ if not self.is_loaded():
626+ return False
627+ try:
628+ slide_show_window = self.presentation.slide_show_window
629+ if slide_show_window is None:
630+ return False
631+ slide_state = self.presentation.slide_show_window.slideshow_view.slide_state()
632+ if slide_state is None or slide_state == appscript.k.missing_value:
633+ return False
634+ except:
635+ return False
636+ return True
637+
638+ def unblank_screen(self):
639+ """
640+ Unblanks (restores) the presentation.
641+ """
642+ log.debug(u'unblank_screen')
643+ if self.is_blank():
644+ settings = self.presentation.slide_show_settings
645+ #settings.run_slide_show()
646+ self.presentation.slide_show_window.slideshow_view.slide_state.set(appscript.k.slide_show_state_running)
647+ self.presentation.slide_show_window.slideshow_view.go_to_next_slide()
648+ self.presentation.slide_show_window.slideshow_view.go_to_previous_slide()
649+
650+ def blank_screen(self):
651+ """
652+ Blanks the screen.
653+ """
654+ log.debug(u'blank_screen')
655+ self.presentation.slide_show_window.slideshow_view.slide_state.set(appscript.k.slide_show_state_black_screen)
656+
657+ def is_blank(self):
658+ """
659+ Returns ``True`` if screen is blank.
660+ """
661+ log.debug(u'is_blank')
662+ if self.is_active() and self.presentation.slide_show_window.slideshow_view\
663+ .slide_state() is appscript.k.slide_show_state_black_screen:
664+ return True
665+ else:
666+ return False
667+
668+ def stop_presentation(self):
669+ """
670+ Stops the current presentation and hides the output.
671+ """
672+ log.debug(u'stop_presentation')
673+ self.presentation.slide_show_window.slideshow_view.exit_slide_show()
674+
675+
676+ def start_presentation(self):
677+ """
678+ Starts a presentation from the beginning.
679+ """
680+ log.debug(u'start_presentation')
681+ rect = ScreenList().current[u'size']
682+ ppt_settings = self.presentation.slide_show_settings
683+ openlp_settings = Settings("openlp.org","OpenLP")
684+ show_presenter_view = openlp_settings.value(self.controller.plugin.settingsSection + u'/show presenter view')
685+ override_position = openlp_settings.value( u'general/override position')
686+ if show_presenter_view:
687+ ppt_settings.show_type.set(appscript.k.slide_show_type_presenter)
688+ elif override_position:
689+ ppt_settings.show_type.set(appscript.k.slide_show_type_window)
690+ else:
691+ ppt_settings.show_type.set(appscript.k.slide_show_type_kiosk)
692+ #ppt_settings.show_type.set(appscript.k.slide_show_type_speaker)
693+ ppt_window = ppt_settings.run_slide_show()
694+ #TODO set slideshow state = running
695+# if ppt_window.slideshow_view.slide_state() != appscript.k.slide_show_state_running:
696+# ppt_window.slideshow_view.slide_state.set(appscript.k.slide_show_state_running)
697+ if not ppt_window or show_presenter_view:
698+ return
699+ if override_position:
700+ top = float(rect.y())
701+ height = float(rect.height())
702+ left_position = float(rect.x())
703+ width = float(rect.width())
704+ ppt_window.top.set(top)
705+ ppt_window.height.set(height)
706+ ppt_window.left_position.set(left_position)
707+ ppt_window.width.set(width)
708+ else:
709+ #TODO set output monitor for fullscreen mode
710+ pass
711+
712+ def get_slide_number(self):
713+ """
714+ Returns the current slide number.
715+ """
716+ log.debug(u'get_slide_number')
717+ return self.presentation.slide_show_window.slideshow_view.current_show_position()
718+
719+ def get_slide_count(self):
720+ """
721+ Returns total number of slides.
722+ """
723+ log.debug(u'get_slide_count')
724+ return len(self.presentation.slides())
725+
726+ def goto_slide(self, slideno):
727+ """
728+ Moves to a specific slide in the presentation.
729+ """
730+ log.debug(u'goto_slide')
731+ #TODO this works. but needs to fix this dumb code
732+ while self.get_slide_number() != slideno:
733+ if self.get_slide_number() < slideno:
734+ self.presentation.slide_show_window.slideshow_view.go_to_next_slide()
735+ else:
736+ self.presentation.slide_show_window.slideshow_view.go_to_previous_slide()
737+ self.controller.process.activate()
738+
739+ def next_step(self):
740+ """
741+ Triggers the next effect of slide on the running presentation.
742+ """
743+ log.debug(u'next_step')
744+ self.presentation.slide_show_window.slideshow_view.go_to_next_slide()
745+ self.controller.process.activate()
746+ if self.get_slide_number() > self.get_slide_count():
747+ self.previous_step()
748+
749+ def previous_step(self):
750+ """
751+ Triggers the previous slide on the running presentation.
752+ """
753+ log.debug(u'previous_step')
754+ self.presentation.slide_show_window.slideshow_view.go_to_previous_slide()
755+ self.controller.process.activate()
756+
757+ def get_slide_text(self, slide_no):
758+ """
759+ Returns the text on the slide.
760+
761+ ``slide_no``
762+ The slide the text is required for, starting at 1.
763+ """
764+ return _get_text_from_shapes(self.presentation.slides[slide_no-1].shapes)
765+
766+ def get_slide_notes(self, slide_no):
767+ """
768+ Returns the text on the slide.
769+
770+ ``slide_no``
771+ The slide the notes are required for, starting at 1.
772+ """
773+ return _get_text_from_shapes(
774+ self.presentation.slides[slide_no].notes_page.shapes())
775+
776+def _get_text_from_shapes(shapes):
777+ """
778+ Returns any text extracted from the shapes on a presentation slide.
779+
780+ ``shapes``
781+ A set of shapes to search for text.
782+ """
783+ text = u''
784+ for idx in range(len(shapes)):
785+ shape = shapes[idx + 1]
786+ if shape.has_text_frame():
787+ text += shape.text_frame.text_range.content() + '\n'
788+ return text
789
790=== modified file 'openlp/plugins/presentations/lib/presentationtab.py'
791--- openlp/plugins/presentations/lib/presentationtab.py 2013-03-16 21:18:05 +0000
792+++ openlp/plugins/presentations/lib/presentationtab.py 2013-04-01 23:08:22 +0000
793@@ -30,6 +30,7 @@
794 from PyQt4 import QtGui
795
796 from openlp.core.lib import Settings, SettingsTab, UiStrings, translate
797+import sys
798
799
800 class PresentationTab(SettingsTab):
801@@ -60,6 +61,7 @@
802 controller = self.controllers[key]
803 checkbox = QtGui.QCheckBox(self.controllers_group_box)
804 checkbox.setObjectName(controller.name + u'CheckBox')
805+<<<<<<< TREE
806 self.presenter_check_boxes[controller.name] = checkbox
807 self.controllers_layout.addWidget(checkbox)
808 self.left_layout.addWidget(self.controllers_group_box)
809@@ -73,6 +75,26 @@
810 self.left_layout.addWidget(self.advanced_group_box)
811 self.left_layout.addStretch()
812 self.right_layout.addStretch()
813+=======
814+ self.PresenterCheckboxes[controller.name] = checkbox
815+ self.ControllersLayout.addWidget(checkbox)
816+ self.leftLayout.addWidget(self.ControllersGroupBox)
817+ self.AdvancedGroupBox = QtGui.QGroupBox(self.leftColumn)
818+ self.AdvancedGroupBox.setObjectName(u'AdvancedGroupBox')
819+ self.AdvancedLayout = QtGui.QVBoxLayout(self.AdvancedGroupBox)
820+ self.AdvancedLayout.setObjectName(u'AdvancedLayout')
821+ self.OverrideAppCheckBox = QtGui.QCheckBox(self.AdvancedGroupBox)
822+ self.OverrideAppCheckBox.setObjectName(u'OverrideAppCheckBox')
823+ self.AdvancedLayout.addWidget(self.OverrideAppCheckBox)
824+ self.ShowPresenterViewCheckBox = QtGui.QCheckBox(self.AdvancedGroupBox)
825+ self.ShowPresenterViewCheckBox.setObjectName(u'ShowPresenterViewCheckBox')
826+ self.AdvancedLayout.addWidget(self.ShowPresenterViewCheckBox)
827+ if not sys.platform.startswith('darwin'):
828+ self.ShowPresenterViewCheckBox.setVisible(False)
829+ self.leftLayout.addWidget(self.AdvancedGroupBox)
830+ self.leftLayout.addStretch()
831+ self.rightLayout.addStretch()
832+>>>>>>> MERGE-SOURCE
833
834 def retranslateUi(self):
835 """
836@@ -86,6 +108,8 @@
837 self.advanced_group_box.setTitle(UiStrings().Advanced)
838 self.override_app_check_box.setText(
839 translate('PresentationPlugin.PresentationTab', 'Allow presentation application to be overridden'))
840+ self.ShowPresenterViewCheckBox.setText(
841+ translate('PresentationPlugin.PresentationTab', 'Show Presenter View'))
842
843 def set_controller_text(self, checkbox, controller):
844 if checkbox.isEnabled():
845@@ -100,9 +124,16 @@
846 """
847 for key in self.controllers:
848 controller = self.controllers[key]
849+<<<<<<< TREE
850 checkbox = self.presenter_check_boxes[controller.name]
851 checkbox.setChecked(Settings().value(self.settings_section + u'/' + controller.name))
852 self.override_app_check_box.setChecked(Settings().value(self.settings_section + u'/override app'))
853+=======
854+ checkbox = self.PresenterCheckboxes[controller.name]
855+ checkbox.setChecked(Settings().value(self.settingsSection + u'/' + controller.name))
856+ self.OverrideAppCheckBox.setChecked(Settings().value(self.settingsSection + u'/override app'))
857+ self.ShowPresenterViewCheckBox.setChecked(Settings().value(self.settingsSection + u'/show presenter view'))
858+>>>>>>> MERGE-SOURCE
859
860 def save(self):
861 """
862@@ -128,6 +159,10 @@
863 if Settings().value(setting_key) != self.override_app_check_box.checkState():
864 Settings().setValue(setting_key, self.override_app_check_box.checkState())
865 changed = True
866+ setting_key = self.settingsSection + u'/show presenter view'
867+ if Settings().value(setting_key) != self.ShowPresenterViewCheckBox.checkState():
868+ Settings().setValue(setting_key, self.ShowPresenterViewCheckBox.isChecked())
869+ changed = True
870 if changed:
871 self.settings_form.register_post_process(u'mediaitem_suffix_reset')
872 self.settings_form.register_post_process(u'mediaitem_presentation_rebuild')
873
874=== modified file 'openlp/plugins/presentations/presentationplugin.py'
875--- openlp/plugins/presentations/presentationplugin.py 2013-03-19 19:43:22 +0000
876+++ openlp/plugins/presentations/presentationplugin.py 2013-04-01 23:08:22 +0000
877@@ -31,6 +31,7 @@
878 presentations from a variety of document formats.
879 """
880 import os
881+import sys
882 import logging
883
884 from PyQt4 import QtCore
885@@ -46,6 +47,11 @@
886 u'presentations/Impress': QtCore.Qt.Checked,
887 u'presentations/Powerpoint': QtCore.Qt.Checked,
888 u'presentations/Powerpoint Viewer': QtCore.Qt.Checked,
889+ u'presentations/Keynote': QtCore.Qt.Checked,
890+ u'presentations/show presenter view': QtCore.Qt.Checked,
891+ u'PresentationModeUseSecondary': u'',
892+ u'PresentationModeEnableFeedbackDisplay': False,
893+ u'PresentationModePlayWellWithOthers': False,
894 u'presentations/presentations files': []
895 }
896
897@@ -130,6 +136,12 @@
898 u'presentations', u'lib')
899 for filename in os.listdir(controller_dir):
900 if filename.endswith(u'controller.py') and not filename == 'presentationcontroller.py':
901+ if not sys.platform.startswith('darwin') and filename == 'powerpointmaccontroller.py':
902+ continue
903+ if not sys.platform.startswith('darwin') and filename == 'keynotemaccontroller.py':
904+ continue
905+ if not sys.platform.startswith('win') and filename == 'powerpointcontroller.py':
906+ continue
907 path = os.path.join(controller_dir, filename)
908 if os.path.isfile(path):
909 module_name = u'openlp.plugins.presentations.lib.' + os.path.splitext(filename)[0]
910
911=== modified file 'scripts/check_dependencies.py'
912--- scripts/check_dependencies.py 2013-03-14 10:51:49 +0000
913+++ scripts/check_dependencies.py 2013-04-01 23:08:22 +0000
914@@ -47,6 +47,7 @@
915 pass
916
917 IS_WIN = sys.platform.startswith('win')
918+IS_OSX = sys.platform.startswith('darwin')
919
920 VERS = {
921 'Python': '2.6',
922@@ -64,6 +65,11 @@
923 'pywintypes',
924 ]
925
926+# OSX
927+OSX_MODULES = [
928+ 'appscript',
929+ 'mactypes',
930+]
931 MODULES = [
932 'PyQt4',
933 'PyQt4.QtCore',
934@@ -187,6 +193,11 @@
935 print('Checking for Windows specific modules...')
936 for m in WIN32_MODULES:
937 check_module(m)
938+
939+ if IS_OSX:
940+ print('Checking for OS X specific modules...')
941+ for m in OSX_MODULES:
942+ check_module(m)
943
944 verify_versions()
945 verify_pyqt()