r2154 + fixed trunk

This commit is contained in:
Andreas Preikschat 2013-01-21 20:47:53 +01:00
commit d0c9c35deb
10 changed files with 292 additions and 14 deletions

View File

@ -23,3 +23,5 @@ resources/windows/warnOpenLP.txt
openlp.cfg
.idea
openlp.pro
.kdev4
tests.kdev4

View File

@ -183,6 +183,9 @@ class ServiceItem(object):
self.background_audio = []
self.theme_overwritten = False
self.temporary_edit = False
self.auto_play_slides_once = False
self.auto_play_slides_loop = False
self.timed_slide_interval = 0
self.will_auto_start = False
self.has_original_files = True
self._new_item()
@ -344,6 +347,9 @@ class ServiceItem(object):
u'search': self.search_string,
u'data': self.data_string,
u'xml_version': self.xml_version,
u'auto_play_slides_once': self.auto_play_slides_once,
u'auto_play_slides_loop': self.auto_play_slides_loop,
u'timed_slide_interval': self.timed_slide_interval,
u'start_time': self.start_time,
u'end_time': self.end_time,
u'media_length': self.media_length,
@ -398,6 +404,9 @@ class ServiceItem(object):
self.start_time = header.get(u'start_time', 0)
self.end_time = header.get(u'end_time', 0)
self.media_length = header.get(u'media_length', 0)
self.auto_play_slides_once = header.get(u'auto_play_slides_once', False)
self.auto_play_slides_loop = header.get(u'auto_play_slides_loop', False)
self.timed_slide_interval = header.get(u'timed_slide_interval', 0)
self.will_auto_start = header.get(u'will_auto_start', False)
self.has_original_files = True
if u'background_audio' in header:
@ -427,7 +436,6 @@ class ServiceItem(object):
self.add_from_command(path, text_image[u'title'], text_image[u'image'])
else:
self.add_from_command(text_image[u'path'], text_image[u'title'], text_image[u'image'])
self._new_item()
def get_display_title(self):

View File

