Dmitriy Marmyshev has proposed merging lp:~marmyshev/openlp/presentation into lp:openlp.
Requested reviews: OpenLP Core (openlp-core) 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/143389 Add support to load presentations with PowerPoint and Keynote on Mac OS X. -- https://code.launchpad.net/~marmyshev/openlp/presentation/+merge/143389 Your team OpenLP Core is requested to review the proposed merge of lp:~marmyshev/openlp/presentation into lp:openlp.
=== modified file 'openlp/core/lib/pluginmanager.py' --- openlp/core/lib/pluginmanager.py 2012-12-29 20:56:56 +0000 +++ openlp/core/lib/pluginmanager.py 2013-01-15 19:35:24 +0000 @@ -92,8 +92,8 @@ if sys.platform == 'darwin': present_plugin_dir = os.path.join(plugin_dir, 'presentations') # Ignore files from the presentation plugin directory. - if root.startswith(present_plugin_dir): - continue + #if root.startswith(present_plugin_dir): + #continue for name in files: if name.endswith(u'.py') and not name.startswith(u'__'): path = os.path.abspath(os.path.join(root, name)) === 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-01-15 19:35:24 +0000 @@ -0,0 +1,383 @@ +# -*- 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 + +from appscript import * + +from openlp.core.lib import Settings +from presentationcontroller import PresentationController, PresentationDocument + +log = logging.getLogger(__name__) + +# PPT API documentation: +# http://msdn.microsoft.com/en-us/library/aa269321(office.10).aspx + +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') + return True + #return False + + + def start_process(self): + """ + Loads KeyNote process + """ + log.debug(u'start_process') + if not self.process: + self.process = app('Keynote') + self.process.relaunchmode = 'always' + 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: + self.docs[0].close_presentation() + if self.process is None: + return + try: + if self.process and len(self.process.slideshows()) > 0: + return + self.process.quit(saving_ = k.no) + #except pywintypes.com_error: + except: + 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("openlp.org","OpenLP") + keynote_settings = Settings("apple", "iWork.Keynote") + use_secondary = int(keynote_settings.value(u'PresentationModeUseSecondary', u'')) + monitor = openlp_settings.value( u'general/monitor', 0) + override_position = openlp_settings.value( u'general/override position', False) + 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.settingsSection + 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) + play_well_with_others = keynote_settings.value(u'PresentationModePlayWellWithOthers', False) + 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 pywintypes.com_error: + except: + log.debug(u'KeyNote open failed') + return False + self.presentation = self.controller.process.slideshows[ + len(self.controller.process.slideshows())-1] + self.create_thumbnails() + return True + + def create_thumbnails(self): + """ + Create the thumbnail images for the current presentation. + + Note an alternative and quicker method would be do:: + + self.presentation.Slides[n].Copy() + thumbnail = QApplication.clipboard.image() + + However, for the moment, we want a physical file since it makes life + easier elsewhere. + """ + log.debug(u'create_thumbnails') + if self.check_thumbnails(): + return + #debug + #return + get_thumbnail_folder = self.get_thumbnail_folder() + if not os.path.exists(get_thumbnail_folder): + os.makedirs(get_thumbnail_folder) + try: + self.controller.process.open(self.filepath) + except: + log.debug(u'KeyNote open failed') + return + self.controller.process.activate() + app(u'System Events').processes[u'Keynote'].menu_bars[1].menu_bar_items[3].menus.menu_items[11].click() + app(u'System Events').processes[u'Keynote'].windows[1].sheets[1].tool_bars.buttons[4].click() + app(u'System Events').processes[u'Keynote'].windows[1].sheets[1].radio_groups[1].radio_buttons[1].click() + app(u'System Events').processes[u'Keynote'].windows[1].sheets[1].pop_up_buttons[1].click() + app(u'System Events').processes[u'Keynote'].windows[1].sheets[1].pop_up_buttons[1].menus.menu_items[2].click() + app(u'System Events').processes[u'Keynote'].windows[1].sheets[1].buttons[2].click() + app(u'System Events').processes[u'Keynote'].keystroke(os.path.join(get_thumbnail_folder, u'temp' + self.controller.thumbnail_prefix)) + #app(u'System Events').processes[u'Keynote'].keystroke(u'\r') + app(u'System Events').processes[u'Keynote'].key_code(36) + app(u'System Events').processes[u'Keynote'].windows[1].sheets[1].buttons[1].click() + #self.activate() + slide_no = 0 +# temp_dir = os.path.join(get_thumbnail_folder, self.get_file_name()) + for filename in os.listdir(get_thumbnail_folder): + full_filename = os.path.join(get_thumbnail_folder, 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(get_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) +# 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 pywintypes.com_error: + except: + 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: + #TODO this doesnt works right + if not self.controller.process.isrunning(): + return False + if len(self.controller.process.windows()) == 0: + return False + if len(self.controller.process.slideshows()) == 0: + return False + except: + return False + return True + + 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: + return False + return True + + def unblank_screen(self): + """ + Unblanks (restores) the presentation. + """ + log.debug(u'unblank_screen') +# settings = self.presentation.slide_show_settings +# settings.run_slide_show() +# self.presentation.slide_show_window().slide_show_view().slide_state()\ +# .set(k.slide_show_state_running) +# self.presentation.SlideShowSettings.Run() +# self.presentation.SlideShowWindow.View.State = 1 +# self.presentation.SlideShowWindow.Activate() + + def blank_screen(self): + """ + Blanks the screen. + """ + log.debug(u'blank_screen') +# self.presentation.slide_show_window().slide_show_view().slide_state()\ +# .set(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(): + 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: + return + renderer = self.controller.plugin.renderer + rect = renderer.screens.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') + return len(self.presentation.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 + +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 = '' + for idx in range(shapes.Count): + shape = shapes(idx + 1) + if shape.HasTextFrame: + text += shape.TextFrame.TextRange.Text + '\n' + return text === 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-01-15 19:35:24 +0000 @@ -0,0 +1,402 @@ +# -*- 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 + +from appscript import * + +from openlp.core.lib import Settings +from presentationcontroller import PresentationController, PresentationDocument + +log = logging.getLogger(__name__) + +# PPT API documentation: +# http://msdn.microsoft.com/en-us/library/aa269321(office.10).aspx + +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') + return True + #return False + + + def start_process(self): + """ + Loads PowerPoint process + """ + log.debug(u'start_process') + if not self.process: + self.process = app(id='com.microsoft.powerpoint') + self.process.relaunchmode = 'always' + self.process.start_up_dialog.set(False) + #self.process.Visible = True + #self.process.WindowState = 2 + 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: + self.docs[0].close_presentation() + if self.process is None: + return + #TODO this doesnt worok right + try: + if self.process and len(self.process.presentations()) > 0: + return + self.process.quit() + #except pywintypes.com_error: + except: + 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.settingsSection + 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 pywintypes.com_error: + except: + log.debug(u'PPT open failed') + return False + self.presentation = self.controller.process.presentations[ + len(self.controller.process.presentations())-1] + self.create_thumbnails() + return True + + def create_thumbnails(self): + """ + Create the thumbnail images for the current presentation. + + Note an alternative and quicker method would be do:: + + self.presentation.Slides[n].Copy() + thumbnail = QApplication.clipboard.image() + + However, for the moment, we want a physical file since it makes life + easier elsewhere. + """ + log.debug(u'create_thumbnails') + if self.check_thumbnails(): + return + get_thumbnail_folder = self.get_thumbnail_folder() + self.presentation.save(in_=get_thumbnail_folder, as_=k.save_as_PNG) + slide_no = 0 + temp_dir = os.path.join(get_thumbnail_folder, self.get_file_name()) + 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(get_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) + 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: + 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 + if len(self.controller.process.presentations()) == 0: + return False + except: + return False + presentations = self.controller.process.presentations() + for presentation in presentations: + name = presentation.name() + basename = os.path.basename(self.filepath) + if basename == 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 == 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(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(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 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') + renderer = self.controller.plugin.renderer + rect = renderer.screens.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.settingsSection + u'/show presenter view', False) + override_position = openlp_settings.value( u'general/override position', False) + if show_presenter_view: + ppt_settings.show_type.set(k.slide_show_type_presenter) + elif override_position: + ppt_settings.show_type.set(k.slide_show_type_window) + else: + ppt_settings.show_type.set(k.slide_show_type_kiosk) + #ppt_settings.show_type.set(k.slide_show_type_speaker) + ppt_window = ppt_settings.run_slide_show() + if ppt_window.slideshow_view.slide_state() != k.slide_show_state_running: + ppt_window.slideshow_view.slide_state.set(k.slide_show_state_running) +# slide_state = ppt_window.slideshow_view.slide_state() +# slide_state = ppt_window.slideshow_view.slide_state() + 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') + 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') + 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 = '' + 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-01-05 22:17:30 +0000 +++ openlp/plugins/presentations/lib/presentationtab.py 2013-01-15 19:35:24 +0000 @@ -31,6 +31,7 @@ from openlp.core.lib import Receiver, Settings, SettingsTab, translate from openlp.core.lib.ui import UiStrings +import sys class PresentationTab(SettingsTab): """ @@ -70,6 +71,11 @@ self.OverrideAppCheckBox = QtGui.QCheckBox(self.AdvancedGroupBox) self.OverrideAppCheckBox.setObjectName(u'OverrideAppCheckBox') self.AdvancedLayout.addWidget(self.OverrideAppCheckBox) + self.ShowPresenterViewCheckBox = QtGui.QCheckBox(self.AdvancedGroupBox) + self.ShowPresenterViewCheckBox.setObjectName(u'ShowPresenterViewCheckBox') + self.AdvancedLayout.addWidget(self.ShowPresenterViewCheckBox) + if not sys.platform.startswith('darwin'): + self.ShowPresenterViewCheckBox.setVisible(False) self.leftLayout.addWidget(self.AdvancedGroupBox) self.leftLayout.addStretch() self.rightLayout.addStretch() @@ -86,6 +92,8 @@ self.AdvancedGroupBox.setTitle(UiStrings().Advanced) self.OverrideAppCheckBox.setText( translate('PresentationPlugin.PresentationTab', 'Allow presentation application to be overridden')) + self.ShowPresenterViewCheckBox.setText( + translate('PresentationPlugin.PresentationTab', 'Show Presenter View')) def setControllerText(self, checkbox, controller): if checkbox.isEnabled(): @@ -104,6 +112,8 @@ checkbox.setChecked(Settings().value(self.settingsSection + u'/' + controller.name, QtCore.Qt.Checked)) self.OverrideAppCheckBox.setChecked(Settings().value(self.settingsSection + u'/override app', QtCore.Qt.Unchecked)) + self.ShowPresenterViewCheckBox.setChecked(Settings().value(self.settingsSection + u'/show presenter view', + QtCore.Qt.Unchecked)) def save(self): """ @@ -130,6 +140,10 @@ if Settings().value(setting_key, QtCore.Qt.Checked) != self.OverrideAppCheckBox.checkState(): Settings().setValue(setting_key, self.OverrideAppCheckBox.checkState()) changed = True + setting_key = self.settingsSection + u'/show presenter view' + if Settings().value(setting_key, QtCore.Qt.Unchecked) != self.ShowPresenterViewCheckBox.checkState(): + Settings().setValue(setting_key, self.ShowPresenterViewCheckBox.isChecked()) + changed = True if changed: self.parent.resetSupportedSuffixes() Receiver.send_message(u'mediaitem_presentation_rebuild') === modified file 'openlp/plugins/presentations/presentationplugin.py' --- openlp/plugins/presentations/presentationplugin.py 2013-01-05 22:17:30 +0000 +++ openlp/plugins/presentations/presentationplugin.py 2013-01-15 19:35:24 +0000 @@ -31,6 +31,7 @@ presentations from a variety of document formats. """ import os +import sys import logging from openlp.core.lib import Plugin, StringContent, build_icon, translate @@ -120,6 +121,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): modulename = u'openlp.plugins.presentations.lib.' + os.path.splitext(filename)[0]
_______________________________________________ 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