forked from openlp/openlp
Refactor slide controller so slide list is a separate class
bzr-revno: 2250
This commit is contained in:
commit
f3e77b39d7
173
openlp/core/ui/listpreviewwidget.py
Normal file
173
openlp/core/ui/listpreviewwidget.py
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
# -*- 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:`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
|
||||||
|
|
||||||
|
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)
|
||||||
|
# Set up the widget.
|
||||||
|
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)
|
||||||
|
# Initialize variables.
|
||||||
|
self.service_item = ServiceItem()
|
||||||
|
self.screen_ratio = screen_ratio
|
||||||
|
|
||||||
|
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 on its own.
|
||||||
|
"""
|
||||||
|
self.setColumnWidth(0, self.viewport().width())
|
||||||
|
if self.service_item:
|
||||||
|
# Sort out songs, bibles, etc.
|
||||||
|
if self.service_item.is_text():
|
||||||
|
self.resizeRowsToContents()
|
||||||
|
else:
|
||||||
|
# Sort out image heights.
|
||||||
|
for framenumber in range(len(self.service_item.get_frames())):
|
||||||
|
height = self.viewport().width() / self.screen_ratio
|
||||||
|
self.setRowHeight(framenumber, height)
|
||||||
|
|
||||||
|
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 replace_service_item(self, service_item, width, slideNumber):
|
||||||
|
"""
|
||||||
|
Replaces the current preview items with the ones in service_item.
|
||||||
|
Displays the given slide.
|
||||||
|
"""
|
||||||
|
self.service_item = service_item
|
||||||
|
self.clear()
|
||||||
|
self.setRowCount(0)
|
||||||
|
self.setColumnWidth(0, width)
|
||||||
|
row = 0
|
||||||
|
text = []
|
||||||
|
for framenumber, frame in enumerate(self.service_item.get_frames()):
|
||||||
|
self.setRowCount(self.slide_count() + 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)
|
||||||
|
if self.service_item.is_command():
|
||||||
|
label.setPixmap(QtGui.QPixmap(frame[u'image']))
|
||||||
|
else:
|
||||||
|
image = self.image_manager.get_image(frame[u'path'], ImageSource.ImagePlugin)
|
||||||
|
label.setPixmap(QtGui.QPixmap.fromImage(image))
|
||||||
|
self.setCellWidget(framenumber, 0, label)
|
||||||
|
slideHeight = width / self.screen_ratio
|
||||||
|
row += 1
|
||||||
|
text.append(unicode(row))
|
||||||
|
self.setItem(framenumber, 0, item)
|
||||||
|
if slideHeight:
|
||||||
|
self.setRowHeight(framenumber, slideHeight)
|
||||||
|
self.setVerticalHeaderLabels(text)
|
||||||
|
if self.service_item.is_text():
|
||||||
|
self.resizeRowsToContents()
|
||||||
|
self.setColumnWidth(0, self.viewport().width())
|
||||||
|
self.setFocus()
|
||||||
|
self.change_slide(slideNumber)
|
||||||
|
|
||||||
|
def change_slide(self, slide):
|
||||||
|
"""
|
||||||
|
Switches to the given row.
|
||||||
|
"""
|
||||||
|
if slide >= self.slide_count():
|
||||||
|
slide = self.slide_count() - 1
|
||||||
|
# Scroll to next item if possible.
|
||||||
|
if slide + 1 < self.slide_count():
|
||||||
|
self.scrollToItem(self.item(slide + 1, 0))
|
||||||
|
self.selectRow(slide)
|
||||||
|
|
||||||
|
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 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.
|
||||||
|
"""
|
||||||
|
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)
|
||||||
|
|
@ -1369,7 +1369,7 @@ class ServiceManager(QtGui.QWidget, ServiceManagerDialog):
|
|||||||
self.preview_controller.addServiceManagerItem(self.service_items[item][u'service_item'], 0)
|
self.preview_controller.addServiceManagerItem(self.service_items[item][u'service_item'], 0)
|
||||||
next_item = self.service_manager_list.topLevelItem(item)
|
next_item = self.service_manager_list.topLevelItem(item)
|
||||||
self.service_manager_list.setCurrentItem(next_item)
|
self.service_manager_list.setCurrentItem(next_item)
|
||||||
self.live_controller.preview_list_widget.setFocus()
|
self.live_controller.preview_widget.setFocus()
|
||||||
else:
|
else:
|
||||||
critical_error_message_box(translate('OpenLP.ServiceManager', 'Missing Display Handler'),
|
critical_error_message_box(translate('OpenLP.ServiceManager', 'Missing Display Handler'),
|
||||||
translate('OpenLP.ServiceManager',
|
translate('OpenLP.ServiceManager',
|
||||||
|
@ -41,6 +41,7 @@ from openlp.core.lib import OpenLPToolbar, ItemCapabilities, ServiceItem, ImageS
|
|||||||
from openlp.core.ui import HideMode, MainDisplay, Display, DisplayControllerType
|
from openlp.core.ui import HideMode, MainDisplay, Display, DisplayControllerType
|
||||||
from openlp.core.lib.ui import create_action
|
from openlp.core.lib.ui import create_action
|
||||||
from openlp.core.utils.actions import ActionList, CategoryOrder
|
from openlp.core.utils.actions import ActionList, CategoryOrder
|
||||||
|
from openlp.core.ui.listpreviewwidget import ListPreviewWidget
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -159,18 +160,8 @@ class SlideController(DisplayController):
|
|||||||
self.controller_layout.setSpacing(0)
|
self.controller_layout.setSpacing(0)
|
||||||
self.controller_layout.setMargin(0)
|
self.controller_layout.setMargin(0)
|
||||||
# Controller list view
|
# Controller list view
|
||||||
self.preview_list_widget = QtGui.QTableWidget(self.controller)
|
self.preview_widget = ListPreviewWidget(self, self.ratio)
|
||||||
self.preview_list_widget.setColumnCount(1)
|
self.controller_layout.addWidget(self.preview_widget)
|
||||||
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)
|
|
||||||
# Build the full toolbar
|
# Build the full toolbar
|
||||||
self.toolbar = OpenLPToolbar(self)
|
self.toolbar = OpenLPToolbar(self)
|
||||||
size_toolbar_policy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
|
size_toolbar_policy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
|
||||||
@ -352,7 +343,7 @@ class SlideController(DisplayController):
|
|||||||
{u'key': u'O', u'configurable': True, u'text': translate('OpenLP.SlideController', 'Go to "Other"')}
|
{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)])
|
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'),
|
u'shortcutAction_%s' % s[u'key'], text=s.get(u'text'),
|
||||||
can_shortcuts=True,
|
can_shortcuts=True,
|
||||||
context=QtCore.Qt.WidgetWithChildrenShortcut,
|
context=QtCore.Qt.WidgetWithChildrenShortcut,
|
||||||
@ -360,7 +351,7 @@ class SlideController(DisplayController):
|
|||||||
triggers=self._slideShortcutActivated) for s in shortcuts])
|
triggers=self._slideShortcutActivated) for s in shortcuts])
|
||||||
self.shortcutTimer.timeout.connect(self._slideShortcutActivated)
|
self.shortcutTimer.timeout.connect(self._slideShortcutActivated)
|
||||||
# Signals
|
# Signals
|
||||||
self.preview_list_widget.clicked.connect(self.onSlideSelected)
|
self.preview_widget.clicked.connect(self.onSlideSelected)
|
||||||
if self.is_live:
|
if self.is_live:
|
||||||
# Need to use event as called across threads and UI is updated
|
# Need to use event as called across threads and UI is updated
|
||||||
QtCore.QObject.connect(self, QtCore.SIGNAL(u'slidecontroller_toggle_display'), self.toggle_display)
|
QtCore.QObject.connect(self, QtCore.SIGNAL(u'slidecontroller_toggle_display'), self.toggle_display)
|
||||||
@ -368,13 +359,13 @@ class SlideController(DisplayController):
|
|||||||
self.toolbar.set_widget_visible(self.loop_list, False)
|
self.toolbar.set_widget_visible(self.loop_list, False)
|
||||||
self.toolbar.set_widget_visible(self.wide_menu, False)
|
self.toolbar.set_widget_visible(self.wide_menu, False)
|
||||||
else:
|
else:
|
||||||
self.preview_list_widget.doubleClicked.connect(self.onGoLiveClick)
|
self.preview_widget.doubleClicked.connect(self.onGoLiveClick)
|
||||||
self.toolbar.set_widget_visible([u'editSong'], False)
|
self.toolbar.set_widget_visible([u'editSong'], False)
|
||||||
if self.is_live:
|
if self.is_live:
|
||||||
self.setLiveHotkeys(self)
|
self.setLiveHotkeys(self)
|
||||||
self.__addActionsToWidget(self.preview_list_widget)
|
self.__addActionsToWidget(self.controller)
|
||||||
else:
|
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_stop_loop' % self.type_prefix, self.on_stop_loop)
|
||||||
Registry().register_function(u'slidecontroller_%s_change' % self.type_prefix, self.on_slide_change)
|
Registry().register_function(u'slidecontroller_%s_change' % self.type_prefix, self.on_slide_change)
|
||||||
Registry().register_function(u'slidecontroller_%s_blank' % self.type_prefix, self.on_slide_blank)
|
Registry().register_function(u'slidecontroller_%s_blank' % self.type_prefix, self.on_slide_blank)
|
||||||
@ -433,7 +424,7 @@ class SlideController(DisplayController):
|
|||||||
if len(matches) == 1:
|
if len(matches) == 1:
|
||||||
self.shortcutTimer.stop()
|
self.shortcutTimer.stop()
|
||||||
self.current_shortcut = u''
|
self.current_shortcut = u''
|
||||||
self.__checkUpdateSelectedSlide(self.slideList[matches[0]])
|
self.preview_widget.change_slide(self.slideList[matches[0]])
|
||||||
self.slideSelected()
|
self.slideSelected()
|
||||||
elif sender_name != u'shortcutTimer':
|
elif sender_name != u'shortcutTimer':
|
||||||
# Start the time as we did not have any match.
|
# Start the time as we did not have any match.
|
||||||
@ -443,7 +434,7 @@ class SlideController(DisplayController):
|
|||||||
if self.current_shortcut in keys:
|
if self.current_shortcut in keys:
|
||||||
# We had more than one match for example "V1" and "V10", but
|
# We had more than one match for example "V1" and "V10", but
|
||||||
# "V1" was the slide we wanted to go.
|
# "V1" was the slide we wanted to go.
|
||||||
self.__checkUpdateSelectedSlide(self.slideList[self.current_shortcut])
|
self.preview_widget.change_slide(self.slideList[self.current_shortcut])
|
||||||
self.slideSelected()
|
self.slideSelected()
|
||||||
# Reset the shortcut.
|
# Reset the shortcut.
|
||||||
self.current_shortcut = u''
|
self.current_shortcut = u''
|
||||||
@ -538,6 +529,7 @@ class SlideController(DisplayController):
|
|||||||
self.ratio = 1
|
self.ratio = 1
|
||||||
self.media_controller.setup_display(self.display, False)
|
self.media_controller.setup_display(self.display, False)
|
||||||
self.preview_size_changed()
|
self.preview_size_changed()
|
||||||
|
self.preview_widget.screen_size_changed(self.ratio)
|
||||||
self.preview_display.setup()
|
self.preview_display.setup()
|
||||||
service_item = ServiceItem()
|
service_item = ServiceItem()
|
||||||
self.preview_display.web_view.setHtml(build_html(service_item, self.preview_display.screen, None, self.is_live,
|
self.preview_display.web_view.setHtml(build_html(service_item, self.preview_display.screen, None, self.is_live,
|
||||||
@ -575,17 +567,6 @@ class SlideController(DisplayController):
|
|||||||
self.preview_display.setFixedSize(QtCore.QSize(max_width, max_width / self.ratio))
|
self.preview_display.setFixedSize(QtCore.QSize(max_width, max_width / self.ratio))
|
||||||
self.preview_display.screen = {
|
self.preview_display.screen = {
|
||||||
u'size': self.preview_display.geometry()}
|
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)
|
|
||||||
self.onControllerSizeChanged(self.controller.width())
|
self.onControllerSizeChanged(self.controller.width())
|
||||||
|
|
||||||
def onControllerSizeChanged(self, width):
|
def onControllerSizeChanged(self, width):
|
||||||
@ -710,7 +691,7 @@ class SlideController(DisplayController):
|
|||||||
Replacement item following a remote edit
|
Replacement item following a remote edit
|
||||||
"""
|
"""
|
||||||
if item == self.service_item:
|
if item == self.service_item:
|
||||||
self._process_item(item, self.preview_list_widget.currentRow())
|
self._process_item(item, self.preview_widget.current_slide_number())
|
||||||
|
|
||||||
def addServiceManagerItem(self, item, slideno):
|
def addServiceManagerItem(self, item, slideno):
|
||||||
"""
|
"""
|
||||||
@ -726,7 +707,7 @@ class SlideController(DisplayController):
|
|||||||
slidenum = 0
|
slidenum = 0
|
||||||
# If service item is the same as the current one, only change slide
|
# If service item is the same as the current one, only change slide
|
||||||
if slideno >= 0 and item == self.service_item:
|
if slideno >= 0 and item == self.service_item:
|
||||||
self.__checkUpdateSelectedSlide(slidenum)
|
self.preview_widget.change_slide(slidenum)
|
||||||
self.slideSelected()
|
self.slideSelected()
|
||||||
else:
|
else:
|
||||||
self._process_item(item, slidenum)
|
self._process_item(item, slidenum)
|
||||||
@ -753,10 +734,6 @@ class SlideController(DisplayController):
|
|||||||
self._resetBlank()
|
self._resetBlank()
|
||||||
Registry().execute(u'%s_start' % service_item.name.lower(), [service_item, self.is_live, self.hide_mode(), slideno])
|
Registry().execute(u'%s_start' % service_item.name.lower(), [service_item, self.is_live, self.hide_mode(), slideno])
|
||||||
self.slideList = {}
|
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:
|
if self.is_live:
|
||||||
self.song_menu.menu().clear()
|
self.song_menu.menu().clear()
|
||||||
self.display.audio_player.reset()
|
self.display.audio_player.reset()
|
||||||
@ -781,9 +758,8 @@ class SlideController(DisplayController):
|
|||||||
self.setAudioItemsVisibility(True)
|
self.setAudioItemsVisibility(True)
|
||||||
row = 0
|
row = 0
|
||||||
text = []
|
text = []
|
||||||
|
width = self.main_window.controlSplitter.sizes()[self.split]
|
||||||
for framenumber, frame in enumerate(self.service_item.get_frames()):
|
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
|
slideHeight = 0
|
||||||
if self.service_item.is_text():
|
if self.service_item.is_text():
|
||||||
if frame[u'verseTag']:
|
if frame[u'verseTag']:
|
||||||
@ -799,36 +775,15 @@ class SlideController(DisplayController):
|
|||||||
else:
|
else:
|
||||||
row += 1
|
row += 1
|
||||||
self.slideList[unicode(row)] = row - 1
|
self.slideList[unicode(row)] = row - 1
|
||||||
item.setText(frame[u'text'])
|
|
||||||
else:
|
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)
|
slideHeight = width * (1 / self.ratio)
|
||||||
row += 1
|
row += 1
|
||||||
self.slideList[unicode(row)] = row - 1
|
self.slideList[unicode(row)] = row - 1
|
||||||
text.append(unicode(row))
|
# If current slide set background to image
|
||||||
self.preview_list_widget.setItem(framenumber, 0, item)
|
if not self.service_item.is_command() and framenumber == slideno:
|
||||||
if slideHeight:
|
self.service_item.bg_image_bytes = self.image_manager.get_image_bytes(frame[u'path'],
|
||||||
self.preview_list_widget.setRowHeight(framenumber, slideHeight)
|
ImageSource.ImagePlugin)
|
||||||
self.preview_list_widget.setVerticalHeaderLabels(text)
|
self.preview_widget.replace_service_item(self.service_item, width, slideno)
|
||||||
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.enable_tool_bar(service_item)
|
self.enable_tool_bar(service_item)
|
||||||
# Pass to display for viewing.
|
# Pass to display for viewing.
|
||||||
# Postpone image build, we need to do this later to avoid the theme
|
# Postpone image build, we need to do this later to avoid the theme
|
||||||
@ -838,7 +793,6 @@ class SlideController(DisplayController):
|
|||||||
if service_item.is_media():
|
if service_item.is_media():
|
||||||
self.onMediaStart(service_item)
|
self.onMediaStart(service_item)
|
||||||
self.slideSelected(True)
|
self.slideSelected(True)
|
||||||
self.preview_list_widget.setFocus()
|
|
||||||
if old_item:
|
if old_item:
|
||||||
# Close the old item after the new one is opened
|
# Close the old item after the new one is opened
|
||||||
# This avoids the service theme/desktop flashing on screen
|
# This avoids the service theme/desktop flashing on screen
|
||||||
@ -850,16 +804,6 @@ class SlideController(DisplayController):
|
|||||||
self.onMediaClose()
|
self.onMediaClose()
|
||||||
Registry().execute(u'slidecontroller_%s_started' % self.type_prefix, [service_item])
|
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
|
# Screen event methods
|
||||||
def on_slide_selected_index(self, message):
|
def on_slide_selected_index(self, message):
|
||||||
"""
|
"""
|
||||||
@ -872,7 +816,7 @@ class SlideController(DisplayController):
|
|||||||
Registry().execute(u'%s_slide' % self.service_item.name.lower(), [self.service_item, self.is_live, index])
|
Registry().execute(u'%s_slide' % self.service_item.name.lower(), [self.service_item, self.is_live, index])
|
||||||
self.updatePreview()
|
self.updatePreview()
|
||||||
else:
|
else:
|
||||||
self.__checkUpdateSelectedSlide(index)
|
self.preview_widget.change_slide(index)
|
||||||
self.slideSelected()
|
self.slideSelected()
|
||||||
|
|
||||||
def mainDisplaySetBackground(self):
|
def mainDisplaySetBackground(self):
|
||||||
@ -1015,9 +959,9 @@ class SlideController(DisplayController):
|
|||||||
Generate the preview when you click on a slide.
|
Generate the preview when you click on a slide.
|
||||||
if this is the Live Controller also display on the screen
|
if this is the Live Controller also display on the screen
|
||||||
"""
|
"""
|
||||||
row = self.preview_list_widget.currentRow()
|
row = self.preview_widget.current_slide_number()
|
||||||
self.selected_row = 0
|
self.selected_row = 0
|
||||||
if -1 < row < self.preview_list_widget.rowCount():
|
if -1 < row < self.preview_widget.slide_count():
|
||||||
if self.service_item.is_command():
|
if self.service_item.is_command():
|
||||||
if self.is_live and not start:
|
if self.is_live and not start:
|
||||||
Registry().execute(u'%s_slide' % self.service_item.name.lower(),
|
Registry().execute(u'%s_slide' % self.service_item.name.lower(),
|
||||||
@ -1035,7 +979,7 @@ class SlideController(DisplayController):
|
|||||||
self.service_item.bg_image_bytes = None
|
self.service_item.bg_image_bytes = None
|
||||||
self.updatePreview()
|
self.updatePreview()
|
||||||
self.selected_row = row
|
self.selected_row = row
|
||||||
self.__checkUpdateSelectedSlide(row)
|
self.preview_widget.change_slide(row)
|
||||||
Registry().execute(u'slidecontroller_%s_changed' % self.type_prefix, row)
|
Registry().execute(u'slidecontroller_%s_changed' % self.type_prefix, row)
|
||||||
self.display.setFocus()
|
self.display.setFocus()
|
||||||
|
|
||||||
@ -1043,7 +987,7 @@ class SlideController(DisplayController):
|
|||||||
"""
|
"""
|
||||||
The slide has been changed. Update the slidecontroller accordingly
|
The slide has been changed. Update the slidecontroller accordingly
|
||||||
"""
|
"""
|
||||||
self.__checkUpdateSelectedSlide(row)
|
self.preview_widget.change_slide(row)
|
||||||
self.updatePreview()
|
self.updatePreview()
|
||||||
Registry().execute(u'slidecontroller_%s_changed' % self.type_prefix, row)
|
Registry().execute(u'slidecontroller_%s_changed' % self.type_prefix, row)
|
||||||
|
|
||||||
@ -1089,8 +1033,8 @@ class SlideController(DisplayController):
|
|||||||
if self.service_item.is_command() and self.is_live:
|
if self.service_item.is_command() and self.is_live:
|
||||||
self.updatePreview()
|
self.updatePreview()
|
||||||
else:
|
else:
|
||||||
row = self.preview_list_widget.currentRow() + 1
|
row = self.preview_widget.current_slide_number() + 1
|
||||||
if row == self.preview_list_widget.rowCount():
|
if row == self.preview_widget.slide_count():
|
||||||
if wrap is None:
|
if wrap is None:
|
||||||
if self.slide_limits == SlideLimits.Wrap:
|
if self.slide_limits == SlideLimits.Wrap:
|
||||||
row = 0
|
row = 0
|
||||||
@ -1098,12 +1042,12 @@ class SlideController(DisplayController):
|
|||||||
self.serviceNext()
|
self.serviceNext()
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
row = self.preview_list_widget.rowCount() - 1
|
row = self.preview_widget.slide_count() - 1
|
||||||
elif wrap:
|
elif wrap:
|
||||||
row = 0
|
row = 0
|
||||||
else:
|
else:
|
||||||
row = self.preview_list_widget.rowCount() - 1
|
row = self.preview_widget.slide_count() - 1
|
||||||
self.__checkUpdateSelectedSlide(row)
|
self.preview_widget.change_slide(row)
|
||||||
self.slideSelected()
|
self.slideSelected()
|
||||||
|
|
||||||
def on_slide_selected_previous(self):
|
def on_slide_selected_previous(self):
|
||||||
@ -1116,27 +1060,19 @@ class SlideController(DisplayController):
|
|||||||
if self.service_item.is_command() and self.is_live:
|
if self.service_item.is_command() and self.is_live:
|
||||||
self.updatePreview()
|
self.updatePreview()
|
||||||
else:
|
else:
|
||||||
row = self.preview_list_widget.currentRow() - 1
|
row = self.preview_widget.current_slide_number() - 1
|
||||||
if row == -1:
|
if row == -1:
|
||||||
if self.slide_limits == SlideLimits.Wrap:
|
if self.slide_limits == SlideLimits.Wrap:
|
||||||
row = self.preview_list_widget.rowCount() - 1
|
row = self.preview_widget.slide_count() - 1
|
||||||
elif self.is_live and self.slide_limits == SlideLimits.Next:
|
elif self.is_live and self.slide_limits == SlideLimits.Next:
|
||||||
self.keypress_queue.append(ServiceItemAction.PreviousLastSlide)
|
self.keypress_queue.append(ServiceItemAction.PreviousLastSlide)
|
||||||
self._process_queue()
|
self._process_queue()
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
row = 0
|
row = 0
|
||||||
self.__checkUpdateSelectedSlide(row)
|
self.preview_widget.change_slide(row)
|
||||||
self.slideSelected()
|
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):
|
def onToggleLoop(self):
|
||||||
"""
|
"""
|
||||||
Toggles the loop state.
|
Toggles the loop state.
|
||||||
@ -1151,7 +1087,7 @@ class SlideController(DisplayController):
|
|||||||
"""
|
"""
|
||||||
Start the timer loop running and store the timer id
|
Start the timer loop running and store the timer id
|
||||||
"""
|
"""
|
||||||
if self.preview_list_widget.rowCount() > 1:
|
if self.preview_widget.slide_count() > 1:
|
||||||
self.timer_id = self.startTimer(int(self.delay_spin_box.value()) * 1000)
|
self.timer_id = self.startTimer(int(self.delay_spin_box.value()) * 1000)
|
||||||
|
|
||||||
def on_stop_loop(self):
|
def on_stop_loop(self):
|
||||||
@ -1261,8 +1197,8 @@ class SlideController(DisplayController):
|
|||||||
"""
|
"""
|
||||||
If preview copy slide item to live controller from Preview Controller
|
If preview copy slide item to live controller from Preview Controller
|
||||||
"""
|
"""
|
||||||
row = self.preview_list_widget.currentRow()
|
row = self.preview_widget.current_slide_number()
|
||||||
if -1 < row < self.preview_list_widget.rowCount():
|
if -1 < row < self.preview_widget.slide_count():
|
||||||
if self.service_item.from_service:
|
if self.service_item.from_service:
|
||||||
self.service_manager.preview_live(self.service_item.unique_identifier, row)
|
self.service_manager.preview_live(self.service_item.unique_identifier, row)
|
||||||
else:
|
else:
|
||||||
|
0
tests/__init__.py
Normal file
0
tests/__init__.py
Normal file
@ -2,11 +2,12 @@
|
|||||||
Package to test the openlp.core.lib package.
|
Package to test the openlp.core.lib package.
|
||||||
"""
|
"""
|
||||||
import os
|
import os
|
||||||
import cPickle
|
|
||||||
from unittest import TestCase
|
from unittest import TestCase
|
||||||
from mock import MagicMock, patch
|
from mock import MagicMock, patch
|
||||||
|
|
||||||
from openlp.core.lib import ItemCapabilities, ServiceItem, Registry
|
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'\
|
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'
|
'r{/pk}{o}e{/o}{pp}n{/pp} of the Lord\n'
|
||||||
FOOTER = [u'Arky Arky (Unknown)', u'Public Domain', u'CCLI 123456']
|
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):
|
class TestServiceItem(TestCase):
|
||||||
|
|
||||||
@ -78,7 +77,7 @@ class TestServiceItem(TestCase):
|
|||||||
service_item.name = u'test'
|
service_item.name = u'test'
|
||||||
|
|
||||||
# WHEN: adding image to a service item
|
# 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')
|
service_item.add_from_image(test_image, u'Image Title')
|
||||||
|
|
||||||
# THEN: We should get back a valid service item
|
# THEN: We should get back a valid service item
|
||||||
@ -133,8 +132,8 @@ class TestServiceItem(TestCase):
|
|||||||
service_item.name = u'test'
|
service_item.name = u'test'
|
||||||
|
|
||||||
# WHEN: adding image to a service item
|
# WHEN: adding image to a service item
|
||||||
test_file = os.path.join(TEST_PATH, u'church.jpg')
|
test_file = os.path.join(TEST_RESOURCES_PATH, u'church.jpg')
|
||||||
service_item.add_from_command(TEST_PATH, u'church.jpg', test_file)
|
service_item.add_from_command(TEST_RESOURCES_PATH, u'church.jpg', test_file)
|
||||||
|
|
||||||
# THEN: We should get back a valid service item
|
# THEN: We should get back a valid service item
|
||||||
assert service_item.is_valid is True, u'The new service item should be valid'
|
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 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'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'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'
|
assert service[u'data'][0][u'image'] == test_file, u'The image should match the full path to image'
|
||||||
|
|
||||||
# WHEN validating a service item
|
# WHEN validating a service item
|
||||||
@ -170,13 +169,12 @@ class TestServiceItem(TestCase):
|
|||||||
"""
|
"""
|
||||||
Test the Service Item - adding a custom slide from a saved service
|
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 = ServiceItem(None)
|
||||||
service_item.add_icon = MagicMock()
|
|
||||||
|
|
||||||
# WHEN: adding a custom from a saved Service
|
# WHEN: adding a custom from a saved Service
|
||||||
line = self.convert_file_service_item(u'serviceitem_custom_1.osd')
|
service = read_service_from_file(u'serviceitem_custom_1.osd')
|
||||||
service_item.set_from_service(line)
|
service_item.set_from_service(service[0])
|
||||||
|
|
||||||
# THEN: We should get back a valid service item
|
# THEN: We should get back a valid service item
|
||||||
assert service_item.is_valid is True, u'The new service item should be valid'
|
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
|
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'
|
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}
|
frame_array = {u'path': test_file, u'title': image_name}
|
||||||
|
|
||||||
service_item = ServiceItem(None)
|
service_item = ServiceItem(None)
|
||||||
service_item.add_icon = MagicMock()
|
|
||||||
|
|
||||||
# WHEN: adding an image from a saved Service and mocked exists
|
# 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'):
|
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
|
# THEN: We should get back a valid service item
|
||||||
assert service_item.is_valid is True, u'The new service item should be valid'
|
assert service_item.is_valid is True, u'The new service item should be valid'
|
||||||
@ -229,7 +226,7 @@ class TestServiceItem(TestCase):
|
|||||||
"""
|
"""
|
||||||
Test the Service Item - adding an image from a saved local service
|
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_name1 = u'image_1.jpg'
|
||||||
image_name2 = u'image_2.jpg'
|
image_name2 = u'image_2.jpg'
|
||||||
test_file1 = os.path.join(u'/home/openlp', image_name1)
|
test_file1 = os.path.join(u'/home/openlp', image_name1)
|
||||||
@ -238,12 +235,11 @@ class TestServiceItem(TestCase):
|
|||||||
frame_array2 = {u'path': test_file2, u'title': image_name2}
|
frame_array2 = {u'path': test_file2, u'title': image_name2}
|
||||||
|
|
||||||
service_item = ServiceItem(None)
|
service_item = ServiceItem(None)
|
||||||
service_item.add_icon = MagicMock()
|
|
||||||
|
|
||||||
# WHEN: adding an image from a saved Service and mocked exists
|
# 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'):
|
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
|
# THEN: We should get back a valid service item
|
||||||
assert service_item.is_valid is True, u'The new service item should be valid'
|
assert service_item.is_valid is True, u'The new service item should be valid'
|
||||||
@ -286,16 +282,3 @@ class TestServiceItem(TestCase):
|
|||||||
assert service_item.title is None, u'The title should be set to a value'
|
assert service_item.title is None, u'The title should be set to a value'
|
||||||
assert service_item.is_capable(ItemCapabilities.HasDetailedTitleDisplay) is False, \
|
assert service_item.is_capable(ItemCapabilities.HasDetailedTitleDisplay) is False, \
|
||||||
u'The Capability should have been removed'
|
u'The Capability should have been removed'
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
|
88
tests/interfaces/openlp_core_ui/test_listpreviewwidget.py
Normal file
88
tests/interfaces/openlp_core_ui/test_listpreviewwidget.py
Normal file
@ -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 TestListPreviewWidget(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.')
|
0
tests/utils/__init__.py
Normal file
0
tests/utils/__init__.py
Normal file
5
tests/utils/constants.py
Normal file
5
tests/utils/constants.py
Normal file
@ -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')
|
49
tests/utils/osdinteraction.py
Normal file
49
tests/utils/osdinteraction.py
Normal file
@ -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
|
Loading…
Reference in New Issue
Block a user