openlp-core team mailing list archive
-
openlp-core team
-
Mailing list archive
-
Message #26956
Re: [Merge] lp:~tomasgroth/openlp/bugfixes20 into lp:openlp
Se my reply to your comment below.
Diff comments:
> === modified file 'openlp/.version'
> --- openlp/.version 2015-02-21 20:05:25 +0000
> +++ openlp/.version 2015-05-27 08:50:25 +0000
> @@ -1,1 +1,1 @@
> -2.1.3
> +2.1.4
>
> === modified file 'openlp/core/ui/mainwindow.py'
> --- openlp/core/ui/mainwindow.py 2015-02-21 20:05:25 +0000
> +++ openlp/core/ui/mainwindow.py 2015-05-27 08:50:25 +0000
> @@ -900,7 +900,10 @@
> for section_key in import_keys:
> if 'eneral' in section_key:
> section_key = section_key.lower()
> - value = import_settings.value(section_key)
> + try:
> + value = import_settings.value(section_key)
> + except KeyError:
> + log.warning('The key "%s" does not exist (anymore), so it will be skipped.' % section_key)
> if value is not None:
> settings.setValue('%s' % (section_key), value)
> now = datetime.now()
>
> === modified file 'openlp/core/ui/slidecontroller.py'
> --- openlp/core/ui/slidecontroller.py 2015-05-25 19:31:12 +0000
> +++ openlp/core/ui/slidecontroller.py 2015-05-27 08:50:25 +0000
> @@ -828,8 +828,10 @@
> self.selected_row = 0
> # take a copy not a link to the servicemanager copy.
> self.service_item = copy.copy(service_item)
> - if old_item and self.is_live and old_item.is_capable(ItemCapabilities.ProvidesOwnDisplay):
> - self._reset_blank()
> + # Reset blanking if needed
> + if old_item and self.is_live and (old_item.is_capable(ItemCapabilities.ProvidesOwnDisplay) or
> + self.service_item.is_capable(ItemCapabilities.ProvidesOwnDisplay)):
> + self._reset_blank(self.service_item.is_capable(ItemCapabilities.ProvidesOwnDisplay))
> if service_item.is_command():
> Registry().execute(
> '%s_start' % service_item.name.lower(), [self.service_item, self.is_live, self.hide_mode(), slide_no])
> @@ -1080,6 +1082,7 @@
> % timeout)
> return
> row = self.preview_widget.current_slide_number()
> + old_selected_row = self.selected_row
> self.selected_row = 0
> if -1 < row < self.preview_widget.slide_count():
> if self.service_item.is_command():
> @@ -1089,7 +1092,7 @@
> else:
> to_display = self.service_item.get_rendered_frame(row)
> if self.service_item.is_text():
> - self.display.text(to_display)
> + self.display.text(to_display, row != old_selected_row)
> else:
> if start:
> self.display.build_html(self.service_item, to_display)
> @@ -1119,8 +1122,7 @@
> This updates the preview frame, for example after changing a slide or using *Blank to Theme*.
> """
> self.log_debug('update_preview %s ' % self.screens.current['primary'])
> - if not self.screens.current['primary'] and self.service_item and \
> - self.service_item.is_capable(ItemCapabilities.ProvidesOwnDisplay):
> + if self.service_item and self.service_item.is_capable(ItemCapabilities.ProvidesOwnDisplay):
> # Grab now, but try again in a couple of seconds if slide change is slow
> QtCore.QTimer.singleShot(0.5, self.grab_maindisplay)
> QtCore.QTimer.singleShot(2.5, self.grab_maindisplay)
> @@ -1349,7 +1351,11 @@
>
> :param item: The service item to be processed
> """
> - self.media_controller.video(self.controller_type, item, self.hide_mode())
> + if self.is_live and self.hide_mode() == HideMode.Theme:
> + self.media_controller.video(self.controller_type, item, HideMode.Blank)
> + self.on_blank_display(True)
> + else:
> + self.media_controller.video(self.controller_type, item, self.hide_mode())
> if not self.is_live:
> self.preview_display.show()
> self.slide_preview.hide()
> @@ -1362,16 +1368,22 @@
> self.preview_display.hide()
> self.slide_preview.show()
>
> - def _reset_blank(self):
> + def _reset_blank(self, no_theme):
I don't see why it should? In most cases the value will indeed be False, but this is a "private" method (or whatever we call methods only intended for internal class use), and is (so far) only used once, so I don't see the need...
> """
> Used by command items which provide their own displays to reset the
> screen hide attributes
> +
> + :param no_theme: Does the new item support theme-blanking.
> """
> hide_mode = self.hide_mode()
> if hide_mode == HideMode.Blank:
> self.on_blank_display(True)
> elif hide_mode == HideMode.Theme:
> - self.on_theme_display(True)
> + # The new item-type doesn't support theme-blanking, so 'switch' to normal blanking.
> + if no_theme:
> + self.on_blank_display(True)
> + else:
> + self.on_theme_display(True)
> elif hide_mode == HideMode.Screen:
> self.on_hide_display(True)
> else:
>
> === modified file 'openlp/plugins/bibles/lib/mediaitem.py'
> --- openlp/plugins/bibles/lib/mediaitem.py 2015-04-07 22:01:52 +0000
> +++ openlp/plugins/bibles/lib/mediaitem.py 2015-05-27 08:50:25 +0000
> @@ -193,7 +193,7 @@
> self.add_search_fields('quick', translate('BiblesPlugin.MediaItem', 'Quick'))
> self.quickTab.setVisible(True)
> # Add the Advanced Search tab.
> - self.add_search_tab('advanced', UiStrings().Advanced)
> + self.add_search_tab('advanced', translate('BiblesPlugin.MediaItem', 'Advanced'))
> self.advanced_book_label = QtGui.QLabel(self.advancedTab)
> self.advanced_book_label.setObjectName('advanced_book_label')
> self.advancedLayout.addWidget(self.advanced_book_label, 0, 0, QtCore.Qt.AlignRight)
>
> === modified file 'openlp/plugins/presentations/lib/messagelistener.py'
> --- openlp/plugins/presentations/lib/messagelistener.py 2015-03-26 14:17:14 +0000
> +++ openlp/plugins/presentations/lib/messagelistener.py 2015-05-27 08:50:25 +0000
> @@ -243,6 +243,9 @@
> Instruct the controller to stop and hide the presentation.
> """
> log.debug('Live = %s, stop' % self.is_live)
> + # Save the current slide number to be able to return to this slide if the presentation is activated again.
> + if self.doc.is_active():
> + self.doc.slidenumber = self.doc.get_slide_number()
> self.hide_mode = HideMode.Screen
> if not self.doc:
> return
> @@ -266,8 +269,6 @@
> return
> if not self.activate():
> return
> - if self.doc.slidenumber and self.doc.slidenumber != self.doc.get_slide_number():
> - self.doc.goto_slide(self.doc.slidenumber)
> self.doc.unblank_screen()
> Registry().execute('live_display_hide', HideMode.Screen)
>
>
> === modified file 'openlp/plugins/presentations/lib/powerpointcontroller.py'
> --- openlp/plugins/presentations/lib/powerpointcontroller.py 2015-04-02 08:33:46 +0000
> +++ openlp/plugins/presentations/lib/powerpointcontroller.py 2015-05-27 08:50:25 +0000
> @@ -32,12 +32,15 @@
> from openlp.core.common import is_win, Settings
>
> if is_win():
> - from win32com.client import Dispatch
> + from win32com.client import DispatchWithEvents
> import win32com
> + import win32con
> import winreg
> import win32ui
> + import win32gui
> import pywintypes
>
> +
> from openlp.core.lib import ScreenList
> from openlp.core.lib.ui import UiStrings, critical_error_message_box, translate
> from openlp.core.common import trace_error_handler, Registry
> @@ -70,8 +73,18 @@
> if is_win():
> try:
> winreg.OpenKey(winreg.HKEY_CLASSES_ROOT, 'PowerPoint.Application').Close()
> + try:
> + # Try to detect if the version is 12 (2007) or above, and if so add 'odp' as a support filetype
> + version_key = winreg.OpenKey(winreg.HKEY_CLASSES_ROOT, 'PowerPoint.Application\\CurVer')
> + tmp1, app_version_string, tmp2 = winreg.EnumValue(version_key, 0)
> + version_key.Close()
> + app_version = int(app_version_string[-2:])
> + if app_version >= 12:
> + self.also_supports = ['odp']
> + except (OSError, ValueError):
> + log.warning('Detection of powerpoint version using registry failed.')
> return True
> - except WindowsError:
> + except OSError:
> pass
> return False
>
> @@ -80,12 +93,22 @@
> """
> Loads PowerPoint process.
> """
> + class PowerPointEvents:
> + """
> + Class to catch events from PowerPoint.
> + """
> + def OnSlideShowNextClick(self, slideshow_window, effect):
> + """
> + Occurs on the next click of the slide.
> + If the main OpenLP window is not in focus force update of the slidecontroller.
> + """
> + if not Registry().get('main_window').isActiveWindow():
> + log.debug('main window is not in focus - should update slidecontroller')
> + Registry().execute('slidecontroller_live_change', slideshow_window.View.CurrentShowPosition)
> +
> log.debug('start_process')
> if not self.process:
> - self.process = Dispatch('PowerPoint.Application')
> - self.process.Visible = True
> - # ppWindowMinimized = 2
> - self.process.WindowState = 2
> + self.process = DispatchWithEvents('PowerPoint.Application', PowerPointEvents)
>
> def kill(self):
> """
> @@ -124,6 +147,9 @@
> self.presentation = None
> self.index_map = {}
> self.slide_count = 0
> + self.blank_slide = 1
> + self.blank_click = None
> + self.presentation_hwnd = None
>
> def load_presentation(self):
> """
> @@ -132,23 +158,15 @@
> """
> log.debug('load_presentation')
> try:
> - if not self.controller.process or not self.controller.process.Visible:
> + if not self.controller.process:
> self.controller.start_process()
> - self.controller.process.Presentations.Open(self.file_path, False, False, True)
> + self.controller.process.Presentations.Open(os.path.normpath(self.file_path), False, False, False)
> self.presentation = self.controller.process.Presentations(self.controller.process.Presentations.Count)
> self.create_thumbnails()
> self.create_titles_and_notes()
> - # Powerpoint 2010 and 2013 pops up when loading a file, so we minimize it again
> - if float(self.presentation.Application.Version) >= 14.0:
> - try:
> - # ppWindowMinimized = 2
> - self.presentation.Application.WindowState = 2
> - except (AttributeError, pywintypes.com_error) as e:
> - log.exception('Failed to minimize main powerpoint window')
> - log.exception(e)
> - trace_error_handler(log)
> - # Make sure powerpoint doesn't steal focus
> - Registry().get('main_window').activateWindow()
> + # Make sure powerpoint doesn't steal focus, unless we're on a single screen setup
> + if len(ScreenList().screen_list) > 1:
> + Registry().get('main_window').activateWindow()
> return True
> except (AttributeError, pywintypes.com_error) as e:
> log.exception('Exception caught while loading Powerpoint presentation')
> @@ -194,8 +212,9 @@
> trace_error_handler(log)
> self.presentation = None
> self.controller.remove_doc(self)
> - # Make sure powerpoint doesn't steal focus
> - Registry().get('main_window').activateWindow()
> + # Make sure powerpoint doesn't steal focus, unless we're on a single screen setup
> + if len(ScreenList().screen_list) > 1:
> + Registry().get('main_window').activateWindow()
>
> def is_loaded(self):
> """
> @@ -203,10 +222,6 @@
> """
> log.debug('is_loaded')
> try:
> - if not self.controller.process.Visible:
> - return False
> - if self.controller.process.Windows.Count == 0:
> - return False
> if self.controller.process.Presentations.Count == 0:
> return False
> except (AttributeError, pywintypes.com_error) as e:
> @@ -241,13 +256,11 @@
> """
> log.debug('unblank_screen')
> try:
> - self.presentation.SlideShowSettings.Run()
> - # ppSlideShowRunning = 1
> + self.presentation.SlideShowWindow.Activate()
> self.presentation.SlideShowWindow.View.State = 1
> - self.presentation.SlideShowWindow.Activate()
> - # Unblanking is broken in PowerPoint 2010 and 2013, need to redisplay
> - if float(self.presentation.Application.Version) >= 14.0:
> - self.presentation.SlideShowWindow.View.GotoSlide(self.blank_slide, False)
> + # Unblanking is broken in PowerPoint 2010 (14.0), need to redisplay
> + if 15.0 > float(self.presentation.Application.Version) >= 14.0:
> + self.presentation.SlideShowWindow.View.GotoSlide(self.index_map[self.blank_slide], False)
> if self.blank_click:
> self.presentation.SlideShowWindow.View.GotoClick(self.blank_click)
> except (AttributeError, pywintypes.com_error) as e:
> @@ -255,8 +268,12 @@
> log.exception(e)
> trace_error_handler(log)
> self.show_error_msg()
> - # Make sure powerpoint doesn't steal focus
> - Registry().get('main_window').activateWindow()
> + # Stop powerpoint from flashing in the taskbar
> + if self.presentation_hwnd:
> + win32gui.FlashWindowEx(self.presentation_hwnd, win32con.FLASHW_STOP, 0, 0)
> + # Make sure powerpoint doesn't steal focus, unless we're on a single screen setup
> + if len(ScreenList().screen_list) > 1:
> + Registry().get('main_window').activateWindow()
>
> def blank_screen(self):
> """
> @@ -264,8 +281,8 @@
> """
> log.debug('blank_screen')
> try:
> - # Unblanking is broken in PowerPoint 2010 and 2013, need to save info for later
> - if float(self.presentation.Application.Version) >= 14.0:
> + # Unblanking is broken in PowerPoint 2010 (14.0), need to save info for later
> + if 15.0 > float(self.presentation.Application.Version) >= 14.0:
> self.blank_slide = self.get_slide_number()
> self.blank_click = self.presentation.SlideShowWindow.View.GetClickIndex()
> # ppSlideShowBlackScreen = 3
> @@ -295,7 +312,7 @@
>
> def stop_presentation(self):
> """
> - Stops the current presentation and hides the output.
> + Stops the current presentation and hides the output. Used when blanking to desktop.
> """
> log.debug('stop_presentation')
> try:
> @@ -321,28 +338,52 @@
> except win32ui.error:
> dpi = 96
> size = ScreenList().current['size']
> - ppt_window = self.presentation.SlideShowSettings.Run()
> - if not ppt_window:
> - return
> + ppt_window = None
> try:
> - ppt_window.Top = size.y() * 72 / dpi
> - ppt_window.Height = size.height() * 72 / dpi
> - ppt_window.Left = size.x() * 72 / dpi
> - ppt_window.Width = size.width() * 72 / dpi
> - except AttributeError as e:
> - log.exception('AttributeError while in start_presentation')
> + ppt_window = self.presentation.SlideShowSettings.Run()
> + except (AttributeError, pywintypes.com_error) as e:
> + log.exception('Caught exception while in start_presentation')
> log.exception(e)
> - # Powerpoint 2010 and 2013 pops up when starting a file, so we minimize it again
> - if float(self.presentation.Application.Version) >= 14.0:
> + trace_error_handler(log)
> + self.show_error_msg()
> + if ppt_window and not Settings().value('presentations/powerpoint control window'):
> try:
> - # ppWindowMinimized = 2
> - self.presentation.Application.WindowState = 2
> - except (AttributeError, pywintypes.com_error) as e:
> - log.exception('Failed to minimize main powerpoint window')
> + ppt_window.Top = size.y() * 72 / dpi
> + ppt_window.Height = size.height() * 72 / dpi
> + ppt_window.Left = size.x() * 72 / dpi
> + ppt_window.Width = size.width() * 72 / dpi
> + except AttributeError as e:
> + log.exception('AttributeError while in start_presentation')
> log.exception(e)
> - trace_error_handler(log)
> - # Make sure powerpoint doesn't steal focus
> - Registry().get('main_window').activateWindow()
> + # Find the presentation window and save the handle for later
> + self.presentation_hwnd = None
> + if ppt_window:
> + log.debug('main display size: y=%d, height=%d, x=%d, width=%d'
> + % (size.y(), size.height(), size.x(), size.width()))
> + win32gui.EnumWindows(self._window_enum_callback, size)
> + # Make sure powerpoint doesn't steal focus, unless we're on a single screen setup
> + if len(ScreenList().screen_list) > 1:
> + Registry().get('main_window').activateWindow()
> +
> + def _window_enum_callback(self, hwnd, size):
> + """
> + Method for callback from win32gui.EnumWindows.
> + Used to find the powerpoint presentation window and stop it flashing in the taskbar.
> + """
> + # Get the size of the current window and if it matches the size of our main display we assume
> + # it is the powerpoint presentation window.
> + (left, top, right, bottom) = win32gui.GetWindowRect(hwnd)
> + window_title = win32gui.GetWindowText(hwnd)
> + log.debug('window size: left=%d, top=%d, right=%d, width=%d' % (left, top, right, bottom))
> + log.debug('compare size: %d and %d, %d and %d, %d and %d, %d and %d'
> + % (size.y(), top, size.height(), (bottom - top), size.x(), left, size.width(), (right - left)))
> + log.debug('window title: %s' % window_title)
> + if size.y() == top and size.height() == (bottom - top) and size.x() == left and \
> + size.width() == (right - left) and os.path.basename(self.file_path) in window_title:
> + log.debug('Found a match and will save the handle')
> + self.presentation_hwnd = hwnd
> + # Stop powerpoint from flashing in the taskbar
> + win32gui.FlashWindowEx(self.presentation_hwnd, win32con.FLASHW_STOP, 0, 0)
>
> def get_slide_number(self):
> """
> @@ -384,7 +425,7 @@
> log.debug('goto_slide')
> try:
> if Settings().value('presentations/powerpoint slide click advance') \
> - and self.get_slide_number() == self.index_map[slide_no]:
> + and self.get_slide_number() == slide_no:
> click_index = self.presentation.SlideShowWindow.View.GetClickIndex()
> click_count = self.presentation.SlideShowWindow.View.GetClickCount()
> log.debug('We are already on this slide - go to next effect if any left, idx: %d, count: %d'
> @@ -405,6 +446,7 @@
> """
> log.debug('next_step')
> try:
> + self.presentation.SlideShowWindow.Activate()
> self.presentation.SlideShowWindow.View.Next()
> except (AttributeError, pywintypes.com_error) as e:
> log.exception('Caught exception while in next_step')
> @@ -415,6 +457,12 @@
> if self.get_slide_number() > self.get_slide_count():
> log.debug('past end, stepping back to previous')
> self.previous_step()
> + # Stop powerpoint from flashing in the taskbar
> + if self.presentation_hwnd:
> + win32gui.FlashWindowEx(self.presentation_hwnd, win32con.FLASHW_STOP, 0, 0)
> + # Make sure powerpoint doesn't steal focus, unless we're on a single screen setup
> + if len(ScreenList().screen_list) > 1:
> + Registry().get('main_window').activateWindow()
>
> def previous_step(self):
> """
> @@ -490,8 +538,12 @@
> :param shapes: A set of shapes to search for text.
> """
> text = ''
> - for shape in shapes:
> - if shape.PlaceholderFormat.Type == 2: # 2 from is enum PpPlaceholderType.ppPlaceholderBody
> - if shape.HasTextFrame and shape.TextFrame.HasText:
> - text += shape.TextFrame.TextRange.Text + '\n'
> + try:
> + for shape in shapes:
> + if shape.PlaceholderFormat.Type == 2: # 2 from is enum PpPlaceholderType.ppPlaceholderBody
> + if shape.HasTextFrame and shape.TextFrame.HasText:
> + text += shape.TextFrame.TextRange.Text + '\n'
> + except pywintypes.com_error as e:
> + log.warning('Failed to extract text from powerpoint slide')
> + log.warning(e)
> return text
>
> === modified file 'openlp/plugins/presentations/lib/presentationtab.py'
> --- openlp/plugins/presentations/lib/presentationtab.py 2015-04-02 08:33:46 +0000
> +++ openlp/plugins/presentations/lib/presentationtab.py 2015-05-27 08:50:25 +0000
> @@ -74,8 +74,11 @@
> self.powerpoint_layout = QtGui.QVBoxLayout(self.powerpoint_group_box)
> self.powerpoint_layout.setObjectName('powerpoint_layout')
> self.ppt_slide_click_check_box = QtGui.QCheckBox(self.powerpoint_group_box)
> - self.powerpoint_group_box.setObjectName('ppt_slide_click_check_box')
> + self.ppt_slide_click_check_box.setObjectName('ppt_slide_click_check_box')
> self.powerpoint_layout.addWidget(self.ppt_slide_click_check_box)
> + self.ppt_window_check_box = QtGui.QCheckBox(self.powerpoint_group_box)
> + self.ppt_window_check_box.setObjectName('ppt_window_check_box')
> + self.powerpoint_layout.addWidget(self.ppt_window_check_box)
> self.left_layout.addWidget(self.powerpoint_group_box)
> # Pdf options
> self.pdf_group_box = QtGui.QGroupBox(self.left_column)
> @@ -123,6 +126,9 @@
> self.ppt_slide_click_check_box.setText(
> translate('PresentationPlugin.PresentationTab',
> 'Clicking on a selected slide in the slidecontroller advances to next effect.'))
> + self.ppt_window_check_box.setText(
> + translate('PresentationPlugin.PresentationTab',
> + 'Let PowerPoint control the size and position of the presentation window.'))
> self.pdf_program_check_box.setText(
> translate('PresentationPlugin.PresentationTab', 'Use given full path for mudraw or ghostscript binary:'))
>
> @@ -148,6 +154,8 @@
> self.ppt_slide_click_check_box.setChecked(Settings().value(self.settings_section +
> '/powerpoint slide click advance'))
> self.ppt_slide_click_check_box.setEnabled(powerpoint_available)
> + self.ppt_window_check_box.setChecked(Settings().value(self.settings_section + '/powerpoint control window'))
> + self.ppt_window_check_box.setEnabled(powerpoint_available)
> # load pdf-program settings
> enable_pdf_program = Settings().value(self.settings_section + '/enable_pdf_program')
> self.pdf_program_check_box.setChecked(enable_pdf_program)
> @@ -186,6 +194,10 @@
> if Settings().value(setting_key) != self.ppt_slide_click_check_box.checkState():
> Settings().setValue(setting_key, self.ppt_slide_click_check_box.checkState())
> changed = True
> + setting_key = self.settings_section + '/powerpoint control window'
> + if Settings().value(setting_key) != self.ppt_window_check_box.checkState():
> + Settings().setValue(setting_key, self.ppt_window_check_box.checkState())
> + changed = True
> # Save pdf-settings
> pdf_program = self.pdf_program_path.text()
> enable_pdf_program = self.pdf_program_check_box.checkState()
>
> === modified file 'openlp/plugins/presentations/presentationplugin.py'
> --- openlp/plugins/presentations/presentationplugin.py 2015-03-26 14:22:23 +0000
> +++ openlp/plugins/presentations/presentationplugin.py 2015-05-27 08:50:25 +0000
> @@ -45,7 +45,8 @@
> 'presentations/Pdf': QtCore.Qt.Checked,
> 'presentations/presentations files': [],
> 'presentations/thumbnail_scheme': '',
> - 'presentations/powerpoint slide click advance': QtCore.Qt.Unchecked
> + 'presentations/powerpoint slide click advance': QtCore.Qt.Unchecked,
> + 'presentations/powerpoint control window': QtCore.Qt.Unchecked
> }
>
>
>
> === modified file 'openlp/plugins/songs/lib/importers/worshipassistant.py'
> --- openlp/plugins/songs/lib/importers/worshipassistant.py 2015-03-09 20:57:39 +0000
> +++ openlp/plugins/songs/lib/importers/worshipassistant.py 2015-05-27 08:50:25 +0000
> @@ -131,6 +131,7 @@
> return
> verse = ''
> used_verses = []
> + verse_id = VerseType.tags[VerseType.Verse] + '1'
> for line in lyrics.splitlines():
> if line.startswith('['): # verse marker
> # Add previous verse
>
> === modified file 'tests/functional/openlp_plugins/presentations/test_powerpointcontroller.py'
> --- tests/functional/openlp_plugins/presentations/test_powerpointcontroller.py 2015-04-02 08:33:46 +0000
> +++ tests/functional/openlp_plugins/presentations/test_powerpointcontroller.py 2015-05-27 08:50:25 +0000
> @@ -164,45 +164,42 @@
> """
> Test creating the titles from PowerPoint
> """
> - if is_win() and self.real_controller.check_available():
> - # GIVEN: mocked save_titles_and_notes, _get_text_from_shapes and two mocked slides
> - self.doc = PowerpointDocument(self.real_controller, self.file_name)
> - self.doc.save_titles_and_notes = MagicMock()
> - self.doc._PowerpointDocument__get_text_from_shapes = MagicMock()
> - slide = MagicMock()
> - slide.Shapes.Title.TextFrame.TextRange.Text = 'SlideText'
> - pres = MagicMock()
> - pres.Slides = [slide, slide]
> - self.doc.presentation = pres
> -
> - # WHEN reading the titles and notes
> - self.doc.create_titles_and_notes()
> -
> - # THEN the save should have been called exactly once with 2 titles and 2 notes
> - self.doc.save_titles_and_notes.assert_called_once_with(['SlideText\n', 'SlideText\n'], [' ', ' '])
> - else:
> - self.skipTest('Powerpoint not available, skipping test.')
> + # GIVEN: mocked save_titles_and_notes, _get_text_from_shapes and two mocked slides
> + self.doc = PowerpointDocument(self.mock_controller, self.file_name)
> + self.doc.get_slide_count = MagicMock()
> + self.doc.get_slide_count.return_value = 2
> + self.doc.index_map = {1: 1, 2: 2}
> + self.doc.save_titles_and_notes = MagicMock()
> + self.doc._PowerpointDocument__get_text_from_shapes = MagicMock()
> + slide = MagicMock()
> + slide.Shapes.Title.TextFrame.TextRange.Text = 'SlideText'
> + pres = MagicMock()
> + pres.Slides = MagicMock(side_effect=[slide, slide])
> + self.doc.presentation = pres
> +
> + # WHEN reading the titles and notes
> + self.doc.create_titles_and_notes()
> +
> + # THEN the save should have been called exactly once with 2 titles and 2 notes
> + self.doc.save_titles_and_notes.assert_called_once_with(['SlideText\n', 'SlideText\n'], [' ', ' '])
>
> def create_titles_and_notes_with_no_slides_test(self):
> """
> Test creating the titles from PowerPoint when it returns no slides
> """
> - if is_win() and self.real_controller.check_available():
> - # GIVEN: mocked save_titles_and_notes, _get_text_from_shapes and two mocked slides
> - doc = PowerpointDocument(self.real_controller, self.file_name)
> - doc.save_titles_and_notes = MagicMock()
> - doc._PowerpointDocument__get_text_from_shapes = MagicMock()
> - pres = MagicMock()
> - pres.Slides = []
> - doc.presentation = pres
> -
> - # WHEN reading the titles and notes
> - doc.create_titles_and_notes()
> -
> - # THEN the save should have been called exactly once with empty titles and notes
> - doc.save_titles_and_notes.assert_called_once_with([], [])
> - else:
> - self.skipTest('Powerpoint not available, skipping test.')
> + # GIVEN: mocked save_titles_and_notes, _get_text_from_shapes and two mocked slides
> + doc = PowerpointDocument(self.mock_controller, self.file_name)
> + doc.save_titles_and_notes = MagicMock()
> + doc._PowerpointDocument__get_text_from_shapes = MagicMock()
> + pres = MagicMock()
> + pres.Slides = []
> + doc.presentation = pres
> +
> + # WHEN reading the titles and notes
> + doc.create_titles_and_notes()
> +
> + # THEN the save should have been called exactly once with empty titles and notes
> + doc.save_titles_and_notes.assert_called_once_with([], [])
>
> def get_text_from_shapes_test(self):
> """
> @@ -253,3 +250,54 @@
>
> # THEN: next_step() should be call to try to advance to the next effect.
> self.assertTrue(doc.next_step.called, 'next_step() should have been called!')
> +
> + def blank_screen_test(self):
> + """
> + Test that blank_screen works as expected
> + """
> + # GIVEN: A Document with mocked controller, presentation, and mocked function get_slide_number
> + doc = PowerpointDocument(self.mock_controller, self.mock_presentation)
> + doc.presentation = MagicMock()
> + doc.presentation.SlideShowWindow.View.GetClickIndex.return_value = 3
> + doc.presentation.Application.Version = 14.0
> + doc.get_slide_number = MagicMock()
> + doc.get_slide_number.return_value = 2
> +
> + # WHEN: Calling goto_slide
> + doc.blank_screen()
> +
> + # THEN: The view state, doc.blank_slide and doc.blank_click should have new values
> + self.assertEquals(doc.presentation.SlideShowWindow.View.State, 3, 'The View State should be 3')
> + self.assertEquals(doc.blank_slide, 2, 'doc.blank_slide should be 2 because of the PowerPoint version')
> + self.assertEquals(doc.blank_click, 3, 'doc.blank_click should be 3 because of the PowerPoint version')
> +
> + def unblank_screen_test(self):
> + """
> + Test that unblank_screen works as expected
> + """
> + # GIVEN: A Document with mocked controller, presentation, ScreenList, and mocked function get_slide_number
> + with patch('openlp.plugins.presentations.lib.powerpointcontroller.ScreenList') as mocked_screen_list:
> + mocked_screen_list_ret = MagicMock()
> + mocked_screen_list_ret.screen_list = [1]
> + mocked_screen_list.return_value = mocked_screen_list_ret
> + doc = PowerpointDocument(self.mock_controller, self.mock_presentation)
> + doc.presentation = MagicMock()
> + doc.presentation.SlideShowWindow.View.GetClickIndex.return_value = 3
> + doc.presentation.Application.Version = 14.0
> + doc.get_slide_number = MagicMock()
> + doc.get_slide_number.return_value = 2
> + doc.index_map[1] = 1
> + doc.blank_slide = 1
> + doc.blank_click = 1
> +
> + # WHEN: Calling goto_slide
> + doc.unblank_screen()
> +
> + # THEN: The view state have new value, and several function should have been called
> + self.assertEquals(doc.presentation.SlideShowWindow.View.State, 1, 'The View State should be 1')
> + self.assertEquals(doc.presentation.SlideShowWindow.Activate.called, True,
> + 'SlideShowWindow.Activate should have been called')
> + self.assertEquals(doc.presentation.SlideShowWindow.View.GotoSlide.called, True,
> + 'View.GotoSlide should have been called because of the PowerPoint version')
> + self.assertEquals(doc.presentation.SlideShowWindow.View.GotoClick.called, True,
> + 'View.GotoClick should have been called because of the PowerPoint version')
>
> === modified file 'tests/functional/openlp_plugins/songs/test_worshipassistantimport.py'
> --- tests/functional/openlp_plugins/songs/test_worshipassistantimport.py 2015-01-22 17:42:29 +0000
> +++ tests/functional/openlp_plugins/songs/test_worshipassistantimport.py 2015-05-27 08:50:25 +0000
> @@ -49,3 +49,5 @@
> self.load_external_result_data(os.path.join(TEST_PATH, 'would_you_be_free.json')))
> self.file_import(os.path.join(TEST_PATH, 'would_you_be_free2.csv'),
> self.load_external_result_data(os.path.join(TEST_PATH, 'would_you_be_free.json')))
> + self.file_import(os.path.join(TEST_PATH, 'lift_up_your_heads.csv'),
> + self.load_external_result_data(os.path.join(TEST_PATH, 'lift_up_your_heads.json')))
>
> === added file 'tests/resources/worshipassistantsongs/lift_up_your_heads.csv'
> --- tests/resources/worshipassistantsongs/lift_up_your_heads.csv 1970-01-01 00:00:00 +0000
> +++ tests/resources/worshipassistantsongs/lift_up_your_heads.csv 2015-05-27 08:50:25 +0000
> @@ -0,0 +1,40 @@
> +"SongID","SongNr","Title","Author","Copyright","FirstLine","PriKey","AltKey","Tempo","Focus","Theme","Scripture","Active","Songbook","TimeSig","Introduced","LastUsed","TimesUsed","CCLINr","User1","User2","User3","User4","User5","Roadmap","Overmap","FileLink1","FileLink2","Updated","Lyrics","Info","Lyrics2","Background"
> +"000013ab-0000-0000-0000-000000000000","0","Lift Up Your Heads"," Bryan Mierau","Public Domain","Lift up your heads and the doors","Em","NULL","NULL","NULL","NULL","NULL","1","1","NULL","NULL","NULL","0","NULL","NULL","NULL","NULL","NULL","NULL","NULL","NULL","NULL","NULL","2004-04-07 06:36:18.952",".Em D C D
> + Lift up your heads and the doors of your heart
> +. Am B7 Em
> + And the King of glory will come in
> +(Repeat)
> +
> +.G Am D
> + Who is this King of Glory?
> +. B7 Em
> + The Lord strong and mighty!
> +.G Am D
> + Who is this King of Glory?
> +. B7
> + The Lord, mighty in battle!
> +
> +.G Am D
> + Who is this King of Glory?
> +.B7 Em
> + Jesus our Messiah!
> +.G Am D
> + Who is this King of Glory?
> +.B7 Em
> + Jesus, Lord of Lords!
> +
> +","NULL","Lift up your heads and the doors of your heart
> +And the King of glory will come in
> +(Repeat)
> +
> +Who is this King of Glory?
> +The Lord strong and mighty!
> +Who is this King of Glory?
> +The Lord, mighty in battle!
> +
> +Who is this King of Glory?
> +Jesus our Messiah!
> +Who is this King of Glory?
> +Jesus, Lord of Lords!
> +
> +","NULL"
>
> === added file 'tests/resources/worshipassistantsongs/lift_up_your_heads.json'
> --- tests/resources/worshipassistantsongs/lift_up_your_heads.json 1970-01-01 00:00:00 +0000
> +++ tests/resources/worshipassistantsongs/lift_up_your_heads.json 2015-05-27 08:50:25 +0000
> @@ -0,0 +1,13 @@
> +{
> + "authors": [
> + "Bryan Mierau"
> + ],
> + "title": "Lift Up Your Heads",
> + "verse_order_list": [],
> + "verses": [
> + [
> + "Lift up your heads and the doors of your heart\nAnd the King of glory will come in\n(Repeat)\n\nWho is this King of Glory?\nThe Lord strong and mighty!\nWho is this King of Glory?\nThe Lord, mighty in battle!\n\nWho is this King of Glory?\nJesus our Messiah!\nWho is this King of Glory?\nJesus, Lord of Lords!\n",
> + "v1"
> + ]
> + ]
> +}
>
--
https://code.launchpad.net/~tomasgroth/openlp/bugfixes20/+merge/260252
Your team OpenLP Core is subscribed to branch lp:openlp.
References