Dmitriy Marmyshev has proposed merging lp:~marmyshev/openlp/presentation into lp:openlp.
Requested reviews: matysek (mzibricky) Andreas Preikschat (googol) Related bugs: Bug #836574 in OpenLP: "PowerPoint Presentations with Office for Mac" https://bugs.launchpad.net/openlp/+bug/836574 For more details, see: https://code.launchpad.net/~marmyshev/openlp/presentation/+merge/156713 Add support to load presentations with PowerPoint and Keynote on Mac OS X. -- https://code.launchpad.net/~marmyshev/openlp/presentation/+merge/156713 Your team OpenLP Core is subscribed to branch lp:openlp.
=== modified file 'openlp/core/lib/pluginmanager.py' --- openlp/core/lib/pluginmanager.py 2013-03-19 19:43:22 +0000 +++ openlp/core/lib/pluginmanager.py 2013-04-02 22:38:33 +0000 @@ -94,11 +94,6 @@ present_plugin_dir = os.path.join(self.base_path, 'presentations') log.debug(u'finding plugins in %s at depth %d', unicode(self.base_path), start_depth) for root, dirs, files in os.walk(self.base_path): - if sys.platform == 'darwin' and root.startswith(present_plugin_dir): - # TODO Presentation plugin is not yet working on Mac OS X. - # For now just ignore it. The following code will ignore files from the presentation plugin directory - # and thereby never import the plugin. - continue for name in files: if name.endswith(u'.py') and not name.startswith(u'__'): path = os.path.abspath(os.path.join(root, name)) === modified file 'openlp/core/ui/firsttimeform.py' --- openlp/core/ui/firsttimeform.py 2013-03-14 22:22:18 +0000 +++ openlp/core/ui/firsttimeform.py 2013-04-02 22:38:33 +0000 @@ -413,10 +413,7 @@ self._incrementProgressBar(translate('OpenLP.FirstTimeWizard', 'Enabling selected plugins...')) self._setPluginStatus(self.songsCheckBox, u'songs/status') self._setPluginStatus(self.bibleCheckBox, u'bibles/status') - # TODO Presentation plugin is not yet working on Mac OS X. - # For now just ignore it. - if sys.platform != 'darwin': - self._setPluginStatus(self.presentationCheckBox, u'presentations/status') + self._setPluginStatus(self.presentationCheckBox, u'presentations/status') self._setPluginStatus(self.imageCheckBox, u'images/status') self._setPluginStatus(self.mediaCheckBox, u'media/status') self._setPluginStatus(self.remoteCheckBox, u'remotes/status') === modified file 'openlp/core/ui/firsttimewizard.py' --- openlp/core/ui/firsttimewizard.py 2013-03-08 08:14:39 +0000 +++ openlp/core/ui/firsttimewizard.py 2013-04-02 22:38:33 +0000 @@ -93,13 +93,10 @@ self.imageCheckBox.setChecked(True) self.imageCheckBox.setObjectName(u'imageCheckBox') self.pluginLayout.addWidget(self.imageCheckBox) - # TODO Presentation plugin is not yet working on Mac OS X. - # For now just ignore it. - if sys.platform != 'darwin': - self.presentationCheckBox = QtGui.QCheckBox(self.pluginPage) - self.presentationCheckBox.setChecked(True) - self.presentationCheckBox.setObjectName(u'presentationCheckBox') - self.pluginLayout.addWidget(self.presentationCheckBox) + self.presentationCheckBox = QtGui.QCheckBox(self.pluginPage) + self.presentationCheckBox.setChecked(True) + self.presentationCheckBox.setObjectName(u'presentationCheckBox') + self.pluginLayout.addWidget(self.presentationCheckBox) self.mediaCheckBox = QtGui.QCheckBox(self.pluginPage) self.mediaCheckBox.setChecked(True) self.mediaCheckBox.setObjectName(u'mediaCheckBox') @@ -219,10 +216,7 @@ self.customCheckBox.setText(translate('OpenLP.FirstTimeWizard', 'Custom Slides')) self.bibleCheckBox.setText(translate('OpenLP.FirstTimeWizard', 'Bible')) self.imageCheckBox.setText(translate('OpenLP.FirstTimeWizard', 'Images')) - # TODO Presentation plugin is not yet working on Mac OS X. - # For now just ignore it. - if sys.platform != 'darwin': - self.presentationCheckBox.setText(translate('OpenLP.FirstTimeWizard', 'Presentations')) + self.presentationCheckBox.setText(translate('OpenLP.FirstTimeWizard', 'Presentations')) self.mediaCheckBox.setText(translate('OpenLP.FirstTimeWizard', 'Media (Audio and Video)')) self.remoteCheckBox.setText(translate('OpenLP.FirstTimeWizard', 'Allow remote access')) self.songUsageCheckBox.setText(translate('OpenLP.FirstTimeWizard', 'Monitor Song Usage')) === added file 'openlp/plugins/presentations/lib/keynotemaccontroller.py' --- openlp/plugins/presentations/lib/keynotemaccontroller.py 1970-01-01 00:00:00 +0000 +++ openlp/plugins/presentations/lib/keynotemaccontroller.py 2013-04-02 22:38:33 +0000 @@ -0,0 +1,362 @@ +# -*- coding: utf-8 -*- +# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4 + +############################################################################### +# OpenLP - Open Source Lyrics Projection # +# --------------------------------------------------------------------------- # +# Copyright (c) 2008-2012 Raoul Snyman # +# Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan # +# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub, # +# Meinert Jordan, Armin Köhler, Eric Ludin, Edwin Lunando, Brian T. Meyer, # +# Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias Põldaru, # +# Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # +# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Dave Warnock, # +# Frode Woldsund, Martin Zibricky # +# --------------------------------------------------------------------------- # +# This program is free software; you can redistribute it and/or modify it # +# under the terms of the GNU General Public License as published by the Free # +# Software Foundation; version 2 of the License. # +# # +# This program is distributed in the hope that it will be useful, but WITHOUT # +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # +# more details. # +# # +# You should have received a copy of the GNU General Public License along # +# with this program; if not, write to the Free Software Foundation, Inc., 59 # +# Temple Place, Suite 330, Boston, MA 02111-1307 USA # +############################################################################### + +import os +import sys +import logging +import mactypes + +import appscript + +from openlp.core.lib import Settings, ScreenList +from presentationcontroller import PresentationController, PresentationDocument + + +log = logging.getLogger(__name__) + + +class KeynoteController(PresentationController): + """ + Class to control interactions with KeyNote Presentations + It creates the runtime Environment , Loads the and Closes the Presentation + As well as triggering the correct activities based on the users input + """ + log.info(u'KeynoteController loaded') + + def __init__(self, plugin): + """ + Initialise the class + """ + log.debug(u'Initialising') + PresentationController.__init__(self, plugin, u'Keynote', KeynoteDocument) + self.supports = [u'key'] + self.process = None + + def check_available(self): + """ + KeyNote is able to run on this machine + """ + log.debug(u'check_available') + try: + self.process = appscript.app('Keynote') + except appscript.ApplicationNotFoundError: + return False + self.kill() + return True + + def start_process(self): + """ + Loads KeyNote process + """ + log.debug(u'start_process') + if not self.process or not self.process.isrunning(): + self.process = appscript.app('Keynote') + self.process.relaunchmode = 'limited' #'always' + self.process.launch() + self.apply_app_settings() + + def kill(self): + """ + Called at system exit to clean up any running presentations + """ + log.debug(u'Kill Keynote') + while self.docs and self.process.isrunning(): + self.docs[0].close_presentation() + if self.process is None or not self.process.isrunning(): + return + try: + total = self.process.slideshows() + if self.process and total != appscript.k.missing_value and len(total) > 0: + return + self.process.quit(saving = appscript.k.ask) + except appscript.CantLaunchApplicationError: + pass + self.process = None + + def apply_app_settings(self): + """ + Apply settings for Keynote + PresentationModeEnableFeedbackDisplay = True if in settings of OpenLP show presenter view = True + PresentationModeUseSecondary = 1 if OpenLP monitor for output = Screen 2 + """ + openlp_settings = Settings(u'openlp.org',u'OpenLP') + keynote_settings = Settings(u'apple', u'iWork.Keynote') + use_secondary = int(keynote_settings.value(u'PresentationModeUseSecondary')) + monitor = openlp_settings.value( u'general/monitor') + override_position = openlp_settings.value( u'general/override position') + if not override_position and use_secondary != monitor: + keynote_settings.setValue(u'PresentationModeUseSecondary', unicode(monitor)) + elif override_position and use_secondary != 0: + keynote_settings.setValue(u'PresentationModeUseSecondary', u'0') + show_presenter_view = openlp_settings.value(self.plugin.settings_section + u'/show presenter view') + keynote_feedback_display = keynote_settings.value(u'PresentationModeEnableFeedbackDisplay') + if show_presenter_view != keynote_feedback_display: + keynote_settings.setValue(u'PresentationModeEnableFeedbackDisplay', show_presenter_view) + play_well_with_others = keynote_settings.value(u'PresentationModePlayWellWithOthers') + if not play_well_with_others: + keynote_settings.setValue(u'PresentationModePlayWellWithOthers', True) + + +class KeynoteDocument(PresentationDocument): + """ + Class which holds information and controls a single presentation + """ + + def __init__(self, controller, presentation): + """ + Constructor, store information about the file and initialise + """ + log.debug(u'Init Presentation Keynote') + PresentationDocument.__init__(self, controller, presentation) + self.presentation = None + + def load_presentation(self): + """ + Called when a presentation is added to the SlideController. + Opens the Keynote file using the process created earlier. + """ + log.debug(u'load_presentation') + if not self.controller.process or not self.controller.process.isrunning(): + self.controller.start_process() + try: + self.controller.process.open(self.filepath) + except appscript.CommandError: + log.debug(u'Keynote open failed') + return False + slideshows = self.controller.process.slideshows() + for slideshow in slideshows: + path = slideshow.path() + if self.filepath == path: + self.presentation = slideshow + self.create_thumbnails() + return True + self.presentation = None + return False + + def create_thumbnails(self): + """ + Create the thumbnail images for the current presentation. + """ + log.debug(u'create_thumbnails') + if self.check_thumbnails(): + return + thumbnail_folder = self.get_thumbnail_folder() + if not os.path.exists(thumbnail_folder): + os.makedirs(thumbnail_folder) + try: + self.controller.process.open(self.filepath) + except appscript.CommandError: + log.debug(u'KeyNote open failed') + return + temp_dir = self.controller.thumbnail_folder + keystroke = os.path.join(temp_dir, u'temp' + self.controller.thumbnail_prefix) + self.controller.process.activate() + appscript.app(u'System Events').processes[u'Keynote'].menu_bars[1].menu_bar_items[3].menus.menu_items[11].click() + appscript.app(u'System Events').processes[u'Keynote'].windows[1].sheets[1].tool_bars.buttons[4].click() + appscript.app(u'System Events').processes[u'Keynote'].windows[1].sheets[1].radio_groups[1].radio_buttons[1].click() + appscript.app(u'System Events').processes[u'Keynote'].windows[1].sheets[1].pop_up_buttons[1].click() + appscript.app(u'System Events').processes[u'Keynote'].windows[1].sheets[1].pop_up_buttons[1]\ + .menus.menu_items[2].click() + appscript.app(u'System Events').processes[u'Keynote'].windows[1].sheets[1].buttons[2].click() + appscript.app(u'System Events').processes[u'Keynote'].keystroke(keystroke) + appscript.app(u'System Events').processes[u'Keynote'].key_code(36) + appscript.app(u'System Events').processes[u'Keynote'].windows[1].sheets[1].buttons[1].click() + self.controller.plugin._main_window.activateWindow() + slide_no = 0 + for filename in os.listdir(temp_dir): + full_filename = os.path.join(temp_dir, filename) + if not os.path.isfile(full_filename) or not filename.endswith(u'.png') or filename == u'icon.png': + continue + slide_no = slide_no + 1 + if not filename.startswith(self.controller.thumbnail_prefix): + path = os.path.join(thumbnail_folder, + self.controller.thumbnail_prefix + unicode(slide_no) + u'.png') + try: + os.rename(full_filename, path) + except: + open(path,'w').write(open(full_filename,'r').read()) + os.unlink(full_filename) + + def close_presentation(self): + """ + Close presentation and clean up objects. This is triggered by a new + object being added to SlideController or OpenLP being shut down. + """ + log.debug(u'ClosePresentation') + if self.presentation: + try: + self.presentation.close() + except appscript.CommandError: + pass + self.presentation = None + self.controller.remove_doc(self) + + def is_loaded(self): + """ + Returns ``True`` if a presentation is loaded. + """ + log.debug(u'is_loaded') + try: + if not self.controller.process.isrunning(): + return False + windows = self.controller.process.windows() + if len(windows) == 0: + return False + slideshows = self.controller.process.slideshows() + if len(slideshows) == 0: + return False + except: + return False + for slideshow in slideshows: + path = slideshow.path() + if self.filepath == path: + return True + return False + + def is_active(self): + """ + Returns ``True`` if a presentation is currently active. + """ + log.debug(u'is_active') + if not self.is_loaded(): + return False + try: + if not self.presentation.playing(): + return False + except appscript.CommandError: + return False + return True + + def unblank_screen(self): + """ + Unblanks (restores) the presentation. + """ + log.debug(u'unblank_screen') + if self.is_blank(): + slef.presentation.start_presentation() + + def blank_screen(self): + """ + Blanks the screen. + """ + log.debug(u'blank_screen') + self.presentation.stop_slideshow() + + def is_blank(self): + """ + Returns ``True`` if screen is blank. + """ + log.debug(u'is_blank') + if self.is_active(): + return not self.presentation.playing() + else: + return False + + def stop_presentation(self): + """ + Stops the current presentation and hides the output. + """ + log.debug(u'stop_presentation') + self.presentation.stop_slideshow() + + + def start_presentation(self): + """ + Starts a presentation from the beginning. + """ + log.debug(u'start_presentation') + if not self.is_active(): + self.controller.apply_app_settings() + try: + self.presentation.start() + except appscript.CommandError: + return + rect = ScreenList().current[u'size'] + top = rect.y() + height = rect.height() + left_position = rect.x() + width = rect.width() + self.controller.process.windows[1].bounds.set([left_position, top, left_position + width, top + height]) + + def get_slide_number(self): + """ + Returns the current slide number. + """ + log.debug(u'get_slide_number') + return self.presentation.current_slide().slide_number() + + def get_slide_count(self): + """ + Returns total number of slides. + """ + log.debug(u'get_slide_count') + slides = self.presentation.slides() + return len(slides) + + def goto_slide(self, slideno): + """ + Moves to a specific slide in the presentation. + """ + log.debug(u'goto_slide') + slide = self.presentation.slides()[slideno-1] + self.presentation.show(slide) + + def next_step(self): + """ + Triggers the next effect of slide on the running presentation. + """ + log.debug(u'next_step') + self.presentation.show_next() + if self.get_slide_number() > self.get_slide_count(): + self.previous_step() + + def previous_step(self): + """ + Triggers the previous slide on the running presentation. + """ + log.debug(u'previous_step') + self.presentation.show_previous() + + def get_slide_text(self, slide_no): + """ + Returns the text on the slide. + + ``slide_no`` + The slide the text is required for, starting at 1. + """ + return self.presentation.slides[slide_no].body + + def get_slide_notes(self, slide_no): + """ + Returns the text on the slide. + + ``slide_no`` + The slide the notes are required for, starting at 1. + """ + return self.presentation.slides[slide_no].notes === added file 'openlp/plugins/presentations/lib/powerpointmaccontroller.py' --- openlp/plugins/presentations/lib/powerpointmaccontroller.py 1970-01-01 00:00:00 +0000 +++ openlp/plugins/presentations/lib/powerpointmaccontroller.py 2013-04-02 22:38:33 +0000 @@ -0,0 +1,405 @@ +# -*- coding: utf-8 -*- +# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4 + +############################################################################### +# OpenLP - Open Source Lyrics Projection # +# --------------------------------------------------------------------------- # +# Copyright (c) 2008-2012 Raoul Snyman # +# Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan # +# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub, # +# Meinert Jordan, Armin Köhler, Eric Ludin, Edwin Lunando, Brian T. Meyer, # +# Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias Põldaru, # +# Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # +# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Dave Warnock, # +# Frode Woldsund, Martin Zibricky # +# --------------------------------------------------------------------------- # +# This program is free software; you can redistribute it and/or modify it # +# under the terms of the GNU General Public License as published by the Free # +# Software Foundation; version 2 of the License. # +# # +# This program is distributed in the hope that it will be useful, but WITHOUT # +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # +# more details. # +# # +# You should have received a copy of the GNU General Public License along # +# with this program; if not, write to the Free Software Foundation, Inc., 59 # +# Temple Place, Suite 330, Boston, MA 02111-1307 USA # +############################################################################### + +import os +import sys +import logging +import shutil +import mactypes + +import appscript + +from openlp.core.lib import Settings, ScreenList +from presentationcontroller import PresentationController, PresentationDocument + + +log = logging.getLogger(__name__) + + +class PowerpointController(PresentationController): + """ + Class to control interactions with PowerPoint Presentations + It creates the runtime Environment , Loads the and Closes the Presentation + As well as triggering the correct activities based on the users input + """ + log.info(u'PowerpointController loaded') + + def __init__(self, plugin): + """ + Initialise the class + """ + log.debug(u'Initialising') + PresentationController.__init__(self, plugin, u'Powerpoint', PowerpointDocument) + self.supports = [u'ppt', u'pps', u'pptx', u'ppsx'] + self.process = None + + def check_available(self): + """ + PowerPoint is able to run on this machine + """ + log.debug(u'check_available') + try: + self.process = appscript.app(id='com.microsoft.powerpoint') + except appscript.ApplicationNotFoundError: + return False + self.kill() + return True + + def start_process(self): + """ + Loads PowerPoint process + """ + log.debug(u'start_process') + if not self.process or not self.process.isrunning(): + self.process = appscript.app(id='com.microsoft.powerpoint') + self.process.relaunchmode = 'limited' #'always' + self.process.launch() + self.apply_app_settings() + + def kill(self): + """ + Called at system exit to clean up any running presentations + """ + log.debug(u'Kill Powerpoint') + while self.docs and self.process.isrunning(): + self.docs[0].close_presentation() + if self.process is None or not self.process.isrunning(): + return + try: + total = self.process.presentations() + if self.process and total != appscript.k.missing_value and len(total) > 0: + return + self.process.quit(saving = appscript.k.ask) + except appscript.CantLaunchApplicationError: + pass + self.process = None + + def apply_app_settings(self): + """ + Apply settings for PowerPoint + 14\Options\Options\Save graphics screen heigth = 240 + 14\Options\Options\Save graphics screen width = 320 + 14\Options\Options\Save only current slide graphics = 0 + + """ + openlp_settings = Settings("openlp.org","OpenLP") + ppt_settings = Settings("Microsoft", "Powerpoint") +# use_secondary = int(keynote_settings.value(u'PresentationModeUseSecondary', u'')) +# monitor = openlp_settings.value( u'general/monitor', 0) +# display_on_monitor = openlp_settings.value( u'general/display on monitor', False) +# if display_on_monitor and use_secondary != monitor: +# keynote_settings.setValue(u'PresentationModeUseSecondary', unicode(monitor)) +# elif not display_on_monitor and use_secondary > 0: +# keynote_settings.setValue(u'PresentationModeUseSecondary', u'0') +# show_presenter_view = openlp_settings.value(self.plugin.settings_section + u'/show presenter view', False) +# keynote_feedback_display = keynote_settings.value(u'PresentationModeEnableFeedbackDisplay', False) +# if show_presenter_view != keynote_feedback_display: +# keynote_settings.setValue(u'PresentationModeEnableFeedbackDisplay', show_presenter_view) + + +class PowerpointDocument(PresentationDocument): + """ + Class which holds information and controls a single presentation + """ + + def __init__(self, controller, presentation): + """ + Constructor, store information about the file and initialise + """ + log.debug(u'Init Presentation Powerpoint') + PresentationDocument.__init__(self, controller, presentation) + self.presentation = None + + def load_presentation(self): + """ + Called when a presentation is added to the SlideController. + Opens the PowerPoint file using the process created earlier. + """ + log.debug(u'load_presentation') + if not self.controller.process or not self.controller.process.isrunning(): + self.controller.start_process() + try: + self.controller.process.open(self.filepath) + except appscript.CommandError: + log.debug(u'PPT open failed') + return False + presentations = self.controller.process.presentations() + for presentation in presentations: + full_name = presentation.full_name() + full_name = full_name.replace(u'Macintosh HD', u'') + full_name = full_name.replace(u':', u'/') + if self.filepath == full_name: + self.presentation = presentation + self.create_thumbnails() + return True + return False + + def create_thumbnails(self): + """ + Create the thumbnail images for the current presentation. + """ + log.debug(u'create_thumbnails') + if self.check_thumbnails(): + return + thumbnail_folder = self.get_thumbnail_folder() + self.presentation.save(in_ = thumbnail_folder, as_ = appscript.k.save_as_PNG) + slide_no = 0 + temp_dir = os.path.join(thumbnail_folder, self.get_file_name()) + if not os.path.isdir(temp_dir): +# log.debug(u'create_thumbnails failed') + temp_dir = thumbnail_folder + for filename in os.listdir(temp_dir): + full_filename = os.path.join(temp_dir, filename) + if not os.path.isfile(full_filename) or not filename.endswith(u'.png') or filename == u'icon.png': + continue + slide_no = slide_no + 1 + if not filename.startswith(self.controller.thumbnail_prefix): + path = os.path.join(thumbnail_folder, + self.controller.thumbnail_prefix + unicode(slide_no) + u'.png') + try: + os.rename(full_filename, path) + except: + open(path,'w').write(open(full_filename,'r').read()) + os.unlink(full_filename) + if temp_dir != thumbnail_folder: + try: + shutil.rmtree(temp_dir) + except: + pass + + def close_presentation(self): + """ + Close presentation and clean up objects. This is triggered by a new + object being added to SlideController or OpenLP being shut down. + """ + log.debug(u'ClosePresentation') + if self.presentation: + try: + self.presentation.close() + except appscript.CommandError: + pass + self.presentation = None + self.controller.remove_doc(self) + + def is_loaded(self): + """ + Returns ``True`` if a presentation is loaded. + """ + log.debug(u'is_loaded') + try: + if not self.controller.process.isrunning(): + return False + if len(self.controller.process.document_windows()) == 0: + return False + presentations = self.controller.process.presentations() + if len(presentations) == 0: + return False + except: + return False + for presentation in presentations: + full_name = presentation.full_name() + full_name = full_name.replace(u'Macintosh HD', u'') + full_name = full_name.replace(u':', u'/') + if self.filepath == full_name: + return True + return False + + def is_active(self): + """ + Returns ``True`` if a presentation is currently active. + """ + log.debug(u'is_active') + if not self.is_loaded(): + return False + try: + slide_show_window = self.presentation.slide_show_window + if slide_show_window is None: + return False + slide_state = self.presentation.slide_show_window.slideshow_view.slide_state() + if slide_state is None or slide_state == appscript.k.missing_value: + return False + except: + return False + return True + + def unblank_screen(self): + """ + Unblanks (restores) the presentation. + """ + log.debug(u'unblank_screen') + if self.is_blank(): + settings = self.presentation.slide_show_settings + #settings.run_slide_show() + self.presentation.slide_show_window.slideshow_view.slide_state.set(appscript.k.slide_show_state_running) + self.presentation.slide_show_window.slideshow_view.go_to_next_slide() + self.presentation.slide_show_window.slideshow_view.go_to_previous_slide() + + def blank_screen(self): + """ + Blanks the screen. + """ + log.debug(u'blank_screen') + self.presentation.slide_show_window.slideshow_view.slide_state.set(appscript.k.slide_show_state_black_screen) + + def is_blank(self): + """ + Returns ``True`` if screen is blank. + """ + log.debug(u'is_blank') + if self.is_active() and self.presentation.slide_show_window.slideshow_view\ + .slide_state() is appscript.k.slide_show_state_black_screen: + return True + else: + return False + + def stop_presentation(self): + """ + Stops the current presentation and hides the output. + """ + log.debug(u'stop_presentation') + self.presentation.slide_show_window.slideshow_view.exit_slide_show() + + + def start_presentation(self): + """ + Starts a presentation from the beginning. + """ + log.debug(u'start_presentation') + rect = ScreenList().current[u'size'] + ppt_settings = self.presentation.slide_show_settings + openlp_settings = Settings("openlp.org","OpenLP") + show_presenter_view = openlp_settings.value(self.controller.plugin.settings_section + u'/show presenter view') + override_position = openlp_settings.value( u'general/override position') + if show_presenter_view: + ppt_settings.show_type.set(appscript.k.slide_show_type_presenter) + elif override_position: + ppt_settings.show_type.set(appscript.k.slide_show_type_window) + else: + ppt_settings.show_type.set(appscript.k.slide_show_type_kiosk) + #ppt_settings.show_type.set(appscript.k.slide_show_type_speaker) + ppt_window = ppt_settings.run_slide_show() + #TODO: set slideshow state = running +# if ppt_window.slideshow_view.slide_state() != appscript.k.slide_show_state_running: +# ppt_window.slideshow_view.slide_state.set(appscript.k.slide_show_state_running) + if not ppt_window or show_presenter_view: + return + if override_position: + top = float(rect.y()) + height = float(rect.height()) + left_position = float(rect.x()) + width = float(rect.width()) + ppt_window.top.set(top) + ppt_window.height.set(height) + ppt_window.left_position.set(left_position) + ppt_window.width.set(width) + else: + #TODO: set output monitor for fullscreen mode + pass + + def get_slide_number(self): + """ + Returns the current slide number. + """ + log.debug(u'get_slide_number') + return self.presentation.slide_show_window.slideshow_view.current_show_position() + + def get_slide_count(self): + """ + Returns total number of slides. + """ + log.debug(u'get_slide_count') + return len(self.presentation.slides()) + + def goto_slide(self, slideno): + """ + Moves to a specific slide in the presentation. + """ + log.debug(u'goto_slide') + #TODO: this works. but needs to fix this dumb code + while self.get_slide_number() != slideno: + if self.get_slide_number() < slideno: + self.presentation.slide_show_window.slideshow_view.go_to_next_slide() + else: + self.presentation.slide_show_window.slideshow_view.go_to_previous_slide() + self.controller.process.activate() + + def next_step(self): + """ + Triggers the next effect of slide on the running presentation. + """ + log.debug(u'next_step') + #TODO: check if slideshow stoped then restart it from current position + if self.is_active(): + self.presentation.slide_show_window.slideshow_view.go_to_next_slide() + self.controller.process.activate() + if self.get_slide_number() > self.get_slide_count(): + self.previous_step() + + def previous_step(self): + """ + Triggers the previous slide on the running presentation. + """ + log.debug(u'previous_step') + #TODO: check if slideshow stoped then restart it from current position + if self.is_active(): + self.presentation.slide_show_window.slideshow_view.go_to_previous_slide() + self.controller.process.activate() + + def get_slide_text(self, slide_no): + """ + Returns the text on the slide. + + ``slide_no`` + The slide the text is required for, starting at 1. + """ + return _get_text_from_shapes(self.presentation.slides[slide_no-1].shapes) + + def get_slide_notes(self, slide_no): + """ + Returns the text on the slide. + + ``slide_no`` + The slide the notes are required for, starting at 1. + """ + return _get_text_from_shapes( + self.presentation.slides[slide_no].notes_page.shapes()) + +def _get_text_from_shapes(shapes): + """ + Returns any text extracted from the shapes on a presentation slide. + + ``shapes`` + A set of shapes to search for text. + """ + text = u'' + for idx in range(len(shapes)): + shape = shapes[idx + 1] + if shape.has_text_frame(): + text += shape.text_frame.text_range.content() + '\n' + return text === modified file 'openlp/plugins/presentations/lib/presentationtab.py' --- openlp/plugins/presentations/lib/presentationtab.py 2013-03-16 21:18:05 +0000 +++ openlp/plugins/presentations/lib/presentationtab.py 2013-04-02 22:38:33 +0000 @@ -30,6 +30,7 @@ from PyQt4 import QtGui from openlp.core.lib import Settings, SettingsTab, UiStrings, translate +import sys class PresentationTab(SettingsTab): @@ -70,6 +71,11 @@ self.override_app_check_box = QtGui.QCheckBox(self.advanced_group_box) self.override_app_check_box.setObjectName(u'override_app_check_box') self.advanced_layout.addWidget(self.override_app_check_box) + self.show_presenter_view_check_box = QtGui.QCheckBox(self.advanced_group_box) + self.show_presenter_view_check_box.setObjectName(u'show_presenter_view_check_box') + self.advanced_layout.addWidget(self.show_presenter_view_check_box) + if not sys.platform.startswith('darwin'): + self.show_presenter_view_check_box.setVisible(False) self.left_layout.addWidget(self.advanced_group_box) self.left_layout.addStretch() self.right_layout.addStretch() @@ -86,6 +92,8 @@ self.advanced_group_box.setTitle(UiStrings().Advanced) self.override_app_check_box.setText( translate('PresentationPlugin.PresentationTab', 'Allow presentation application to be overridden')) + self.show_presenter_view_check_box.setText( + translate('PresentationPlugin.PresentationTab', 'Show Presenter View')) def set_controller_text(self, checkbox, controller): if checkbox.isEnabled(): @@ -103,6 +111,7 @@ checkbox = self.presenter_check_boxes[controller.name] checkbox.setChecked(Settings().value(self.settings_section + u'/' + controller.name)) self.override_app_check_box.setChecked(Settings().value(self.settings_section + u'/override app')) + self.show_presenter_view_check_box.setChecked(Settings().value(self.settings_section + u'/show presenter view')) def save(self): """ @@ -128,6 +137,10 @@ if Settings().value(setting_key) != self.override_app_check_box.checkState(): Settings().setValue(setting_key, self.override_app_check_box.checkState()) changed = True + setting_key = self.settings_section + u'/show presenter view' + if Settings().value(setting_key) != self.show_presenter_view_check_box.checkState(): + Settings().setValue(setting_key, self.show_presenter_view_check_box.isChecked()) + changed = True if changed: self.settings_form.register_post_process(u'mediaitem_suffix_reset') self.settings_form.register_post_process(u'mediaitem_presentation_rebuild') === modified file 'openlp/plugins/presentations/presentationplugin.py' --- openlp/plugins/presentations/presentationplugin.py 2013-03-19 19:43:22 +0000 +++ openlp/plugins/presentations/presentationplugin.py 2013-04-02 22:38:33 +0000 @@ -31,6 +31,7 @@ presentations from a variety of document formats. """ import os +import sys import logging from PyQt4 import QtCore @@ -46,6 +47,11 @@ u'presentations/Impress': QtCore.Qt.Checked, u'presentations/Powerpoint': QtCore.Qt.Checked, u'presentations/Powerpoint Viewer': QtCore.Qt.Checked, + u'presentations/Keynote': QtCore.Qt.Checked, + u'presentations/show presenter view': QtCore.Qt.Checked, + u'PresentationModeUseSecondary': u'', + u'PresentationModeEnableFeedbackDisplay': False, + u'PresentationModePlayWellWithOthers': False, u'presentations/presentations files': [] } @@ -130,6 +136,12 @@ u'presentations', u'lib') for filename in os.listdir(controller_dir): if filename.endswith(u'controller.py') and not filename == 'presentationcontroller.py': + if not sys.platform.startswith('darwin') and filename == 'powerpointmaccontroller.py': + continue + if not sys.platform.startswith('darwin') and filename == 'keynotemaccontroller.py': + continue + if not sys.platform.startswith('win') and filename == 'powerpointcontroller.py': + continue path = os.path.join(controller_dir, filename) if os.path.isfile(path): module_name = u'openlp.plugins.presentations.lib.' + os.path.splitext(filename)[0] === modified file 'scripts/check_dependencies.py' --- scripts/check_dependencies.py 2013-03-14 10:51:49 +0000 +++ scripts/check_dependencies.py 2013-04-02 22:38:33 +0000 @@ -47,6 +47,7 @@ pass IS_WIN = sys.platform.startswith('win') +IS_OSX = sys.platform.startswith('darwin') VERS = { 'Python': '2.6', @@ -64,6 +65,11 @@ 'pywintypes', ] +# OSX +OSX_MODULES = [ + 'appscript', + 'mactypes', +] MODULES = [ 'PyQt4', 'PyQt4.QtCore', @@ -187,6 +193,11 @@ print('Checking for Windows specific modules...') for m in WIN32_MODULES: check_module(m) + + if IS_OSX: + print('Checking for OS X specific modules...') + for m in OSX_MODULES: + check_module(m) verify_versions() verify_pyqt()
_______________________________________________ Mailing list: https://launchpad.net/~openlp-core Post to : openlp-core@lists.launchpad.net Unsubscribe : https://launchpad.net/~openlp-core More help : https://help.launchpad.net/ListHelp