@ -257,6 +257,20 @@ class ServiceManager(QtGui.QWidget):
text=translate('OpenLP.ServiceManager', 'Create New &Custom Slide'),
icon=u':/general/general_edit.png', triggers=self.create_custom)
self.menu.addSeparator()
# Add AutoPlay menu actions
self.autoPlaySlidesGroup = QtGui.QMenu(translate('OpenLP.ServiceManager', '&Auto play slides'))
self.menu.addMenu(self.autoPlaySlidesGroup)
self.autoPlaySlidesLoop = create_widget_action(self.autoPlaySlidesGroup,
text=translate('OpenLP.ServiceManager', 'Auto play slides &Loop'),
checked=False, triggers=self.toggleAutoPlaySlidesLoop)
self.autoPlaySlidesOnce = create_widget_action(self.autoPlaySlidesGroup,
text=translate('OpenLP.ServiceManager', 'Auto play slides &Once'),
checked=False, triggers=self.toggleAutoPlaySlidesOnce)
self.autoPlaySlidesGroup.addSeparator()
self.timedSlideInterval = create_widget_action(self.autoPlaySlidesGroup,
text=translate('OpenLP.ServiceManager', '&Delay between slides'),
checked=False, triggers=self.onTimedSlideInterval)
self.menu.addSeparator()
self.previewAction = create_widget_action(self.menu, text=translate('OpenLP.ServiceManager', 'Show &Preview'),
icon=u':/general/general_preview.png', triggers=self.makePreview)
# Add already existing make live action to the menu.
@ -762,6 +776,22 @@ class ServiceManager(QtGui.QWidget):
self.maintainAction.setVisible(True)
if item.parent() is None:
self.notesAction.setVisible(True)
if serviceItem[u'service_item'].is_capable(ItemCapabilities.CanLoop) and \
len(serviceItem[u'service_item'].get_frames()) > 1:
self.autoPlaySlidesGroup.menuAction().setVisible(True)
self.autoPlaySlidesOnce.setChecked(serviceItem[u'service_item'].auto_play_slides_once)
self.autoPlaySlidesLoop.setChecked(serviceItem[u'service_item'].auto_play_slides_loop)
self.timedSlideInterval.setChecked(serviceItem[u'service_item'].timed_slide_interval > 0)
if serviceItem[u'service_item'].timed_slide_interval > 0:
delay_suffix = u' '
delay_suffix += unicode(serviceItem[u'service_item'].timed_slide_interval)
delay_suffix += u' s'
else:
delay_suffix = u' ...'
self.timedSlideInterval.setText(translate('OpenLP.ServiceManager', '&Delay between slides') + delay_suffix)
# TODO for future: make group explains itself more visually
else:
self.autoPlaySlidesGroup.menuAction().setVisible(False)
if serviceItem[u'service_item'].is_capable(ItemCapabilities.HasVariableStartTime):
self.timeAction.setVisible(True)
if serviceItem[u'service_item'].is_capable(ItemCapabilities.CanAutoStartForLive):
@ -807,6 +837,59 @@ class ServiceManager(QtGui.QWidget):
if self.startTimeForm.exec_():
self.repaintServiceList(item, -1)
def toggleAutoPlaySlidesOnce(self):
"""
Toggle Auto play slide once.
Inverts auto play once option for the item
"""
item = self.findServiceItem()[0]
service_item = self.serviceItems[item][u'service_item']
service_item.auto_play_slides_once = not service_item.auto_play_slides_once
if service_item.auto_play_slides_once:
service_item.auto_play_slides_loop = False
self.autoPlaySlidesLoop.setChecked(False)
if service_item.auto_play_slides_once and service_item.timed_slide_interval == 0:
service_item.timed_slide_interval = Settings().value(u'loop delay')
self.setModified()
def toggleAutoPlaySlidesLoop(self):
"""
Toggle Auto play slide loop.
"""
item = self.findServiceItem()[0]
service_item = self.serviceItems[item][u'service_item']
service_item.auto_play_slides_loop = not service_item.auto_play_slides_loop
if service_item.auto_play_slides_loop:
service_item.auto_play_slides_once = False
self.autoPlaySlidesOnce.setChecked(False)
if service_item.auto_play_slides_loop and service_item.timed_slide_interval == 0:
service_item.timed_slide_interval = Settings().value(u'loop delay')
self.setModified()
def onTimedSlideInterval(self):
"""
on set times slide interval.
Shows input dialog for enter interval in seconds for delay
"""
item = self.findServiceItem()[0]
service_item = self.serviceItems[item][u'service_item']
if service_item.timed_slide_interval == 0:
timed_slide_interval = Settings().value(u'loop delay')
else:
timed_slide_interval = service_item.timed_slide_interval
timed_slide_interval, ok = QtGui.QInputDialog.getInteger(self, translate('OpenLP.ServiceManager',
'Input delay'), translate('OpenLP.ServiceManager', 'Delay between slides in seconds.'),
timed_slide_interval, 0, 180, 1)
if ok:
service_item.timed_slide_interval = timed_slide_interval
if service_item.timed_slide_interval <> 0 and not service_item.auto_play_slides_loop\
and not service_item.auto_play_slides_once:
service_item.auto_play_slides_loop = True
elif service_item.timed_slide_interval == 0:
service_item.auto_play_slides_loop = False
service_item.auto_play_slides_once = False
self.setModified()
def onAutoStart(self):
"""
Toggles to Auto Start Setting.
@ -1287,6 +1370,8 @@ class ServiceManager(QtGui.QWidget):
if self.serviceItems and item < len(self.serviceItems) and \
self.serviceItems[item][u'service_item'].is_capable(ItemCapabilities.CanPreview):
self.mainwindow.previewController.addServiceManagerItem(self.serviceItems[item][u'service_item'], 0)
next_item = self.serviceManagerList.topLevelItem(item)
self.serviceManagerList.setCurrentItem(next_item)
self.mainwindow.liveController.previewListWidget.setFocus()
else:
critical_error_message_box(translate('OpenLP.ServiceManager', 'Missing Display Handler'),

View File

@ -689,6 +689,14 @@ class SlideController(DisplayController):
self.slideSelected()
else:
self._processItem(item, slidenum)
if self.isLive and item.auto_play_slides_loop and item.timed_slide_interval > 0:
self.playSlidesLoop.setChecked(item.auto_play_slides_loop)
self.delaySpinBox.setValue(int(item.timed_slide_interval))
self.onPlaySlidesLoop()
elif self.isLive and item.auto_play_slides_once and item.timed_slide_interval > 0:
self.playSlidesOnce.setChecked(item.auto_play_slides_once)
self.delaySpinBox.setValue(int(item.timed_slide_interval))
self.onPlaySlidesOnce()
def _processItem(self, serviceItem, slideno):
"""
@ -877,6 +885,7 @@ class SlideController(DisplayController):
Settings().remove(self.parent().generalSettingsSection + u'/screen blank')
self.blankPlugin()
self.updatePreview()
self.onToggleLoop()
def onThemeDisplay(self, checked=None):
"""
@ -895,6 +904,7 @@ class SlideController(DisplayController):
Settings().remove(self.parent().generalSettingsSection + u'/screen blank')
self.blankPlugin()
self.updatePreview()
self.onToggleLoop()
def onHideDisplay(self, checked=None):
"""
@ -913,6 +923,7 @@ class SlideController(DisplayController):
Settings().remove(self.parent().generalSettingsSection + u'/screen blank')
self.hidePlugin(checked)
self.updatePreview()
self.onToggleLoop()
def blankPlugin(self):
"""
@ -1088,7 +1099,8 @@ class SlideController(DisplayController):
"""
Toggles the loop state.
"""
if self.playSlidesLoop.isChecked() or self.playSlidesOnce.isChecked():
hide_mode = self.hideMode()
if hide_mode is None and (self.playSlidesLoop.isChecked() or self.playSlidesOnce.isChecked()):
self.onStartLoop()
else:
self.onStopLoop()
@ -1122,11 +1134,11 @@ class SlideController(DisplayController):
self.playSlidesLoop.setText(UiStrings().StopPlaySlidesInLoop)
self.playSlidesOnce.setIcon(build_icon(u':/media/media_time.png'))
self.playSlidesOnce.setText(UiStrings().PlaySlidesToEnd)
self.playSlidesMenu.setDefaultAction(self.playSlidesLoop)
self.playSlidesOnce.setChecked(False)
else:
self.playSlidesLoop.setIcon(build_icon(u':/media/media_time.png'))
self.playSlidesLoop.setText(UiStrings().PlaySlidesInLoop)
self.playSlidesMenu.setDefaultAction(self.playSlidesLoop)
self.playSlidesOnce.setChecked(False)
self.onToggleLoop()
def onPlaySlidesOnce(self, checked=None):
@ -1143,11 +1155,11 @@ class SlideController(DisplayController):
self.playSlidesOnce.setText(UiStrings().StopPlaySlidesToEnd)
self.playSlidesLoop.setIcon(build_icon(u':/media/media_time.png'))
self.playSlidesLoop.setText(UiStrings().PlaySlidesInLoop)
self.playSlidesMenu.setDefaultAction(self.playSlidesOnce)
self.playSlidesLoop.setChecked(False)
else:
self.playSlidesOnce.setIcon(build_icon(u':/media/media_time'))
self.playSlidesOnce.setText(UiStrings().PlaySlidesToEnd)
self.playSlidesMenu.setDefaultAction(self.playSlidesOnce)
self.playSlidesLoop.setChecked(False)
self.onToggleLoop()
def setAudioItemsVisibility(self, visible):

View File

@ -2,10 +2,12 @@
Package to test the openlp.core.lib package.
"""
from unittest import TestCase
from datetime import datetime, timedelta
from mock import MagicMock, patch
from openlp.core.lib import str_to_bool, translate, check_directory_exists, get_text_file_string
from openlp.core.lib import str_to_bool, translate, check_directory_exists, get_text_file_string, build_icon, \
image_to_byte, check_item_selected, validate_thumb
class TestLib(TestCase):
@ -197,3 +199,163 @@ class TestLib(TestCase):
"""
assert True, u'Impossible to test due to conflicts when mocking out the "open" function'
def build_icon_with_qicon_test(self):
"""
Test the build_icon() function with a QIcon instance
"""
with patch(u'openlp.core.lib.QtGui') as MockedQtGui:
# GIVEN: A mocked QIcon
MockedQtGui.QIcon = MagicMock
mocked_icon = MockedQtGui.QIcon()
# WHEN: We pass a QIcon instance in
result = build_icon(mocked_icon)
# THEN: The result should be our mocked QIcon
assert result is mocked_icon, u'The result should be the mocked QIcon'
def build_icon_with_resource_test(self):
"""
Test the build_icon() function with a resource URI
"""
with patch(u'openlp.core.lib.QtGui') as MockedQtGui, \
patch(u'openlp.core.lib.QtGui.QPixmap') as MockedQPixmap:
# GIVEN: A mocked QIcon and a mocked QPixmap
MockedQtGui.QIcon = MagicMock
MockedQtGui.QIcon.Normal = 1
MockedQtGui.QIcon.Off = 2
MockedQPixmap.return_value = u'mocked_pixmap'
resource_uri = u':/resource/uri'
# WHEN: We pass a QIcon instance in
result = build_icon(resource_uri)
# THEN: The result should be our mocked QIcon
MockedQPixmap.assert_called_with(resource_uri)
# There really should be more assert statements here but due to type checking and things they all break. The
# best we can do is to assert that we get back a MagicMock object.
assert isinstance(result, MagicMock), u'The result should be a MagicMock, because we mocked it out'
def image_to_byte_test(self):
"""
Test the image_to_byte() function
"""
with patch(u'openlp.core.lib.QtCore') as MockedQtCore:
# GIVEN: A set of mocked-out Qt classes
mocked_byte_array = MagicMock()
MockedQtCore.QByteArray.return_value = mocked_byte_array
mocked_byte_array.toBase64.return_value = u'base64mock'
mocked_buffer = MagicMock()
MockedQtCore.QBuffer.return_value = mocked_buffer
MockedQtCore.QIODevice.WriteOnly = u'writeonly'
mocked_image = MagicMock()
# WHEN: We convert an image to a byte array
result = image_to_byte(mocked_image)
# THEN: We should receive a value of u'base64mock'
MockedQtCore.QByteArray.assert_called_with()
MockedQtCore.QBuffer.assert_called_with(mocked_byte_array)
mocked_buffer.open.assert_called_with(u'writeonly')
mocked_image.save.assert_called_with(mocked_buffer, "PNG")
mocked_byte_array.toBase64.assert_called_with()
assert result == u'base64mock', u'The result should be the return value of the mocked out base64 method'
def check_item_selected_true_test(self):
"""
Test that the check_item_selected() function returns True when there are selected indexes.
"""
# GIVEN: A mocked out QtGui module and a list widget with selected indexes
MockedQtGui = patch(u'openlp.core.lib.QtGui')
mocked_list_widget = MagicMock()
mocked_list_widget.selectedIndexes.return_value = True
message = u'message'
# WHEN: We check if there are selected items
result = check_item_selected(mocked_list_widget, message)
# THEN: The selectedIndexes function should have been called and the result should be true
mocked_list_widget.selectedIndexes.assert_called_with()
assert result, u'The result should be True'
def check_item_selected_false_test(self):
"""
Test that the check_item_selected() function returns False when there are no selected indexes.
"""
# GIVEN: A mocked out QtGui module and a list widget with selected indexes
with patch(u'openlp.core.lib.QtGui') as MockedQtGui, \
patch(u'openlp.core.lib.translate') as mocked_translate:
mocked_translate.return_value = u'mocked translate'
mocked_list_widget = MagicMock()
mocked_list_widget.selectedIndexes.return_value = False
mocked_list_widget.parent.return_value = u'parent'
message = u'message'
# WHEN: We check if there are selected items
result = check_item_selected(mocked_list_widget, message)
# THEN: The selectedIndexes function should have been called and the result should be true
mocked_list_widget.selectedIndexes.assert_called_with()
MockedQtGui.QMessageBox.information.assert_called_with(u'parent', u'mocked translate', 'message')
assert not result, u'The result should be False'
def validate_thumb_file_does_not_exist_test(self):
"""
Test the validate_thumb() function when the thumbnail does not exist
"""
# GIVEN: A mocked out os module, with path.exists returning False, and fake paths to a file and a thumb
with patch(u'openlp.core.lib.os') as mocked_os:
file_path = u'path/to/file'
thumb_path = u'path/to/thumb'
mocked_os.path.exists.return_value = False
# WHEN: we run the validate_thumb() function
result = validate_thumb(file_path, thumb_path)
# THEN: we should have called a few functions, and the result should be False
mocked_os.path.exists.assert_called_with(thumb_path)
assert result is False, u'The result should be False'
def validate_thumb_file_exists_and_newer_test(self):
"""
Test the validate_thumb() function when the thumbnail exists and has a newer timestamp than the file
"""
# GIVEN: A mocked out os module, functions rigged to work for us, and fake paths to a file and a thumb
with patch(u'openlp.core.lib.os') as mocked_os:
file_path = u'path/to/file'
thumb_path = u'path/to/thumb'
file_mocked_stat = MagicMock()
file_mocked_stat.st_mtime = datetime.now()
thumb_mocked_stat = MagicMock()
thumb_mocked_stat.st_mtime = datetime.now() + timedelta(seconds=10)
mocked_os.path.exists.return_value = True
mocked_os.stat.side_effect = [file_mocked_stat, thumb_mocked_stat]
# WHEN: we run the validate_thumb() function
# THEN: we should have called a few functions, and the result should be True
#mocked_os.path.exists.assert_called_with(thumb_path)
def validate_thumb_file_exists_and_older_test(self):
"""
Test the validate_thumb() function when the thumbnail exists but is older than the file
"""
# GIVEN: A mocked out os module, functions rigged to work for us, and fake paths to a file and a thumb
with patch(u'openlp.core.lib.os') as mocked_os:
file_path = u'path/to/file'
thumb_path = u'path/to/thumb'
file_mocked_stat = MagicMock()
file_mocked_stat.st_mtime = datetime.now()
thumb_mocked_stat = MagicMock()
thumb_mocked_stat.st_mtime = datetime.now() - timedelta(seconds=10)
mocked_os.path.exists.return_value = True
mocked_os.stat.side_effect = [file_mocked_stat, thumb_mocked_stat]
# WHEN: we run the validate_thumb() function
result = validate_thumb(file_path, thumb_path)
# THEN: we should have called a few functions, and the result should be False
mocked_os.path.exists.assert_called_with(thumb_path)
mocked_os.stat.assert_any_call(file_path)
mocked_os.stat.assert_any_call(thumb_path)
assert result is False, u'The result should be False'

View File

@ -16,7 +16,7 @@ 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']
TESTPATH = os.path.abspath(os.path.join(os.path.dirname(__file__), u'resources'))
TESTPATH = os.path.abspath(os.path.join(os.path.dirname(__file__), u'..', u'..', u'resources'))
class TestServiceItem(TestCase):
@ -160,4 +160,4 @@ class TestServiceItem(TestCase):
service_item.validate_item([u'png'])
# THEN the service item should not be valid
assert service_item.is_valid is False, u'The service item is not valid'
assert service_item.is_valid is False, u'The service item is not valid'

View File

@ -1,10 +1,11 @@
"""
Package to test the openlp.core.ui package.
Package to test the openlp.core.ui package.
"""
import sys
from unittest import TestCase
from mock import MagicMock
from openlp.core.ui import starttimeform
from PyQt4 import QtCore, QtGui, QtTest
@ -14,10 +15,18 @@ class TestStartTimeDialog(TestCase):
"""
Create the UI
"""
self.app = QtGui.QApplication(sys.argv)
self.app = QtGui.QApplication([])
self.window = QtGui.QMainWindow()
self.form = starttimeform.StartTimeForm(self.window)
def tearDown(self):
"""
Delete all the C++ objects at the end so that we don't have a segfault
"""
del self.form
del self.window
del self.app
def ui_defaults_test(self):
"""
Test StartTimeDialog defaults
@ -40,9 +49,9 @@ class TestStartTimeDialog(TestCase):
Test StartTimeDialog display initialisation
"""
#GIVEN: A service item with with time
mocked_serviceitem = MagicMock()
mocked_serviceitem = MagicMock()
mocked_serviceitem.start_time = 61
mocked_serviceitem.end_time = 3701
self.form.item = mocked_serviceitem
#self.form.exec_()
#self.form.exec_()

Binary file not shown.

Before

Width:  |  Height:  |  Size: 213 KiB

View File

Before

Width:  |  Height:  |  Size: 213 KiB

After

Width:  |  Height:  |  Size: 213 KiB