From 9220beba786334f13eeaa0336f0806b93fe82ea8 Mon Sep 17 00:00:00 2001 From: Patrick Zimmermann Date: Sun, 14 Apr 2013 23:38:40 +0200 Subject: [PATCH 01/19] Pull preview_list_widget out into separate file. Not yet changed calls to this new class. --- openlp/core/ui/listpreviewwidget.py | 174 ++++++++++++++++++++++++++++ 1 file changed, 174 insertions(+) create mode 100644 openlp/core/ui/listpreviewwidget.py diff --git a/openlp/core/ui/listpreviewwidget.py b/openlp/core/ui/listpreviewwidget.py new file mode 100644 index 000000000..44735c58a --- /dev/null +++ b/openlp/core/ui/listpreviewwidget.py @@ -0,0 +1,174 @@ +# -*- coding: utf-8 -*- +# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4 + +############################################################################### +# OpenLP - Open Source Lyrics Projection # +# --------------------------------------------------------------------------- # +# Copyright (c) 2008-2013 Raoul Snyman # +# Portions copyright (c) 2008-2013 Tim Bentley, Gerald Britton, Jonathan # +# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub, # +# Meinert Jordan, Armin Köhler, Erik Lundin, 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, Patrick Zimmermann # +# --------------------------------------------------------------------------- # +# 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 # +############################################################################### +""" +The :mod:`slidecontroller` module contains the most important part of OpenLP - the slide controller +""" + +from PyQt4 import QtCore, QtGui + +from openlp.core.lib import ImageSource, Registry, ServiceItem + +class ListPreviewWidget(object): + def __init__(self, parent, is_live): + # Controller list view + self.is_live = is_live + self.preview_table_widget = QtGui.QTableWidget(parent) + self.preview_table_widget.setColumnCount(1) + self.preview_table_widget.horizontalHeader().setVisible(False) + self.preview_table_widget.setColumnWidth(0, parent.width()) + self.preview_table_widget.setObjectName(u'preview_table_widget') + self.preview_table_widget.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows) + self.preview_table_widget.setSelectionMode(QtGui.QAbstractItemView.SingleSelection) + self.preview_table_widget.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers) + self.preview_table_widget.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) + self.preview_table_widget.setAlternatingRowColors(True) + self.service_item = ServiceItem() + self.clicked = QtCore.pyqtSignal() + self.double_clicked = QtCore.pyqtSignal() + if not self.is_live: + self.preview_table_widget.doubleClicked.connect(self.double_clicked) + self.preview_table_widget.clicked.connect(self.clicked) + + def clicked(self): + self.clicked.emit() + + def double_clicked(self): + self.double_clicked.emit() + + def get_preview_widget(self): + return self.preview_table_widget + + def set_active(self, active): + if active: + self.preview_table_widget.show() + else: + self.preview_table_widget.hide() + + def replace_service_manager_item(self, service_item, width): + self.service_item = service_item + self._refresh(width) + + def preview_size_changed(self, width, ratio): + """ + Takes care of the SlidePreview's size. Is called when one of the the + splitters is moved or when the screen size is changed. Note, that this + method is (also) called frequently from the mainwindow *paintEvent*. + """ + self.preview_table_widget.setColumnWidth(0, self.preview_table_widget.viewport().size().width()) + if self.service_item: + # Sort out songs, bibles, etc. + if self.service_item.is_text(): + self.preview_table_widget.resizeRowsToContents() + else: + # Sort out image heights. + for framenumber in range(len(self.service_item.get_frames())): + self.preview_table_widget.setRowHeight(framenumber, width / ratio) + + def _refresh(self, width, ratio): + """ + Loads a ServiceItem into the system from ServiceManager + Display the slide number passed + """ + self.preview_table_widget.clear() + self.preview_table_widget.setRowCount(0) + self.preview_table_widget.setColumnWidth(0, width) + row = 0 + text = [] + for framenumber, frame in enumerate(self.service_item.get_frames()): + self.preview_table_widget.setRowCount(self.preview_table_widget.rowCount() + 1) + item = QtGui.QTableWidgetItem() + slideHeight = 0 + if self.service_item.is_text(): + if frame[u'verseTag']: + # These tags are already translated. + verse_def = frame[u'verseTag'] + verse_def = u'%s%s' % (verse_def[0], verse_def[1:]) + two_line_def = u'%s\n%s' % (verse_def[0], verse_def[1:]) + row = two_line_def + else: + row += 1 + item.setText(frame[u'text']) + else: + label = QtGui.QLabel() + label.setMargin(4) + if self.service_item.is_media(): + label.setAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter) + else: + label.setScaledContents(True) + self.preview_table_widget.setCellWidget(framenumber, 0, label) + slideHeight = width / ratio + row += 1 + text.append(unicode(row)) + self.preview_table_widget.setItem(framenumber, 0, item) + if slideHeight: + self.preview_table_widget.setRowHeight(framenumber, slideHeight) + self.preview_table_widget.setVerticalHeaderLabels(text) + if self.service_item.is_text(): + self.preview_table_widget.resizeRowsToContents() + self.preview_table_widget.setColumnWidth(0, self.preview_table_widget.viewport().size().width()) + #stuff happens here, perhaps the setFocus has to happen later... + self.preview_table_widget.setFocus() + + def __updatePreviewSelection(self, slideno): + """ + Utility method to update the selected slide in the list. + """ + if slideno > self.preview_table_widget.rowCount(): + self.preview_table_widget.selectRow( + self.preview_table_widget.rowCount() - 1) + else: + self.__checkUpdateSelectedSlide(slideno) + + def __checkUpdateSelectedSlide(self, row): + """ + Check if this slide has been updated + """ + if row + 1 < self.preview_table_widget.rowCount(): + self.preview_table_widget.scrollToItem(self.preview_table_widget.item(row + 1, 0)) + self.preview_table_widget.selectRow(row) + + def _get_image_manager(self): + """ + Adds the image manager to the class dynamically + """ + if not hasattr(self, u'_image_manager'): + self._image_manager = Registry().get(u'image_manager') + return self._image_manager + + image_manager = property(_get_image_manager) + + def _get_main_window(self): + """ + Adds the main window to the class dynamically + """ + if not hasattr(self, u'_main_window'): + self._main_window = Registry().get(u'main_window') + return self._main_window + + main_window = property(_get_main_window) \ No newline at end of file From 379a27212cb177b245c6d0fcbb45d2bd6481796c Mon Sep 17 00:00:00 2001 From: Patrick Zimmermann Date: Mon, 15 Apr 2013 18:33:50 +0200 Subject: [PATCH 02/19] Clean up preview widget interface a little. --- openlp/core/ui/listpreviewwidget.py | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/openlp/core/ui/listpreviewwidget.py b/openlp/core/ui/listpreviewwidget.py index 44735c58a..6f26d390b 100644 --- a/openlp/core/ui/listpreviewwidget.py +++ b/openlp/core/ui/listpreviewwidget.py @@ -70,10 +70,6 @@ class ListPreviewWidget(object): else: self.preview_table_widget.hide() - def replace_service_manager_item(self, service_item, width): - self.service_item = service_item - self._refresh(width) - def preview_size_changed(self, width, ratio): """ Takes care of the SlidePreview's size. Is called when one of the the @@ -90,11 +86,12 @@ class ListPreviewWidget(object): for framenumber in range(len(self.service_item.get_frames())): self.preview_table_widget.setRowHeight(framenumber, width / ratio) - def _refresh(self, width, ratio): + def replace_service_manager_item(self, service_item, width, ratio): """ Loads a ServiceItem into the system from ServiceManager Display the slide number passed """ + self.service_item = service_item self.preview_table_widget.clear() self.preview_table_widget.setRowCount(0) self.preview_table_widget.setColumnWidth(0, width) @@ -132,10 +129,10 @@ class ListPreviewWidget(object): if self.service_item.is_text(): self.preview_table_widget.resizeRowsToContents() self.preview_table_widget.setColumnWidth(0, self.preview_table_widget.viewport().size().width()) - #stuff happens here, perhaps the setFocus has to happen later... + #stuff happens here, perhaps the setFocus() has to happen later... self.preview_table_widget.setFocus() - def __updatePreviewSelection(self, slideno): + def update_preview_selection(self, slideno): """ Utility method to update the selected slide in the list. """ @@ -143,9 +140,9 @@ class ListPreviewWidget(object): self.preview_table_widget.selectRow( self.preview_table_widget.rowCount() - 1) else: - self.__checkUpdateSelectedSlide(slideno) + self.check_update_selected_slide(slideno) - def __checkUpdateSelectedSlide(self, row): + def check_update_selected_slide(self, row): """ Check if this slide has been updated """ From 3609d2e0e19b28bb23d4f35f6cca2f2b11d312cc Mon Sep 17 00:00:00 2001 From: Patrick Zimmermann Date: Mon, 15 Apr 2013 19:12:47 +0200 Subject: [PATCH 03/19] Switch over to PreviewListWidget class. Untested. --- openlp/core/ui/__init__.py | 3 +- openlp/core/ui/listpreviewwidget.py | 9 +- openlp/core/ui/slidecontroller.py | 133 +++++++--------------------- 3 files changed, 43 insertions(+), 102 deletions(-) diff --git a/openlp/core/ui/__init__.py b/openlp/core/ui/__init__.py index 49e59e4c1..77993c443 100644 --- a/openlp/core/ui/__init__.py +++ b/openlp/core/ui/__init__.py @@ -99,9 +99,10 @@ from shortcutlistform import ShortcutListForm from mediadockmanager import MediaDockManager from servicemanager import ServiceManager from thememanager import ThemeManager +from listpreviewwidget import ListPreviewWidget __all__ = ['SplashScreen', 'AboutForm', 'SettingsForm', 'MainDisplay', 'SlideController', 'ServiceManager', 'ThemeManager', 'MediaDockManager', 'ServiceItemEditForm', 'FirstTimeForm', 'FirstTimeLanguageForm', 'ThemeForm', 'ThemeLayoutForm', 'FileRenameForm', 'StartTimeForm', 'MainDisplay', 'Display', 'ServiceNoteForm', 'SlideController', 'DisplayController', 'GeneralTab', 'ThemesTab', 'AdvancedTab', 'PluginForm', - 'FormattingTagForm', 'ShortcutListForm'] + 'FormattingTagForm', 'ShortcutListForm', 'ListPreviewWidget'] diff --git a/openlp/core/ui/listpreviewwidget.py b/openlp/core/ui/listpreviewwidget.py index 6f26d390b..178f748a7 100644 --- a/openlp/core/ui/listpreviewwidget.py +++ b/openlp/core/ui/listpreviewwidget.py @@ -32,7 +32,8 @@ The :mod:`slidecontroller` module contains the most important part of OpenLP - t from PyQt4 import QtCore, QtGui -from openlp.core.lib import ImageSource, Registry, ServiceItem +from openlp.core.lib import Registry, ServiceItem + class ListPreviewWidget(object): def __init__(self, parent, is_live): @@ -150,6 +151,12 @@ class ListPreviewWidget(object): self.preview_table_widget.scrollToItem(self.preview_table_widget.item(row + 1, 0)) self.preview_table_widget.selectRow(row) + def currentRow(self): + return self.preview_table_widget.currentRow() + + def rowCount(self): + return self.preview_table_widget.rowCount() + def _get_image_manager(self): """ Adds the image manager to the class dynamically diff --git a/openlp/core/ui/slidecontroller.py b/openlp/core/ui/slidecontroller.py index eaeebfba8..183e0a745 100644 --- a/openlp/core/ui/slidecontroller.py +++ b/openlp/core/ui/slidecontroller.py @@ -38,7 +38,7 @@ from PyQt4 import QtCore, QtGui from openlp.core.lib import OpenLPToolbar, ItemCapabilities, ServiceItem, ImageSource, SlideLimits, \ ServiceItemAction, Settings, Registry, UiStrings, ScreenList, build_icon, build_html, translate -from openlp.core.ui import HideMode, MainDisplay, Display, DisplayControllerType +from openlp.core.ui import HideMode, MainDisplay, Display, DisplayControllerType, ListPreviewWidget from openlp.core.lib.ui import create_action from openlp.core.utils.actions import ActionList, CategoryOrder @@ -157,18 +157,8 @@ class SlideController(DisplayController): self.controller_layout.setSpacing(0) self.controller_layout.setMargin(0) # Controller list view - self.preview_list_widget = QtGui.QTableWidget(self.controller) - self.preview_list_widget.setColumnCount(1) - self.preview_list_widget.horizontalHeader().setVisible(False) - self.preview_list_widget.setColumnWidth(0, self.controller.width()) - self.preview_list_widget.is_live = self.is_live - self.preview_list_widget.setObjectName(u'preview_list_widget') - self.preview_list_widget.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows) - self.preview_list_widget.setSelectionMode(QtGui.QAbstractItemView.SingleSelection) - self.preview_list_widget.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers) - self.preview_list_widget.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) - self.preview_list_widget.setAlternatingRowColors(True) - self.controller_layout.addWidget(self.preview_list_widget) + self.preview_widget = ListPreviewWidget(self, self.is_live) + self.controller_layout.addWidget(self.preview_widget.get_preview_widget()) # Build the full toolbar self.toolbar = OpenLPToolbar(self) size_toolbar_policy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed) @@ -350,7 +340,7 @@ class SlideController(DisplayController): {u'key': u'O', u'configurable': True, u'text': translate('OpenLP.SlideController', 'Go to "Other"')} ] shortcuts.extend([{u'key': unicode(number)} for number in range(10)]) - self.preview_list_widget.addActions([create_action(self, + self.controller.addActions([create_action(self, u'shortcutAction_%s' % s[u'key'], text=s.get(u'text'), can_shortcuts=True, context=QtCore.Qt.WidgetWithChildrenShortcut, @@ -358,20 +348,20 @@ class SlideController(DisplayController): triggers=self._slideShortcutActivated) for s in shortcuts]) self.shortcutTimer.timeout.connect(self._slideShortcutActivated) # Signals - self.preview_list_widget.clicked.connect(self.onSlideSelected) + self.preview_widget.clicked.connect(self.onSlideSelected) if self.is_live: Registry().register_function(u'slidecontroller_live_spin_delay', self.receive_spin_delay) Registry().register_function(u'slidecontroller_toggle_display', self.toggle_display) self.toolbar.set_widget_visible(self.loop_list, False) self.toolbar.set_widget_visible(self.wide_menu, False) else: - self.preview_list_widget.doubleClicked.connect(self.onGoLiveClick) + self.preview_widget.double_clicked.connect(self.onGoLiveClick) self.toolbar.set_widget_visible([u'editSong'], False) if self.is_live: self.setLiveHotkeys(self) - self.__addActionsToWidget(self.preview_list_widget) + self.__addActionsToWidget(self.controller) else: - self.preview_list_widget.addActions([self.nextItem, self.previous_item]) + self.controller.addActions([self.nextItem, self.previous_item]) Registry().register_function(u'slidecontroller_%s_stop_loop' % self.type_prefix, self.on_stop_loop) Registry().register_function(u'slidecontroller_%s_next' % self.type_prefix, self.on_slide_selected_next) Registry().register_function(u'slidecontroller_%s_previous' % self.type_prefix, self.on_slide_selected_previous) @@ -427,7 +417,7 @@ class SlideController(DisplayController): if len(matches) == 1: self.shortcutTimer.stop() self.current_shortcut = u'' - self.__checkUpdateSelectedSlide(self.slideList[matches[0]]) + self.preview_widget.check_update_selected_slide(self.slideList[matches[0]]) self.slideSelected() elif sender_name != u'shortcutTimer': # Start the time as we did not have any match. @@ -437,7 +427,7 @@ class SlideController(DisplayController): if self.current_shortcut in keys: # We had more than one match for example "V1" and "V10", but # "V1" was the slide we wanted to go. - self.__checkUpdateSelectedSlide(self.slideList[self.current_shortcut]) + self.preview_widget.check_update_selected_slide(self.slideList[self.current_shortcut]) self.slideSelected() # Reset the shortcut. self.current_shortcut = u'' @@ -571,16 +561,8 @@ class SlideController(DisplayController): self.preview_display.screen = { u'size': self.preview_display.geometry()} # Make sure that the frames have the correct size. - self.preview_list_widget.setColumnWidth(0, self.preview_list_widget.viewport().size().width()) - if self.service_item: - # Sort out songs, bibles, etc. - if self.service_item.is_text(): - self.preview_list_widget.resizeRowsToContents() - else: - # Sort out image heights. - width = self.main_window.controlSplitter.sizes()[self.split] - for framenumber in range(len(self.service_item.get_frames())): - self.preview_list_widget.setRowHeight(framenumber, width / self.ratio) + width = self.main_window.controlSplitter.sizes()[self.split] + self.preview_widget.preview_size_changed(width, self.ratio) self.onControllerSizeChanged(self.controller.width()) def onControllerSizeChanged(self, width): @@ -706,7 +688,7 @@ class SlideController(DisplayController): Replacement item following a remote edit """ if item == self.service_item: - self._processItem(item, self.preview_list_widget.currentRow()) + self._processItem(item, self.preview_widget.currentRow()) def addServiceManagerItem(self, item, slideno): """ @@ -722,7 +704,7 @@ class SlideController(DisplayController): slidenum = 0 # If service item is the same as the current one, only change slide if slideno >= 0 and item == self.service_item: - self.__checkUpdateSelectedSlide(slidenum) + self.preview_widget.check_update_selected_slide(slidenum) self.slideSelected() else: self._processItem(item, slidenum) @@ -749,10 +731,6 @@ class SlideController(DisplayController): self._resetBlank() Registry().execute(u'%s_start' % service_item.name.lower(), [service_item, self.is_live, self.hide_mode(), slideno]) self.slideList = {} - width = self.main_window.controlSplitter.sizes()[self.split] - self.preview_list_widget.clear() - self.preview_list_widget.setRowCount(0) - self.preview_list_widget.setColumnWidth(0, width) if self.is_live: self.song_menu.menu().clear() self.display.audio_player.reset() @@ -777,9 +755,8 @@ class SlideController(DisplayController): self.setAudioItemsVisibility(True) row = 0 text = [] + width = self.main_window.controlSplitter.sizes()[self.split] for framenumber, frame in enumerate(self.service_item.get_frames()): - self.preview_list_widget.setRowCount(self.preview_list_widget.rowCount() + 1) - item = QtGui.QTableWidgetItem() slideHeight = 0 if self.service_item.is_text(): if frame[u'verseTag']: @@ -795,37 +772,12 @@ class SlideController(DisplayController): else: row += 1 self.slideList[unicode(row)] = row - 1 - item.setText(frame[u'text']) else: - label = QtGui.QLabel() - label.setMargin(4) - if service_item.is_media(): - label.setAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter) - else: - label.setScaledContents(True) - if self.service_item.is_command(): - label.setPixmap(QtGui.QPixmap(frame[u'image'])) - else: - # If current slide set background to image - if framenumber == slideno: - self.service_item.bg_image_bytes = self.image_manager.get_image_bytes(frame[u'path'], - ImageSource.ImagePlugin) - image = self.image_manager.get_image(frame[u'path'], ImageSource.ImagePlugin) - label.setPixmap(QtGui.QPixmap.fromImage(image)) - self.preview_list_widget.setCellWidget(framenumber, 0, label) slideHeight = width * (1 / self.ratio) row += 1 self.slideList[unicode(row)] = row - 1 - text.append(unicode(row)) - self.preview_list_widget.setItem(framenumber, 0, item) - if slideHeight: - self.preview_list_widget.setRowHeight(framenumber, slideHeight) - self.preview_list_widget.setVerticalHeaderLabels(text) - if self.service_item.is_text(): - self.preview_list_widget.resizeRowsToContents() - self.preview_list_widget.setColumnWidth(0, - self.preview_list_widget.viewport().size().width()) - self.__updatePreviewSelection(slideno) + self.preview_widget.update_preview_selection(slideno) + self.preview_widget.replace_service_manager_item(self.service_item, width, self.ratio) self.enableToolBar(service_item) # Pass to display for viewing. # Postpone image build, we need to do this later to avoid the theme @@ -835,7 +787,6 @@ class SlideController(DisplayController): if service_item.is_media(): self.onMediaStart(service_item) self.slideSelected(True) - self.preview_list_widget.setFocus() if old_item: # Close the old item after the new one is opened # This avoids the service theme/desktop flashing on screen @@ -847,16 +798,6 @@ class SlideController(DisplayController): self.onMediaClose() Registry().execute(u'slidecontroller_%s_started' % self.type_prefix, [service_item]) - def __updatePreviewSelection(self, slideno): - """ - Utility method to update the selected slide in the list. - """ - if slideno > self.preview_list_widget.rowCount(): - self.preview_list_widget.selectRow( - self.preview_list_widget.rowCount() - 1) - else: - self.__checkUpdateSelectedSlide(slideno) - # Screen event methods def on_slide_selected_index(self, message): """ @@ -869,7 +810,7 @@ class SlideController(DisplayController): Registry().execute(u'%s_slide' % self.service_item.name.lower(), [self.service_item, self.is_live, index]) self.updatePreview() else: - self.__checkUpdateSelectedSlide(index) + self.preview_widget.check_update_selected_slide(index) self.slideSelected() def mainDisplaySetBackground(self): @@ -1012,9 +953,9 @@ class SlideController(DisplayController): Generate the preview when you click on a slide. if this is the Live Controller also display on the screen """ - row = self.preview_list_widget.currentRow() + row = self.preview_widget.currentRow() self.selected_row = 0 - if -1 < row < self.preview_list_widget.rowCount(): + if -1 < row < self.preview_widget.rowCount(): if self.service_item.is_command(): if self.is_live and not start: Registry().execute(u'%s_slide' % self.service_item.name.lower(), @@ -1032,7 +973,7 @@ class SlideController(DisplayController): self.service_item.bg_image_bytes = None self.updatePreview() self.selected_row = row - self.__checkUpdateSelectedSlide(row) + self.preview_widget.check_update_selected_slide(row) Registry().execute(u'slidecontroller_%s_changed' % self.type_prefix, row) self.display.setFocus() @@ -1040,7 +981,7 @@ class SlideController(DisplayController): """ The slide has been changed. Update the slidecontroller accordingly """ - self.__checkUpdateSelectedSlide(row) + self.preview_widget.check_update_selected_slide(row) self.updatePreview() Registry().execute(u'slidecontroller_%s_changed' % self.type_prefix, row) @@ -1085,8 +1026,8 @@ class SlideController(DisplayController): if self.service_item.is_command() and self.is_live: self.updatePreview() else: - row = self.preview_list_widget.currentRow() + 1 - if row == self.preview_list_widget.rowCount(): + row = self.preview_widget.currentRow() + 1 + if row == self.preview_widget.rowCount(): if wrap is None: if self.slide_limits == SlideLimits.Wrap: row = 0 @@ -1094,12 +1035,12 @@ class SlideController(DisplayController): self.serviceNext() return else: - row = self.preview_list_widget.rowCount() - 1 + row = self.preview_widget.rowCount() - 1 elif wrap: row = 0 else: - row = self.preview_list_widget.rowCount() - 1 - self.__checkUpdateSelectedSlide(row) + row = self.preview_widget.rowCount() - 1 + self.preview_widget.check_update_selected_slide(row) self.slideSelected() def on_slide_selected_previous(self): @@ -1112,27 +1053,19 @@ class SlideController(DisplayController): if self.service_item.is_command() and self.is_live: self.updatePreview() else: - row = self.preview_list_widget.currentRow() - 1 + row = self.preview_widget.currentRow() - 1 if row == -1: if self.slide_limits == SlideLimits.Wrap: - row = self.preview_list_widget.rowCount() - 1 + row = self.preview_widget.rowCount() - 1 elif self.is_live and self.slide_limits == SlideLimits.Next: self.keypress_queue.append(ServiceItemAction.PreviousLastSlide) self._process_queue() return else: row = 0 - self.__checkUpdateSelectedSlide(row) + self.preview_widget.check_update_selected_slide(row) self.slideSelected() - def __checkUpdateSelectedSlide(self, row): - """ - Check if this slide has been updated - """ - if row + 1 < self.preview_list_widget.rowCount(): - self.preview_list_widget.scrollToItem(self.preview_list_widget.item(row + 1, 0)) - self.preview_list_widget.selectRow(row) - def onToggleLoop(self): """ Toggles the loop state. @@ -1147,7 +1080,7 @@ class SlideController(DisplayController): """ Start the timer loop running and store the timer id """ - if self.preview_list_widget.rowCount() > 1: + if self.preview_widget.rowCount() > 1: self.timer_id = self.startTimer(int(self.delay_spin_box.value()) * 1000) def on_stop_loop(self): @@ -1257,8 +1190,8 @@ class SlideController(DisplayController): """ If preview copy slide item to live controller from Preview Controller """ - row = self.preview_list_widget.currentRow() - if -1 < row < self.preview_list_widget.rowCount(): + row = self.preview_widget.currentRow() + if -1 < row < self.preview_widget.rowCount(): if self.service_item.from_service: self.service_manager.preview_live(self.service_item.unique_identifier, row) else: From 0dbda9ee21514ecf7c0c9f60f7641a8c5357d54a Mon Sep 17 00:00:00 2001 From: Patrick Zimmermann Date: Mon, 15 Apr 2013 19:26:18 +0200 Subject: [PATCH 04/19] Accidentially removed image load logic. Readded. --- openlp/core/ui/listpreviewwidget.py | 16 +++++++++++++--- openlp/core/ui/slidecontroller.py | 2 +- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/openlp/core/ui/listpreviewwidget.py b/openlp/core/ui/listpreviewwidget.py index 178f748a7..d455a7477 100644 --- a/openlp/core/ui/listpreviewwidget.py +++ b/openlp/core/ui/listpreviewwidget.py @@ -32,7 +32,7 @@ The :mod:`slidecontroller` module contains the most important part of OpenLP - t from PyQt4 import QtCore, QtGui -from openlp.core.lib import Registry, ServiceItem +from openlp.core.lib import ImageSource, Registry, ServiceItem class ListPreviewWidget(object): @@ -87,7 +87,7 @@ class ListPreviewWidget(object): for framenumber in range(len(self.service_item.get_frames())): self.preview_table_widget.setRowHeight(framenumber, width / ratio) - def replace_service_manager_item(self, service_item, width, ratio): + def replace_service_manager_item(self, service_item, width, ratio, slideno): """ Loads a ServiceItem into the system from ServiceManager Display the slide number passed @@ -119,6 +119,15 @@ class ListPreviewWidget(object): label.setAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter) else: label.setScaledContents(True) + if self.service_item.is_command(): + label.setPixmap(QtGui.QPixmap(frame[u'image'])) + else: + # If current slide set background to image + if framenumber == slideno: + self.service_item.bg_image_bytes = self.image_manager.get_image_bytes(frame[u'path'], + ImageSource.ImagePlugin) + image = self.image_manager.get_image(frame[u'path'], ImageSource.ImagePlugin) + label.setPixmap(QtGui.QPixmap.fromImage(image)) self.preview_table_widget.setCellWidget(framenumber, 0, label) slideHeight = width / ratio row += 1 @@ -175,4 +184,5 @@ class ListPreviewWidget(object): self._main_window = Registry().get(u'main_window') return self._main_window - main_window = property(_get_main_window) \ No newline at end of file + main_window = property(_get_main_window) + diff --git a/openlp/core/ui/slidecontroller.py b/openlp/core/ui/slidecontroller.py index 183e0a745..15ba53b2f 100644 --- a/openlp/core/ui/slidecontroller.py +++ b/openlp/core/ui/slidecontroller.py @@ -36,7 +36,7 @@ from collections import deque from PyQt4 import QtCore, QtGui -from openlp.core.lib import OpenLPToolbar, ItemCapabilities, ServiceItem, ImageSource, SlideLimits, \ +from openlp.core.lib import OpenLPToolbar, ItemCapabilities, ServiceItem, SlideLimits, \ ServiceItemAction, Settings, Registry, UiStrings, ScreenList, build_icon, build_html, translate from openlp.core.ui import HideMode, MainDisplay, Display, DisplayControllerType, ListPreviewWidget from openlp.core.lib.ui import create_action From fd22d17d371069e2a690131d787220c1b97f9dbc Mon Sep 17 00:00:00 2001 From: Patrick Zimmermann Date: Mon, 15 Apr 2013 20:01:59 +0200 Subject: [PATCH 05/19] Fix an import problem and use signals correctly. Worksbzr diff --- openlp/core/ui/__init__.py | 3 +-- openlp/core/ui/listpreviewwidget.py | 17 +++++++++-------- openlp/core/ui/slidecontroller.py | 5 +++-- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/openlp/core/ui/__init__.py b/openlp/core/ui/__init__.py index 77993c443..49e59e4c1 100644 --- a/openlp/core/ui/__init__.py +++ b/openlp/core/ui/__init__.py @@ -99,10 +99,9 @@ from shortcutlistform import ShortcutListForm from mediadockmanager import MediaDockManager from servicemanager import ServiceManager from thememanager import ThemeManager -from listpreviewwidget import ListPreviewWidget __all__ = ['SplashScreen', 'AboutForm', 'SettingsForm', 'MainDisplay', 'SlideController', 'ServiceManager', 'ThemeManager', 'MediaDockManager', 'ServiceItemEditForm', 'FirstTimeForm', 'FirstTimeLanguageForm', 'ThemeForm', 'ThemeLayoutForm', 'FileRenameForm', 'StartTimeForm', 'MainDisplay', 'Display', 'ServiceNoteForm', 'SlideController', 'DisplayController', 'GeneralTab', 'ThemesTab', 'AdvancedTab', 'PluginForm', - 'FormattingTagForm', 'ShortcutListForm', 'ListPreviewWidget'] + 'FormattingTagForm', 'ShortcutListForm'] diff --git a/openlp/core/ui/listpreviewwidget.py b/openlp/core/ui/listpreviewwidget.py index d455a7477..d1639b742 100644 --- a/openlp/core/ui/listpreviewwidget.py +++ b/openlp/core/ui/listpreviewwidget.py @@ -35,9 +35,12 @@ from PyQt4 import QtCore, QtGui from openlp.core.lib import ImageSource, Registry, ServiceItem -class ListPreviewWidget(object): +class ListPreviewWidget(QtCore.QObject): + clicked = QtCore.pyqtSignal() + double_clicked = QtCore.pyqtSignal() + def __init__(self, parent, is_live): - # Controller list view + super(QtCore.QObject, self).__init__() self.is_live = is_live self.preview_table_widget = QtGui.QTableWidget(parent) self.preview_table_widget.setColumnCount(1) @@ -50,16 +53,14 @@ class ListPreviewWidget(object): self.preview_table_widget.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) self.preview_table_widget.setAlternatingRowColors(True) self.service_item = ServiceItem() - self.clicked = QtCore.pyqtSignal() - self.double_clicked = QtCore.pyqtSignal() if not self.is_live: - self.preview_table_widget.doubleClicked.connect(self.double_clicked) - self.preview_table_widget.clicked.connect(self.clicked) + self.preview_table_widget.doubleClicked.connect(self._double_clicked) + self.preview_table_widget.clicked.connect(self._clicked) - def clicked(self): + def _clicked(self): self.clicked.emit() - def double_clicked(self): + def _double_clicked(self): self.double_clicked.emit() def get_preview_widget(self): diff --git a/openlp/core/ui/slidecontroller.py b/openlp/core/ui/slidecontroller.py index 15ba53b2f..8492b69bb 100644 --- a/openlp/core/ui/slidecontroller.py +++ b/openlp/core/ui/slidecontroller.py @@ -38,9 +38,10 @@ from PyQt4 import QtCore, QtGui from openlp.core.lib import OpenLPToolbar, ItemCapabilities, ServiceItem, SlideLimits, \ ServiceItemAction, Settings, Registry, UiStrings, ScreenList, build_icon, build_html, translate -from openlp.core.ui import HideMode, MainDisplay, Display, DisplayControllerType, ListPreviewWidget +from openlp.core.ui import HideMode, MainDisplay, Display, DisplayControllerType from openlp.core.lib.ui import create_action from openlp.core.utils.actions import ActionList, CategoryOrder +from openlp.core.ui.listpreviewwidget import ListPreviewWidget log = logging.getLogger(__name__) @@ -777,7 +778,7 @@ class SlideController(DisplayController): row += 1 self.slideList[unicode(row)] = row - 1 self.preview_widget.update_preview_selection(slideno) - self.preview_widget.replace_service_manager_item(self.service_item, width, self.ratio) + self.preview_widget.replace_service_manager_item(self.service_item, width, self.ratio, slideno) self.enableToolBar(service_item) # Pass to display for viewing. # Postpone image build, we need to do this later to avoid the theme From e4d3d8d6d2d9444dd85d49c5a2df713f1f773ec9 Mon Sep 17 00:00:00 2001 From: Patrick Zimmermann Date: Tue, 16 Apr 2013 19:33:36 +0200 Subject: [PATCH 06/19] Rename a slideno -> row for more consistency. --- openlp/core/ui/listpreviewwidget.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/openlp/core/ui/listpreviewwidget.py b/openlp/core/ui/listpreviewwidget.py index d1639b742..3e9bc065c 100644 --- a/openlp/core/ui/listpreviewwidget.py +++ b/openlp/core/ui/listpreviewwidget.py @@ -143,15 +143,14 @@ class ListPreviewWidget(QtCore.QObject): #stuff happens here, perhaps the setFocus() has to happen later... self.preview_table_widget.setFocus() - def update_preview_selection(self, slideno): + def update_preview_selection(self, row): """ Utility method to update the selected slide in the list. """ - if slideno > self.preview_table_widget.rowCount(): - self.preview_table_widget.selectRow( - self.preview_table_widget.rowCount() - 1) + if row > self.preview_table_widget.rowCount(): + self.preview_table_widget.selectRow(self.preview_table_widget.rowCount() - 1) else: - self.check_update_selected_slide(slideno) + self.check_update_selected_slide(row) def check_update_selected_slide(self, row): """ From 1bbf52c7bfe9b537feb27ae6d7e055c2d3e0b225 Mon Sep 17 00:00:00 2001 From: Patrick Zimmermann Date: Tue, 16 Apr 2013 19:34:07 +0200 Subject: [PATCH 07/19] Fix a logic error, an array index border was wrong. --- openlp/core/ui/listpreviewwidget.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openlp/core/ui/listpreviewwidget.py b/openlp/core/ui/listpreviewwidget.py index 3e9bc065c..fb94555fd 100644 --- a/openlp/core/ui/listpreviewwidget.py +++ b/openlp/core/ui/listpreviewwidget.py @@ -147,7 +147,7 @@ class ListPreviewWidget(QtCore.QObject): """ Utility method to update the selected slide in the list. """ - if row > self.preview_table_widget.rowCount(): + if row >= self.preview_table_widget.rowCount(): self.preview_table_widget.selectRow(self.preview_table_widget.rowCount() - 1) else: self.check_update_selected_slide(row) From d68728833601b2a7b98759330aae37f3338c1723 Mon Sep 17 00:00:00 2001 From: Patrick Zimmermann Date: Tue, 16 Apr 2013 23:42:23 +0200 Subject: [PATCH 08/19] Correct a preview_list_widget -> preview_widget call and fix update of preview when switching the service item. --- openlp/core/ui/servicemanager.py | 2 +- openlp/core/ui/slidecontroller.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/openlp/core/ui/servicemanager.py b/openlp/core/ui/servicemanager.py index 6e0f4ad95..4aa7c5307 100644 --- a/openlp/core/ui/servicemanager.py +++ b/openlp/core/ui/servicemanager.py @@ -1379,7 +1379,7 @@ class ServiceManager(QtGui.QWidget, ServiceManagerDialog): self.preview_controller.addServiceManagerItem(self.service_items[item][u'service_item'], 0) next_item = self.service_manager_list.topLevelItem(item) self.service_manager_list.setCurrentItem(next_item) - self.live_controller.preview_list_widget.setFocus() + self.live_controller.preview_widget.get_preview_widget().setFocus() else: critical_error_message_box(translate('OpenLP.ServiceManager', 'Missing Display Handler'), translate('OpenLP.ServiceManager', diff --git a/openlp/core/ui/slidecontroller.py b/openlp/core/ui/slidecontroller.py index 8492b69bb..d1694ca56 100644 --- a/openlp/core/ui/slidecontroller.py +++ b/openlp/core/ui/slidecontroller.py @@ -777,8 +777,8 @@ class SlideController(DisplayController): slideHeight = width * (1 / self.ratio) row += 1 self.slideList[unicode(row)] = row - 1 - self.preview_widget.update_preview_selection(slideno) self.preview_widget.replace_service_manager_item(self.service_item, width, self.ratio, slideno) + self.preview_widget.update_preview_selection(slideno) self.enableToolBar(service_item) # Pass to display for viewing. # Postpone image build, we need to do this later to avoid the theme From 25db18d34cb9ad6c1067297b1fc4e30610b647de Mon Sep 17 00:00:00 2001 From: Patrick Zimmermann Date: Thu, 18 Apr 2013 22:15:44 +0200 Subject: [PATCH 09/19] Use inheritance instead of composition. Some interface cleanup. --- openlp/core/ui/listpreviewwidget.py | 113 +++++++++++++--------------- openlp/core/ui/servicemanager.py | 2 +- openlp/core/ui/slidecontroller.py | 11 ++- 3 files changed, 57 insertions(+), 69 deletions(-) diff --git a/openlp/core/ui/listpreviewwidget.py b/openlp/core/ui/listpreviewwidget.py index fb94555fd..e9025a255 100644 --- a/openlp/core/ui/listpreviewwidget.py +++ b/openlp/core/ui/listpreviewwidget.py @@ -35,72 +35,61 @@ from PyQt4 import QtCore, QtGui from openlp.core.lib import ImageSource, Registry, ServiceItem -class ListPreviewWidget(QtCore.QObject): - clicked = QtCore.pyqtSignal() - double_clicked = QtCore.pyqtSignal() - - def __init__(self, parent, is_live): - super(QtCore.QObject, self).__init__() - self.is_live = is_live - self.preview_table_widget = QtGui.QTableWidget(parent) - self.preview_table_widget.setColumnCount(1) - self.preview_table_widget.horizontalHeader().setVisible(False) - self.preview_table_widget.setColumnWidth(0, parent.width()) - self.preview_table_widget.setObjectName(u'preview_table_widget') - self.preview_table_widget.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows) - self.preview_table_widget.setSelectionMode(QtGui.QAbstractItemView.SingleSelection) - self.preview_table_widget.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers) - self.preview_table_widget.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) - self.preview_table_widget.setAlternatingRowColors(True) +class ListPreviewWidget(QtGui.QTableWidget): + def __init__(self, parent, screen_ratio): + super(QtGui.QTableWidget, self).__init__(parent) self.service_item = ServiceItem() - if not self.is_live: - self.preview_table_widget.doubleClicked.connect(self._double_clicked) - self.preview_table_widget.clicked.connect(self._clicked) + self.screen_ratio = screen_ratio - def _clicked(self): - self.clicked.emit() + self.setColumnCount(1) + self.horizontalHeader().setVisible(False) + self.setColumnWidth(0, parent.width()) + self.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows) + self.setSelectionMode(QtGui.QAbstractItemView.SingleSelection) + self.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers) + self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) + self.setAlternatingRowColors(True) - def _double_clicked(self): - self.double_clicked.emit() + def resizeEvent(self, QResizeEvent): + self.__recalculate_layout() - def get_preview_widget(self): - return self.preview_table_widget - - def set_active(self, active): - if active: - self.preview_table_widget.show() - else: - self.preview_table_widget.hide() - - def preview_size_changed(self, width, ratio): - """ - Takes care of the SlidePreview's size. Is called when one of the the - splitters is moved or when the screen size is changed. Note, that this - method is (also) called frequently from the mainwindow *paintEvent*. - """ - self.preview_table_widget.setColumnWidth(0, self.preview_table_widget.viewport().size().width()) + def __recalculate_layout(self): + self.setColumnWidth(0, self.viewport().width()) if self.service_item: # Sort out songs, bibles, etc. if self.service_item.is_text(): - self.preview_table_widget.resizeRowsToContents() + self.resizeRowsToContents() else: # Sort out image heights. for framenumber in range(len(self.service_item.get_frames())): - self.preview_table_widget.setRowHeight(framenumber, width / ratio) + #self.setRowHeight(framenumber, width / ratio) + height = self.viewport().width() / self.screen_ratio + self.setRowHeight(framenumber, height) - def replace_service_manager_item(self, service_item, width, ratio, slideno): + #width = self.main_window.controlSplitter.sizes()[self.split] + def screen_size_changed(self, screen_ratio): + self.screen_ratio = screen_ratio + self.__recalculate_layout() + + def set_active(self, active): + if active: + self.show() + else: + self.hide() + + def replace_service_manager_item(self, service_item, width, slideno): """ Loads a ServiceItem into the system from ServiceManager Display the slide number passed """ self.service_item = service_item - self.preview_table_widget.clear() - self.preview_table_widget.setRowCount(0) - self.preview_table_widget.setColumnWidth(0, width) + self.clear() + self.setRowCount(0) + self.setColumnWidth(0, width) row = 0 text = [] for framenumber, frame in enumerate(self.service_item.get_frames()): - self.preview_table_widget.setRowCount(self.preview_table_widget.rowCount() + 1) + self.setRowCount(self.rowCount() + 1) item = QtGui.QTableWidgetItem() slideHeight = 0 if self.service_item.is_text(): @@ -129,26 +118,26 @@ class ListPreviewWidget(QtCore.QObject): ImageSource.ImagePlugin) image = self.image_manager.get_image(frame[u'path'], ImageSource.ImagePlugin) label.setPixmap(QtGui.QPixmap.fromImage(image)) - self.preview_table_widget.setCellWidget(framenumber, 0, label) - slideHeight = width / ratio + self.setCellWidget(framenumber, 0, label) + slideHeight = width / self.screen_ratio row += 1 text.append(unicode(row)) - self.preview_table_widget.setItem(framenumber, 0, item) + self.setItem(framenumber, 0, item) if slideHeight: - self.preview_table_widget.setRowHeight(framenumber, slideHeight) - self.preview_table_widget.setVerticalHeaderLabels(text) + self.setRowHeight(framenumber, slideHeight) + self.setVerticalHeaderLabels(text) if self.service_item.is_text(): - self.preview_table_widget.resizeRowsToContents() - self.preview_table_widget.setColumnWidth(0, self.preview_table_widget.viewport().size().width()) + self.resizeRowsToContents() + self.setColumnWidth(0, self.viewport().width()) #stuff happens here, perhaps the setFocus() has to happen later... - self.preview_table_widget.setFocus() + self.setFocus() def update_preview_selection(self, row): """ Utility method to update the selected slide in the list. """ - if row >= self.preview_table_widget.rowCount(): - self.preview_table_widget.selectRow(self.preview_table_widget.rowCount() - 1) + if row >= self.rowCount(): + self.selectRow(self.rowCount() - 1) else: self.check_update_selected_slide(row) @@ -156,15 +145,15 @@ class ListPreviewWidget(QtCore.QObject): """ Check if this slide has been updated """ - if row + 1 < self.preview_table_widget.rowCount(): - self.preview_table_widget.scrollToItem(self.preview_table_widget.item(row + 1, 0)) - self.preview_table_widget.selectRow(row) + if row + 1 < self.rowCount(): + self.scrollToItem(self.item(row + 1, 0)) + self.selectRow(row) def currentRow(self): - return self.preview_table_widget.currentRow() + return super(ListPreviewWidget, self).currentRow() def rowCount(self): - return self.preview_table_widget.rowCount() + return super(ListPreviewWidget, self).rowCount() def _get_image_manager(self): """ diff --git a/openlp/core/ui/servicemanager.py b/openlp/core/ui/servicemanager.py index 4aa7c5307..51e3f790d 100644 --- a/openlp/core/ui/servicemanager.py +++ b/openlp/core/ui/servicemanager.py @@ -1379,7 +1379,7 @@ class ServiceManager(QtGui.QWidget, ServiceManagerDialog): self.preview_controller.addServiceManagerItem(self.service_items[item][u'service_item'], 0) next_item = self.service_manager_list.topLevelItem(item) self.service_manager_list.setCurrentItem(next_item) - self.live_controller.preview_widget.get_preview_widget().setFocus() + self.live_controller.preview_widget.setFocus() else: critical_error_message_box(translate('OpenLP.ServiceManager', 'Missing Display Handler'), translate('OpenLP.ServiceManager', diff --git a/openlp/core/ui/slidecontroller.py b/openlp/core/ui/slidecontroller.py index d1694ca56..6e5e5c8b7 100644 --- a/openlp/core/ui/slidecontroller.py +++ b/openlp/core/ui/slidecontroller.py @@ -158,8 +158,8 @@ class SlideController(DisplayController): self.controller_layout.setSpacing(0) self.controller_layout.setMargin(0) # Controller list view - self.preview_widget = ListPreviewWidget(self, self.is_live) - self.controller_layout.addWidget(self.preview_widget.get_preview_widget()) + self.preview_widget = ListPreviewWidget(self, self.ratio) + self.controller_layout.addWidget(self.preview_widget) # Build the full toolbar self.toolbar = OpenLPToolbar(self) size_toolbar_policy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed) @@ -356,7 +356,7 @@ class SlideController(DisplayController): self.toolbar.set_widget_visible(self.loop_list, False) self.toolbar.set_widget_visible(self.wide_menu, False) else: - self.preview_widget.double_clicked.connect(self.onGoLiveClick) + self.preview_widget.doubleClicked.connect(self.onGoLiveClick) self.toolbar.set_widget_visible([u'editSong'], False) if self.is_live: self.setLiveHotkeys(self) @@ -524,6 +524,7 @@ class SlideController(DisplayController): self.ratio = 1 self.media_controller.setup_display(self.display, False) self.previewSizeChanged() + self.preview_widget.screen_size_changed(self.ratio) self.preview_display.setup() service_item = ServiceItem() self.preview_display.web_view.setHtml(build_html(service_item, self.preview_display.screen, None, self.is_live, @@ -562,8 +563,6 @@ class SlideController(DisplayController): self.preview_display.screen = { u'size': self.preview_display.geometry()} # Make sure that the frames have the correct size. - width = self.main_window.controlSplitter.sizes()[self.split] - self.preview_widget.preview_size_changed(width, self.ratio) self.onControllerSizeChanged(self.controller.width()) def onControllerSizeChanged(self, width): @@ -777,7 +776,7 @@ class SlideController(DisplayController): slideHeight = width * (1 / self.ratio) row += 1 self.slideList[unicode(row)] = row - 1 - self.preview_widget.replace_service_manager_item(self.service_item, width, self.ratio, slideno) + self.preview_widget.replace_service_manager_item(self.service_item, width, slideno) self.preview_widget.update_preview_selection(slideno) self.enableToolBar(service_item) # Pass to display for viewing. From 2b9a13ff97fdd84ad63ade409e2333d7801f1d0f Mon Sep 17 00:00:00 2001 From: Patrick Zimmermann Date: Thu, 18 Apr 2013 22:50:02 +0200 Subject: [PATCH 10/19] Clean up PreviewWidget interface a little more. --- openlp/core/ui/listpreviewwidget.py | 52 +++++++++++++---------------- openlp/core/ui/slidecontroller.py | 23 +++++++------ 2 files changed, 36 insertions(+), 39 deletions(-) diff --git a/openlp/core/ui/listpreviewwidget.py b/openlp/core/ui/listpreviewwidget.py index e9025a255..78b9d26e4 100644 --- a/openlp/core/ui/listpreviewwidget.py +++ b/openlp/core/ui/listpreviewwidget.py @@ -51,9 +51,16 @@ class ListPreviewWidget(QtGui.QTableWidget): self.setAlternatingRowColors(True) def resizeEvent(self, QResizeEvent): + """ + Overloaded method from QTableWidget. Will recalculate the layout. + """ self.__recalculate_layout() def __recalculate_layout(self): + """ + Recalculates the layout of the table widget. It will set height and width + of the table cells. QTableWidget does not adapt the cells to the widget size at all. + """ self.setColumnWidth(0, self.viewport().width()) if self.service_item: # Sort out songs, bibles, etc. @@ -66,21 +73,18 @@ class ListPreviewWidget(QtGui.QTableWidget): height = self.viewport().width() / self.screen_ratio self.setRowHeight(framenumber, height) - #width = self.main_window.controlSplitter.sizes()[self.split] def screen_size_changed(self, screen_ratio): + """ + To be called whenever the live screen size changes. + Because this makes a layout recalculation necessary. + """ self.screen_ratio = screen_ratio self.__recalculate_layout() - def set_active(self, active): - if active: - self.show() - else: - self.hide() - - def replace_service_manager_item(self, service_item, width, slideno): + def replace_service_manager_item(self, service_item, width, slide): """ - Loads a ServiceItem into the system from ServiceManager - Display the slide number passed + Replaces the current preview items with the ones in service_item. + Displays the given slide. """ self.service_item = service_item self.clear() @@ -112,10 +116,6 @@ class ListPreviewWidget(QtGui.QTableWidget): if self.service_item.is_command(): label.setPixmap(QtGui.QPixmap(frame[u'image'])) else: - # If current slide set background to image - if framenumber == slideno: - self.service_item.bg_image_bytes = self.image_manager.get_image_bytes(frame[u'path'], - ImageSource.ImagePlugin) image = self.image_manager.get_image(frame[u'path'], ImageSource.ImagePlugin) label.setPixmap(QtGui.QPixmap.fromImage(image)) self.setCellWidget(framenumber, 0, label) @@ -129,25 +129,19 @@ class ListPreviewWidget(QtGui.QTableWidget): if self.service_item.is_text(): self.resizeRowsToContents() self.setColumnWidth(0, self.viewport().width()) - #stuff happens here, perhaps the setFocus() has to happen later... self.setFocus() + self.change_slide(slide) - def update_preview_selection(self, row): + def change_slide(self, slide): """ - Utility method to update the selected slide in the list. + Switches to the given row. """ - if row >= self.rowCount(): - self.selectRow(self.rowCount() - 1) - else: - self.check_update_selected_slide(row) - - def check_update_selected_slide(self, row): - """ - Check if this slide has been updated - """ - if row + 1 < self.rowCount(): - self.scrollToItem(self.item(row + 1, 0)) - self.selectRow(row) + if slide >= self.rowCount(): + slide = self.rowCount() - 1 + #Scroll to next item if possible. + if slide + 1 < self.rowCount(): + self.scrollToItem(self.item(slide + 1, 0)) + self.selectRow(slide) def currentRow(self): return super(ListPreviewWidget, self).currentRow() diff --git a/openlp/core/ui/slidecontroller.py b/openlp/core/ui/slidecontroller.py index 6e5e5c8b7..3ae696277 100644 --- a/openlp/core/ui/slidecontroller.py +++ b/openlp/core/ui/slidecontroller.py @@ -36,7 +36,7 @@ from collections import deque from PyQt4 import QtCore, QtGui -from openlp.core.lib import OpenLPToolbar, ItemCapabilities, ServiceItem, SlideLimits, \ +from openlp.core.lib import OpenLPToolbar, ImageSource, ItemCapabilities, ServiceItem, SlideLimits, \ ServiceItemAction, Settings, Registry, UiStrings, ScreenList, build_icon, build_html, translate from openlp.core.ui import HideMode, MainDisplay, Display, DisplayControllerType from openlp.core.lib.ui import create_action @@ -418,7 +418,7 @@ class SlideController(DisplayController): if len(matches) == 1: self.shortcutTimer.stop() self.current_shortcut = u'' - self.preview_widget.check_update_selected_slide(self.slideList[matches[0]]) + self.preview_widget.change_slide(self.slideList[matches[0]]) self.slideSelected() elif sender_name != u'shortcutTimer': # Start the time as we did not have any match. @@ -428,7 +428,7 @@ class SlideController(DisplayController): if self.current_shortcut in keys: # We had more than one match for example "V1" and "V10", but # "V1" was the slide we wanted to go. - self.preview_widget.check_update_selected_slide(self.slideList[self.current_shortcut]) + self.preview_widget.change_slide(self.slideList[self.current_shortcut]) self.slideSelected() # Reset the shortcut. self.current_shortcut = u'' @@ -704,7 +704,7 @@ class SlideController(DisplayController): slidenum = 0 # If service item is the same as the current one, only change slide if slideno >= 0 and item == self.service_item: - self.preview_widget.check_update_selected_slide(slidenum) + self.preview_widget.change_slide(slidenum) self.slideSelected() else: self._processItem(item, slidenum) @@ -776,8 +776,11 @@ class SlideController(DisplayController): slideHeight = width * (1 / self.ratio) row += 1 self.slideList[unicode(row)] = row - 1 + # If current slide set background to image + if not self.service_item.is_command() and framenumber == slideno: + self.service_item.bg_image_bytes = self.image_manager.get_image_bytes(frame[u'path'], + ImageSource.ImagePlugin) self.preview_widget.replace_service_manager_item(self.service_item, width, slideno) - self.preview_widget.update_preview_selection(slideno) self.enableToolBar(service_item) # Pass to display for viewing. # Postpone image build, we need to do this later to avoid the theme @@ -810,7 +813,7 @@ class SlideController(DisplayController): Registry().execute(u'%s_slide' % self.service_item.name.lower(), [self.service_item, self.is_live, index]) self.updatePreview() else: - self.preview_widget.check_update_selected_slide(index) + self.preview_widget.change_slide(index) self.slideSelected() def mainDisplaySetBackground(self): @@ -973,7 +976,7 @@ class SlideController(DisplayController): self.service_item.bg_image_bytes = None self.updatePreview() self.selected_row = row - self.preview_widget.check_update_selected_slide(row) + self.preview_widget.change_slide(row) Registry().execute(u'slidecontroller_%s_changed' % self.type_prefix, row) self.display.setFocus() @@ -981,7 +984,7 @@ class SlideController(DisplayController): """ The slide has been changed. Update the slidecontroller accordingly """ - self.preview_widget.check_update_selected_slide(row) + self.preview_widget.change_slide(row) self.updatePreview() Registry().execute(u'slidecontroller_%s_changed' % self.type_prefix, row) @@ -1040,7 +1043,7 @@ class SlideController(DisplayController): row = 0 else: row = self.preview_widget.rowCount() - 1 - self.preview_widget.check_update_selected_slide(row) + self.preview_widget.change_slide(row) self.slideSelected() def on_slide_selected_previous(self): @@ -1063,7 +1066,7 @@ class SlideController(DisplayController): return else: row = 0 - self.preview_widget.check_update_selected_slide(row) + self.preview_widget.change_slide(row) self.slideSelected() def onToggleLoop(self): From 823e7b1ec0163385e7b2ba6cdf094bdfaa624a21 Mon Sep 17 00:00:00 2001 From: Patrick Zimmermann Date: Mon, 22 Apr 2013 22:51:33 +0200 Subject: [PATCH 11/19] Change a line back to trunk state. --- openlp/core/ui/slidecontroller.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openlp/core/ui/slidecontroller.py b/openlp/core/ui/slidecontroller.py index 18d2eed09..36a47ae87 100644 --- a/openlp/core/ui/slidecontroller.py +++ b/openlp/core/ui/slidecontroller.py @@ -36,7 +36,7 @@ from collections import deque from PyQt4 import QtCore, QtGui -from openlp.core.lib import OpenLPToolbar, ImageSource, ItemCapabilities, ServiceItem, SlideLimits, \ +from openlp.core.lib import OpenLPToolbar, ItemCapabilities, ServiceItem, ImageSource, SlideLimits, \ ServiceItemAction, Settings, Registry, UiStrings, ScreenList, build_icon, build_html, translate from openlp.core.ui import HideMode, MainDisplay, Display, DisplayControllerType from openlp.core.lib.ui import create_action From 145a1aedcb6f9bb6022428e66636f5677985243a Mon Sep 17 00:00:00 2001 From: Patrick Zimmermann Date: Tue, 23 Apr 2013 19:12:08 +0200 Subject: [PATCH 12/19] Add some docstrings and rename some methods for clarity. --- openlp/core/ui/listpreviewwidget.py | 36 +++++++++++++++++++---------- openlp/core/ui/slidecontroller.py | 24 +++++++++---------- 2 files changed, 36 insertions(+), 24 deletions(-) diff --git a/openlp/core/ui/listpreviewwidget.py b/openlp/core/ui/listpreviewwidget.py index 78b9d26e4..636d58468 100644 --- a/openlp/core/ui/listpreviewwidget.py +++ b/openlp/core/ui/listpreviewwidget.py @@ -27,7 +27,8 @@ # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### """ -The :mod:`slidecontroller` module contains the most important part of OpenLP - the slide controller +The :mod:`listpreviewwidget` is a widget that lists the slides in the slide controller. +It is based on a QTableWidget but represents its contents in list form. """ from PyQt4 import QtCore, QtGui @@ -37,6 +38,11 @@ from openlp.core.lib import ImageSource, Registry, ServiceItem class ListPreviewWidget(QtGui.QTableWidget): def __init__(self, parent, screen_ratio): + """ + Initializes the widget to default state. + An empty ServiceItem is used per default. + One needs to call replace_service_manager_item() to make this widget display something. + """ super(QtGui.QTableWidget, self).__init__(parent) self.service_item = ServiceItem() self.screen_ratio = screen_ratio @@ -59,7 +65,7 @@ class ListPreviewWidget(QtGui.QTableWidget): def __recalculate_layout(self): """ Recalculates the layout of the table widget. It will set height and width - of the table cells. QTableWidget does not adapt the cells to the widget size at all. + of the table cells. QTableWidget does not adapt the cells to the widget size on its own. """ self.setColumnWidth(0, self.viewport().width()) if self.service_item: @@ -81,7 +87,7 @@ class ListPreviewWidget(QtGui.QTableWidget): self.screen_ratio = screen_ratio self.__recalculate_layout() - def replace_service_manager_item(self, service_item, width, slide): + def replace_service_manager_item(self, service_item, width, slideNumber): """ Replaces the current preview items with the ones in service_item. Displays the given slide. @@ -93,7 +99,7 @@ class ListPreviewWidget(QtGui.QTableWidget): row = 0 text = [] for framenumber, frame in enumerate(self.service_item.get_frames()): - self.setRowCount(self.rowCount() + 1) + self.setRowCount(self.slide_count() + 1) item = QtGui.QTableWidgetItem() slideHeight = 0 if self.service_item.is_text(): @@ -130,28 +136,34 @@ class ListPreviewWidget(QtGui.QTableWidget): self.resizeRowsToContents() self.setColumnWidth(0, self.viewport().width()) self.setFocus() - self.change_slide(slide) + self.change_slide(slideNumber) def change_slide(self, slide): """ Switches to the given row. """ - if slide >= self.rowCount(): - slide = self.rowCount() - 1 + if slide >= self.slide_count(): + slide = self.slide_count() - 1 #Scroll to next item if possible. - if slide + 1 < self.rowCount(): + if slide + 1 < self.slide_count(): self.scrollToItem(self.item(slide + 1, 0)) self.selectRow(slide) - def currentRow(self): + def current_slide_number(self): + """ + Returns the position of the currently active item. Will return -1 if the widget is empty. + """ return super(ListPreviewWidget, self).currentRow() - def rowCount(self): + def slide_count(self): + """ + Returns the number of slides this widget holds. + """ return super(ListPreviewWidget, self).rowCount() def _get_image_manager(self): """ - Adds the image manager to the class dynamically + Adds the image manager to the class dynamically. """ if not hasattr(self, u'_image_manager'): self._image_manager = Registry().get(u'image_manager') @@ -161,7 +173,7 @@ class ListPreviewWidget(QtGui.QTableWidget): def _get_main_window(self): """ - Adds the main window to the class dynamically + Adds the main window to the class dynamically. """ if not hasattr(self, u'_main_window'): self._main_window = Registry().get(u'main_window') diff --git a/openlp/core/ui/slidecontroller.py b/openlp/core/ui/slidecontroller.py index 76616d152..2c24faca0 100644 --- a/openlp/core/ui/slidecontroller.py +++ b/openlp/core/ui/slidecontroller.py @@ -692,7 +692,7 @@ class SlideController(DisplayController): Replacement item following a remote edit """ if item == self.service_item: - self._processItem(item, self.preview_widget.currentRow()) + self._processItem(item, self.preview_widget.current_slide_number()) def addServiceManagerItem(self, item, slideno): """ @@ -960,9 +960,9 @@ class SlideController(DisplayController): Generate the preview when you click on a slide. if this is the Live Controller also display on the screen """ - row = self.preview_widget.currentRow() + row = self.preview_widget.current_slide_number() self.selected_row = 0 - if -1 < row < self.preview_widget.rowCount(): + if -1 < row < self.preview_widget.slide_count(): if self.service_item.is_command(): if self.is_live and not start: Registry().execute(u'%s_slide' % self.service_item.name.lower(), @@ -1033,8 +1033,8 @@ class SlideController(DisplayController): if self.service_item.is_command() and self.is_live: self.updatePreview() else: - row = self.preview_widget.currentRow() + 1 - if row == self.preview_widget.rowCount(): + row = self.preview_widget.current_slide_number() + 1 + if row == self.preview_widget.slide_count(): if wrap is None: if self.slide_limits == SlideLimits.Wrap: row = 0 @@ -1042,11 +1042,11 @@ class SlideController(DisplayController): self.serviceNext() return else: - row = self.preview_widget.rowCount() - 1 + row = self.preview_widget.slide_count() - 1 elif wrap: row = 0 else: - row = self.preview_widget.rowCount() - 1 + row = self.preview_widget.slide_count() - 1 self.preview_widget.change_slide(row) self.slideSelected() @@ -1060,10 +1060,10 @@ class SlideController(DisplayController): if self.service_item.is_command() and self.is_live: self.updatePreview() else: - row = self.preview_widget.currentRow() - 1 + row = self.preview_widget.current_slide_number() - 1 if row == -1: if self.slide_limits == SlideLimits.Wrap: - row = self.preview_widget.rowCount() - 1 + row = self.preview_widget.slide_count() - 1 elif self.is_live and self.slide_limits == SlideLimits.Next: self.keypress_queue.append(ServiceItemAction.PreviousLastSlide) self._process_queue() @@ -1087,7 +1087,7 @@ class SlideController(DisplayController): """ Start the timer loop running and store the timer id """ - if self.preview_widget.rowCount() > 1: + if self.preview_widget.slide_count() > 1: self.timer_id = self.startTimer(int(self.delay_spin_box.value()) * 1000) def on_stop_loop(self): @@ -1197,8 +1197,8 @@ class SlideController(DisplayController): """ If preview copy slide item to live controller from Preview Controller """ - row = self.preview_widget.currentRow() - if -1 < row < self.preview_widget.rowCount(): + row = self.preview_widget.current_slide_number() + if -1 < row < self.preview_widget.slide_count(): if self.service_item.from_service: self.service_manager.preview_live(self.service_item.unique_identifier, row) else: From edb0eab31d9aa0e64bdf5357b0c943d52b92aa28 Mon Sep 17 00:00:00 2001 From: Patrick Zimmermann Date: Tue, 23 Apr 2013 19:14:35 +0200 Subject: [PATCH 13/19] Remove a dev comment. Pretify a comment. --- openlp/core/ui/listpreviewwidget.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/openlp/core/ui/listpreviewwidget.py b/openlp/core/ui/listpreviewwidget.py index 636d58468..d259d43e7 100644 --- a/openlp/core/ui/listpreviewwidget.py +++ b/openlp/core/ui/listpreviewwidget.py @@ -75,7 +75,6 @@ class ListPreviewWidget(QtGui.QTableWidget): else: # Sort out image heights. for framenumber in range(len(self.service_item.get_frames())): - #self.setRowHeight(framenumber, width / ratio) height = self.viewport().width() / self.screen_ratio self.setRowHeight(framenumber, height) @@ -144,7 +143,7 @@ class ListPreviewWidget(QtGui.QTableWidget): """ if slide >= self.slide_count(): slide = self.slide_count() - 1 - #Scroll to next item if possible. + # Scroll to next item if possible. if slide + 1 < self.slide_count(): self.scrollToItem(self.item(slide + 1, 0)) self.selectRow(slide) From 84e9f6f1b1dbec12b6884f1ddbd78c93d3c25036 Mon Sep 17 00:00:00 2001 From: Patrick Zimmermann Date: Sat, 27 Apr 2013 11:54:57 +0200 Subject: [PATCH 14/19] Add test utils and move a function to there. --- tests/__init__.py | 0 .../openlp_core_lib/test_serviceitem.py | 49 ++++++------------- tests/utils/__init__.py | 0 tests/utils/constants.py | 5 ++ tests/utils/osdinteraction.py | 49 +++++++++++++++++++ 5 files changed, 70 insertions(+), 33 deletions(-) create mode 100644 tests/__init__.py create mode 100644 tests/utils/__init__.py create mode 100644 tests/utils/constants.py create mode 100644 tests/utils/osdinteraction.py diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/functional/openlp_core_lib/test_serviceitem.py b/tests/functional/openlp_core_lib/test_serviceitem.py index 26e9e7d44..cf3560d07 100644 --- a/tests/functional/openlp_core_lib/test_serviceitem.py +++ b/tests/functional/openlp_core_lib/test_serviceitem.py @@ -2,11 +2,12 @@ Package to test the openlp.core.lib package. """ import os -import cPickle from unittest import TestCase from mock import MagicMock, patch from openlp.core.lib import ItemCapabilities, ServiceItem, Registry +from tests.utils.osdinteraction import read_service_from_file +from tests.utils.constants import TEST_RESOURCES_PATH VERSE = u'The Lord said to {r}Noah{/r}: \n'\ @@ -18,8 +19,6 @@ VERSE = u'The Lord said to {r}Noah{/r}: \n'\ 'r{/pk}{o}e{/o}{pp}n{/pp} of the Lord\n' FOOTER = [u'Arky Arky (Unknown)', u'Public Domain', u'CCLI 123456'] -TEST_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), u'..', u'..', u'resources')) - class TestServiceItem(TestCase): @@ -78,7 +77,7 @@ class TestServiceItem(TestCase): service_item.name = u'test' # WHEN: adding image to a service item - test_image = os.path.join(TEST_PATH, u'church.jpg') + test_image = os.path.join(TEST_RESOURCES_PATH, u'church.jpg') service_item.add_from_image(test_image, u'Image Title') # THEN: We should get back a valid service item @@ -133,8 +132,8 @@ class TestServiceItem(TestCase): service_item.name = u'test' # WHEN: adding image to a service item - test_file = os.path.join(TEST_PATH, u'church.jpg') - service_item.add_from_command(TEST_PATH, u'church.jpg', test_file) + test_file = os.path.join(TEST_RESOURCES_PATH, u'church.jpg') + service_item.add_from_command(TEST_RESOURCES_PATH, u'church.jpg', test_file) # THEN: We should get back a valid service item assert service_item.is_valid is True, u'The new service item should be valid' @@ -151,7 +150,7 @@ class TestServiceItem(TestCase): assert len(service) == 2, u'The saved service should have two parts' assert service[u'header'][u'name'] == u'test', u'A test plugin should be returned' assert service[u'data'][0][u'title'] == u'church.jpg', u'The first title name should be "church,jpg"' - assert service[u'data'][0][u'path'] == TEST_PATH, u'The path should match the input path' + assert service[u'data'][0][u'path'] == TEST_RESOURCES_PATH, u'The path should match the input path' assert service[u'data'][0][u'image'] == test_file, u'The image should match the full path to image' # WHEN validating a service item @@ -170,13 +169,12 @@ class TestServiceItem(TestCase): """ Test the Service Item - adding a custom slide from a saved service """ - # GIVEN: A new service item and a mocked add icon function + # GIVEN: A new service item service_item = ServiceItem(None) - service_item.add_icon = MagicMock() # WHEN: adding a custom from a saved Service - line = self.convert_file_service_item(u'serviceitem_custom_1.osd') - service_item.set_from_service(line) + service = read_service_from_file(u'serviceitem_custom_1.osd') + service_item.set_from_service(service[0]) # THEN: We should get back a valid service item assert service_item.is_valid is True, u'The new service item should be valid' @@ -195,18 +193,17 @@ class TestServiceItem(TestCase): """ Test the Service Item - adding an image from a saved service """ - # GIVEN: A new service item and a mocked add icon function + # GIVEN: A new service item image_name = u'image_1.jpg' - test_file = os.path.join(TEST_PATH, image_name) + test_file = os.path.join(TEST_RESOURCES_PATH, image_name) frame_array = {u'path': test_file, u'title': image_name} service_item = ServiceItem(None) - service_item.add_icon = MagicMock() # WHEN: adding an image from a saved Service and mocked exists - line = self.convert_file_service_item(u'serviceitem_image_1.osd') + service = read_service_from_file(u'serviceitem_image_1.osd') with patch('os.path.exists'): - service_item.set_from_service(line, TEST_PATH) + service_item.set_from_service(service[0], TEST_RESOURCES_PATH) # THEN: We should get back a valid service item assert service_item.is_valid is True, u'The new service item should be valid' @@ -230,7 +227,7 @@ class TestServiceItem(TestCase): """ Test the Service Item - adding an image from a saved local service """ - # GIVEN: A new service item and a mocked add icon function + # GIVEN: A new service item image_name1 = u'image_1.jpg' image_name2 = u'image_2.jpg' test_file1 = os.path.join(u'/home/openlp', image_name1) @@ -239,12 +236,11 @@ class TestServiceItem(TestCase): frame_array2 = {u'path': test_file2, u'title': image_name2} service_item = ServiceItem(None) - service_item.add_icon = MagicMock() # WHEN: adding an image from a saved Service and mocked exists - line = self.convert_file_service_item(u'serviceitem_image_2.osd') + service = read_service_from_file(u'serviceitem_image_2.osd') with patch('os.path.exists'): - service_item.set_from_service(line) + service_item.set_from_service(service[0]) # THEN: We should get back a valid service item assert service_item.is_valid is True, u'The new service item should be valid' @@ -267,16 +263,3 @@ class TestServiceItem(TestCase): u'This service item should be able to be run in a can be made to Loop' assert service_item.is_capable(ItemCapabilities.CanAppend) is True, \ u'This service item should be able to have new items added to it' - - def convert_file_service_item(self, name): - service_file = os.path.join(TEST_PATH, name) - try: - open_file = open(service_file, u'r') - items = cPickle.load(open_file) - first_line = items[0] - except IOError: - first_line = u'' - finally: - open_file.close() - return first_line - diff --git a/tests/utils/__init__.py b/tests/utils/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/utils/constants.py b/tests/utils/constants.py new file mode 100644 index 000000000..56a7a78ca --- /dev/null +++ b/tests/utils/constants.py @@ -0,0 +1,5 @@ + +import os + +OPENLP_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), u'..', u'..')) +TEST_RESOURCES_PATH = os.path.join(OPENLP_PATH, u'tests', u'resources') \ No newline at end of file diff --git a/tests/utils/osdinteraction.py b/tests/utils/osdinteraction.py new file mode 100644 index 000000000..f275d18c2 --- /dev/null +++ b/tests/utils/osdinteraction.py @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- +# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4 + +############################################################################### +# OpenLP - Open Source Lyrics Projection # +# --------------------------------------------------------------------------- # +# Copyright (c) 2008-2013 Raoul Snyman # +# Portions copyright (c) 2008-2013 Tim Bentley, Gerald Britton, Jonathan # +# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub, # +# Meinert Jordan, Armin Köhler, Erik Lundin, 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, Patrick Zimmermann # +# --------------------------------------------------------------------------- # +# 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 # +############################################################################### +""" +The :mod:`osdinteraction` provides miscellaneous functions for interacting with +OSD files. +""" + +import os +import cPickle + +from tests.utils.constants import TEST_RESOURCES_PATH + + +def read_service_from_file(file_name): + """ + Reads an OSD file and returns the first service item found therein. + @param file_name: File name of an OSD file residing in the tests/resources folder. + @return: The service contained in the file. + """ + service_file = os.path.join(TEST_RESOURCES_PATH, file_name) + with open(service_file, u'r') as open_file: + service = cPickle.load(open_file) + return service From 154c82f5ea623d7c83731efcf1694f04712d62f4 Mon Sep 17 00:00:00 2001 From: Patrick Zimmermann Date: Sat, 27 Apr 2013 12:00:27 +0200 Subject: [PATCH 15/19] Rename a method and remove a non needed registry var. --- openlp/core/ui/listpreviewwidget.py | 12 +----------- openlp/core/ui/slidecontroller.py | 2 +- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/openlp/core/ui/listpreviewwidget.py b/openlp/core/ui/listpreviewwidget.py index d259d43e7..94385dd91 100644 --- a/openlp/core/ui/listpreviewwidget.py +++ b/openlp/core/ui/listpreviewwidget.py @@ -86,7 +86,7 @@ class ListPreviewWidget(QtGui.QTableWidget): self.screen_ratio = screen_ratio self.__recalculate_layout() - def replace_service_manager_item(self, service_item, width, slideNumber): + def replace_service_item(self, service_item, width, slideNumber): """ Replaces the current preview items with the ones in service_item. Displays the given slide. @@ -170,13 +170,3 @@ class ListPreviewWidget(QtGui.QTableWidget): image_manager = property(_get_image_manager) - def _get_main_window(self): - """ - Adds the main window to the class dynamically. - """ - if not hasattr(self, u'_main_window'): - self._main_window = Registry().get(u'main_window') - return self._main_window - - main_window = property(_get_main_window) - diff --git a/openlp/core/ui/slidecontroller.py b/openlp/core/ui/slidecontroller.py index 2c24faca0..e1b8b8183 100644 --- a/openlp/core/ui/slidecontroller.py +++ b/openlp/core/ui/slidecontroller.py @@ -784,7 +784,7 @@ class SlideController(DisplayController): if not self.service_item.is_command() and framenumber == slideno: self.service_item.bg_image_bytes = self.image_manager.get_image_bytes(frame[u'path'], ImageSource.ImagePlugin) - self.preview_widget.replace_service_manager_item(self.service_item, width, slideno) + self.preview_widget.replace_service_item(self.service_item, width, slideno) self.enableToolBar(service_item) # Pass to display for viewing. # Postpone image build, we need to do this later to avoid the theme From 46882beefeb3f76884fba7841e6eb085aa70e9ad Mon Sep 17 00:00:00 2001 From: Patrick Zimmermann Date: Sat, 27 Apr 2013 12:00:46 +0200 Subject: [PATCH 16/19] Add tests for the listpreviewwidget. --- .../openlp_core_ui/test_listpreviewwidget.py | 88 +++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 tests/interfaces/openlp_core_ui/test_listpreviewwidget.py diff --git a/tests/interfaces/openlp_core_ui/test_listpreviewwidget.py b/tests/interfaces/openlp_core_ui/test_listpreviewwidget.py new file mode 100644 index 000000000..afad91ab7 --- /dev/null +++ b/tests/interfaces/openlp_core_ui/test_listpreviewwidget.py @@ -0,0 +1,88 @@ +""" + Package to test the openlp.core.ui.listpreviewwidget. +""" + +from unittest import TestCase +from mock import MagicMock, patch + +from PyQt4 import QtGui + +from openlp.core.lib import Registry, ServiceItem +from openlp.core.ui import listpreviewwidget +from tests.utils.osdinteraction import read_service_from_file + +class TestServiceManager(TestCase): + + def setUp(self): + """ + Create the UI. + """ + Registry.create() + self.app = QtGui.QApplication([]) + self.main_window = QtGui.QMainWindow() + self.image = QtGui.QImage(1, 1, QtGui.QImage.Format_RGB32) + self.image_manager = MagicMock() + self.image_manager.get_image.return_value = self.image + Registry().register(u'image_manager', self.image_manager) + self.preview_widget = listpreviewwidget.ListPreviewWidget(self.main_window, 2) + + def tearDown(self): + """ + Delete all the C++ objects at the end so that we don't have a segfault. + """ + del self.preview_widget + del self.main_window + del self.app + + def initial_slide_count_test(self): + """ + Test the inital slide count. + """ + # GIVEN: A new ListPreviewWidget instance. + # WHEN: No SlideItem has been added yet. + # THEN: The count of items should be zero. + self.assertEqual(self.preview_widget.slide_count(), 0, + u'The slide list should be empty.') + + def initial_slide_number_test(self): + """ + Test the inital slide number. + """ + # GIVEN: A new ListPreviewWidget instance. + # WHEN: No SlideItem has been added yet. + # THEN: The number of the current item should be -1. + self.assertEqual(self.preview_widget.current_slide_number(), -1, + u'The slide number should be -1.') + + def replace_service_item_test(self): + """ + Test item counts and current number with a service item. + """ + # GIVEN: A ServiceItem with two frames. + service_item = ServiceItem(None) + service = read_service_from_file(u'serviceitem_image_2.osd') + with patch('os.path.exists'): + service_item.set_from_service(service[0]) + # WHEN: Added to the preview widget. + self.preview_widget.replace_service_item(service_item, 1, 1) + # THEN: The slide count and number should fit. + self.assertEqual(self.preview_widget.slide_count(), 2, + u'The slide count should be 2.') + self.assertEqual(self.preview_widget.current_slide_number(), 1, + u'The current slide number should be 1.') + + def change_slide_test(self): + """ + Test the change_slide method. + """ + # GIVEN: A ServiceItem with two frames content. + service_item = ServiceItem(None) + service = read_service_from_file(u'serviceitem_image_2.osd') + with patch('os.path.exists'): + service_item.set_from_service(service[0]) + # WHEN: Added to the preview widget and switched to the second frame. + self.preview_widget.replace_service_item(service_item, 1, 0) + self.preview_widget.change_slide(1) + # THEN: The current_slide_number should reflect the change. + self.assertEqual(self.preview_widget.current_slide_number(), 1, + u'The current slide number should be 1.') From c0d722e63ac8bf2b545e7def0ab6147f7574a65e Mon Sep 17 00:00:00 2001 From: Patrick Zimmermann Date: Sat, 27 Apr 2013 12:06:08 +0200 Subject: [PATCH 17/19] Name listpreviewwidget test class correctly. --- tests/interfaces/openlp_core_ui/test_listpreviewwidget.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/interfaces/openlp_core_ui/test_listpreviewwidget.py b/tests/interfaces/openlp_core_ui/test_listpreviewwidget.py index afad91ab7..8a25c0b4f 100644 --- a/tests/interfaces/openlp_core_ui/test_listpreviewwidget.py +++ b/tests/interfaces/openlp_core_ui/test_listpreviewwidget.py @@ -11,7 +11,7 @@ from openlp.core.lib import Registry, ServiceItem from openlp.core.ui import listpreviewwidget from tests.utils.osdinteraction import read_service_from_file -class TestServiceManager(TestCase): +class TestListPreviewWidget(TestCase): def setUp(self): """ From 4c2f078bf185574537564b60fac407ab90523d3c Mon Sep 17 00:00:00 2001 From: Patrick Zimmermann Date: Sat, 27 Apr 2013 22:59:56 +0200 Subject: [PATCH 18/19] Add a missing \n at EOF. Add a comment. --- openlp/core/ui/listpreviewwidget.py | 7 ++++--- tests/utils/constants.py | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/openlp/core/ui/listpreviewwidget.py b/openlp/core/ui/listpreviewwidget.py index 94385dd91..ca04c9688 100644 --- a/openlp/core/ui/listpreviewwidget.py +++ b/openlp/core/ui/listpreviewwidget.py @@ -44,9 +44,7 @@ class ListPreviewWidget(QtGui.QTableWidget): One needs to call replace_service_manager_item() to make this widget display something. """ super(QtGui.QTableWidget, self).__init__(parent) - self.service_item = ServiceItem() - self.screen_ratio = screen_ratio - + # Set up the widget. self.setColumnCount(1) self.horizontalHeader().setVisible(False) self.setColumnWidth(0, parent.width()) @@ -55,6 +53,9 @@ class ListPreviewWidget(QtGui.QTableWidget): self.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers) self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) self.setAlternatingRowColors(True) + # Initialize variables. + self.service_item = ServiceItem() + self.screen_ratio = screen_ratio def resizeEvent(self, QResizeEvent): """ diff --git a/tests/utils/constants.py b/tests/utils/constants.py index 56a7a78ca..4b28fcc83 100644 --- a/tests/utils/constants.py +++ b/tests/utils/constants.py @@ -2,4 +2,4 @@ import os OPENLP_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), u'..', u'..')) -TEST_RESOURCES_PATH = os.path.join(OPENLP_PATH, u'tests', u'resources') \ No newline at end of file +TEST_RESOURCES_PATH = os.path.join(OPENLP_PATH, u'tests', u'resources') From 4106ecd71e8dfa0b6dc838bc21d2bd3edf7c86ac Mon Sep 17 00:00:00 2001 From: Patrick Zimmermann Date: Sat, 15 Jun 2013 12:56:09 +0200 Subject: [PATCH 19/19] Remove superfluous comment. --- openlp/core/ui/slidecontroller.py | 1 - 1 file changed, 1 deletion(-) diff --git a/openlp/core/ui/slidecontroller.py b/openlp/core/ui/slidecontroller.py index 24840e74d..5cec2659c 100644 --- a/openlp/core/ui/slidecontroller.py +++ b/openlp/core/ui/slidecontroller.py @@ -567,7 +567,6 @@ class SlideController(DisplayController): self.preview_display.setFixedSize(QtCore.QSize(max_width, max_width / self.ratio)) self.preview_display.screen = { u'size': self.preview_display.geometry()} - # Make sure that the frames have the correct size. self.onControllerSizeChanged(self.controller.width()) def onControllerSizeChanged(self, width):