This commit is contained in:
Tim Bentley 2014-01-04 20:58:46 +00:00
commit 8038388110
12 changed files with 296 additions and 70 deletions

View File

@ -342,18 +342,16 @@ def create_valign_selection_widgets(parent):
return label, combo_box
def find_and_set_in_combo_box(combo_box, value_to_find):
def find_and_set_in_combo_box(combo_box, value_to_find, set_missing=True):
"""
Find a string in a combo box and set it as the selected item if present
``combo_box``
The combo box to check for selected items
``value_to_find``
The value to find
:param combo_box: The combo box to check for selected items
:param value_to_find: The value to find
:param set_missing: if not found leave value as current
"""
index = combo_box.findText(value_to_find, QtCore.Qt.MatchExactly)
if index == -1:
# Not Found.
index = 0
index = 0 if set_missing else combo_box.currentIndex()
combo_box.setCurrentIndex(index)

View File

@ -475,6 +475,19 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage
Settings().setValue('servicemanager/last file', '')
self.plugin_manager.new_service_created()
def create_basic_service(self):
"""
Create the initial service array with the base items to be saved.
:return service array
"""
service = []
core = {'lite-service': self._save_lite,
'service-theme': self.service_theme
}
service.append({'openlp_core': core})
return service
def save_file(self):
"""
Save the current service file.
@ -495,7 +508,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage
service_file_name = '%s.osj' % base_name
self.log_debug('ServiceManager.save_file - %s' % path_file_name)
Settings().setValue(self.main_window.service_manager_settings_section + '/last directory', path)
service = []
service = self.create_basic_service()
write_list = []
missing_list = []
audio_files = []
@ -607,9 +620,9 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage
path, file_name = os.path.split(path_file_name)
base_name = os.path.splitext(file_name)[0]
service_file_name = '%s.osj' % base_name
self.log_debug('ServiceManager.save_file - %s', path_file_name)
self.log_debug('ServiceManager.save_file - %s' % path_file_name)
Settings().setValue(self.main_window.service_manager_settings_section + '/last directory', path)
service = []
service = self.create_basic_service()
self.application.set_busy_cursor()
# Number of items + 1 to zip it
self.main_window.display_progress_bar(len(self.service_items) + 1)
@ -647,7 +660,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage
delete_file(temp_file_name)
return success
def save_file_as(self):
def save_file_as(self, field=None):
"""
Get a file name and then call :func:`ServiceManager.save_file` to save the file.
"""
@ -748,19 +761,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage
self.new_file()
self.set_file_name(file_name)
self.main_window.display_progress_bar(len(items))
for item in items:
self.main_window.increment_progress_bar()
service_item = ServiceItem()
if self._save_lite:
service_item.set_from_service(item)
else:
service_item.set_from_service(item, self.service_path)
service_item.validate_item(self.suffixes)
if service_item.is_capable(ItemCapabilities.OnLoadUpdate):
new_item = Registry().get(service_item.name).service_load(service_item)
if new_item:
service_item = new_item
self.add_service_item(service_item, repaint=False)
self.process_service_items(items)
delete_file(p_file)
self.main_window.add_recent_file(file_name)
self.set_modified(False)
@ -794,6 +795,34 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage
self.application.set_normal_cursor()
self.repaint_service_list(-1, -1)
def process_service_items(self, service_items):
"""
Process all the array of service items loaded from the saved service
:param service_items: list of service_items
"""
for item in service_items:
self.main_window.increment_progress_bar()
service_item = ServiceItem()
if 'openlp_core' in item:
item = item.get('openlp_core')
theme = item.get('service-theme', None)
if theme:
find_and_set_in_combo_box(self.theme_combo_box, theme, set_missing=False)
if theme == self.theme_combo_box.currentText():
self.renderer.set_service_theme(theme)
else:
if self._save_lite:
service_item.set_from_service(item)
else:
service_item.set_from_service(item, self.service_path)
service_item.validate_item(self.suffixes)
if service_item.is_capable(ItemCapabilities.OnLoadUpdate):
new_item = Registry().get(service_item.name).service_load(service_item)
if new_item:
service_item = new_item
self.add_service_item(service_item, repaint=False)
def load_last_file(self):
"""
Load the last service item from the service manager when the service was last closed. Can be blank if there was
@ -896,6 +925,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage
def toggle_auto_play_slides_once(self, field=None):
"""
Toggle Auto play slide once. Inverts auto play once option for the item
:param field:
"""
item = self.find_service_item()[0]
@ -912,6 +942,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage
def toggle_auto_play_slides_loop(self, field=None):
"""
Toggle Auto play slide loop.
:param field:
"""
item = self.find_service_item()[0]

View File

@ -72,6 +72,11 @@ WIDE_MENU = [
'desktop_screen_button'
]
NON_TEXT_MENU = [
'blank_screen_button',
'desktop_screen_button'
]
class DisplayController(QtGui.QWidget):
"""
@ -116,6 +121,9 @@ class SlideController(DisplayController):
self.screen_size_changed()
def initialise(self):
"""
Initialise the UI elements of the controller
"""
self.screens = ScreenList()
try:
self.ratio = self.screens.current['size'].width() / self.screens.current['size'].height()
@ -442,6 +450,8 @@ class SlideController(DisplayController):
def set_live_hot_keys(self, parent=None):
"""
Set the live hotkeys
:param parent: The parent UI object for actions to be added to.
"""
self.previous_service = create_action(parent, 'previousService',
text=translate('OpenLP.SlideController', 'Previous Service'),
@ -469,6 +479,8 @@ class SlideController(DisplayController):
def toggle_display(self, action):
"""
Toggle the display settings triggered from remote messages.
:param action: The blank action to be processed.
"""
if action == 'blank' or action == 'hide':
self.on_blank_display(True)
@ -544,6 +556,8 @@ class SlideController(DisplayController):
def __add_actions_to_widget(self, widget):
"""
Add actions to the widget specified by `widget`
:param widget: The UI widget for the actions
"""
widget.addActions([
self.previous_item, self.next_item,
@ -574,6 +588,8 @@ class SlideController(DisplayController):
def on_controller_size_changed(self, width):
"""
Change layout of display control buttons on controller size change
:param width: the new width of the display
"""
if self.is_live:
# Space used by the toolbar.
@ -581,12 +597,24 @@ class SlideController(DisplayController):
# Add the threshold to prevent flickering.
if width > used_space + HIDE_MENU_THRESHOLD and self.hide_menu.isVisible():
self.toolbar.set_widget_visible(NARROW_MENU, False)
self.toolbar.set_widget_visible(WIDE_MENU)
self.set_blank_menu()
# Take away a threshold to prevent flickering.
elif width < used_space - HIDE_MENU_THRESHOLD and not self.hide_menu.isVisible():
self.toolbar.set_widget_visible(WIDE_MENU, False)
self.set_blank_menu(False)
self.toolbar.set_widget_visible(NARROW_MENU)
def set_blank_menu(self, visible=True):
"""
Set the correct menu type dependent on the service item type
:param visible: Do I need to hide the menu?
"""
self.toolbar.set_widget_visible(WIDE_MENU, False)
if self.service_item and self.service_item.is_text():
self.toolbar.set_widget_visible(WIDE_MENU, visible)
else:
self.toolbar.set_widget_visible(NON_TEXT_MENU, visible)
def on_song_bar_handler(self):
"""
Some song handler
@ -612,6 +640,8 @@ class SlideController(DisplayController):
def enable_tool_bar(self, item):
"""
Allows the toolbars to be reconfigured based on Controller Type and ServiceItem Type
:param item: current service item being processed
"""
if self.is_live:
self.enable_live_tool_bar(item)
@ -621,6 +651,8 @@ class SlideController(DisplayController):
def enable_live_tool_bar(self, item):
"""
Allows the live toolbar to be customised
:param item: The current service item
"""
# Work-around for OS X, hide and then show the toolbar
# See bug #791050
@ -643,6 +675,7 @@ class SlideController(DisplayController):
self.mediabar.show()
self.previous_item.setVisible(not item.is_media())
self.next_item.setVisible(not item.is_media())
self.set_blank_menu()
# Work-around for OS X, hide and then show the toolbar
# See bug #791050
self.toolbar.show()

View File

@ -59,22 +59,18 @@ class TestRegistry(TestCase):
with self.assertRaises(KeyError) as context:
Registry().register('test1', mock_1)
self.assertEqual(context.exception.args[0], 'Duplicate service exception test1',
'KeyError exception should have been thrown for duplicate service')
'KeyError exception should have been thrown for duplicate service')
# WHEN I try to get back a non existent component
# THEN I will get an exception
with self.assertRaises(KeyError) as context:
temp = Registry().get('test2')
self.assertEqual(context.exception.args[0], 'Service test2 not found in list',
'KeyError exception should have been thrown for missing service')
temp = Registry().get('test2')
self.assertEqual(temp, None, 'None should have been returned for missing service')
# WHEN I try to replace a component I should be allowed (testing only)
Registry().remove('test1')
# THEN I will get an exception
with self.assertRaises(KeyError) as context:
temp = Registry().get('test1')
self.assertEqual(context.exception.args[0], 'Service test1 not found in list',
'KeyError exception should have been thrown for deleted service')
temp = Registry().get('test1')
self.assertEqual(temp, None, 'None should have been returned for deleted service')
def registry_function_test(self):
"""

View File

@ -0,0 +1,85 @@
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2014 Raoul Snyman #
# Portions copyright (c) 2008-2014 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 #
###############################################################################
"""
Package to test the openlp.core.ui.slidecontroller package.
"""
from unittest import TestCase
from openlp.core.common import Registry
from openlp.core.ui import ServiceManager
from tests.interfaces import MagicMock, patch
class TestServiceManager(TestCase):
def setUp(self):
"""
Create the UI
"""
Registry.create()
#self.app = QtGui.QApplication([])
#ScreenList.create(self.app.desktop())
#Registry().register('application', MagicMock())
#with patch('openlp.core.lib.PluginManager'):
# self.main_window = MainWindow()
#self.service_manager = Registry().get('service_manager')
def tearDown(self):
"""
Delete all the C++ objects at the end so that we don't have a segfault
"""
#del self.main_window
#del self.app
pass
def initial_service_manager_test(self):
"""
Test the initial of service manager.
"""
# GIVEN: A new service manager instance.
ServiceManager(None)
# WHEN: the default service manager is built.
# THEN: The the controller should be registered in the registry.
self.assertNotEqual(Registry().get('service_manager'), None, 'The base service manager should be registered')
def create_basic_service_test(self):
"""
Test the create basic service array
"""
# GIVEN: A new service manager instance.
service_manager = ServiceManager(None)
# WHEN: when the basic service array is created.
service_manager._save_lite = False
service_manager.service_theme = 'test_theme'
service = service_manager.create_basic_service()[0]
# THEN: The the controller should be registered in the registry.
self.assertNotEqual(service, None, 'The base service should be created')
self.assertEqual(service['openlp_core']['service-theme'], 'test_theme', 'The test theme should be saved')
self.assertEqual(service['openlp_core']['lite-service'], False, 'The lite service should be saved')

View File

@ -0,0 +1,78 @@
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2014 Raoul Snyman #
# Portions copyright (c) 2008-2014 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 #
###############################################################################
"""
Package to test the openlp.core.ui.slidecontroller package.
"""
from unittest import TestCase
from openlp.core.ui import SlideController
from tests.interfaces import MagicMock, patch
class TestSlideController(TestCase):
def initial_slide_controller_test(self):
"""
Test the initial slide controller state .
"""
# GIVEN: A new slideController instance.
slide_controller = SlideController(None)
# WHEN: the default controller is built.
# THEN: The controller should not be a live controller.
self.assertEqual(slide_controller.is_live, False, 'The base slide controller should not be a live controller')
def toggle_blank_test(self):
"""
Test the setting of the display blank icons by display type.
"""
# GIVEN: A new slideController instance.
slide_controller = SlideController(None)
service_item = MagicMock()
toolbar = MagicMock()
toolbar.set_widget_visible = self.dummy_widget_visible
slide_controller.toolbar = toolbar
slide_controller.service_item = service_item
# WHEN a text based service item is used
slide_controller.service_item.is_text = MagicMock(return_value=True)
slide_controller.set_blank_menu()
# THEN: then call set up the toolbar to blank the display screen.
self.assertEqual(len(self.test_widget), 3, 'There should be three icons to display on the screen')
# WHEN a non text based service item is used
slide_controller.service_item.is_text = MagicMock(return_value=False)
slide_controller.set_blank_menu()
# THEN: then call set up the toolbar to blank the display screen.
self.assertEqual(len(self.test_widget), 2, 'There should be only two icons to display on the screen')
def dummy_widget_visible(self, widget, visible=True):
self.test_widget = widget

View File

@ -38,7 +38,7 @@ class TestListPreviewWidget(TestCase):
def initial_slide_count_test(self):
"""
Test the inital slide count.
Test the initial slide count .
"""
# GIVEN: A new ListPreviewWidget instance.
# WHEN: No SlideItem has been added yet.
@ -47,7 +47,7 @@ class TestListPreviewWidget(TestCase):
def initial_slide_number_test(self):
"""
Test the inital slide number.
Test the initial current slide number.
"""
# GIVEN: A new ListPreviewWidget instance.
# WHEN: No SlideItem has been added yet.

View File

@ -22,12 +22,13 @@ class TestMainWindow(TestCase):
# Mock cursor busy/normal methods.
self.app.set_busy_cursor = MagicMock()
self.app.set_normal_cursor = MagicMock()
self.app.args =[]
self.app.args = []
Registry().register('application', self.app)
# Mock classes and methods used by mainwindow.
with patch('openlp.core.ui.mainwindow.SettingsForm') as mocked_settings_form, \
patch('openlp.core.ui.mainwindow.ImageManager') as mocked_image_manager, \
patch('openlp.core.ui.mainwindow.SlideController') as mocked_slide_controller, \
patch('openlp.core.ui.mainwindow.LiveController') as mocked_live_controller, \
patch('openlp.core.ui.mainwindow.PreviewController') as mocked_preview_controller, \
patch('openlp.core.ui.mainwindow.OpenLPDockWidget') as mocked_dock_widget, \
patch('openlp.core.ui.mainwindow.QtGui.QToolBox') as mocked_q_tool_box_class, \
patch('openlp.core.ui.mainwindow.QtGui.QMainWindow.addDockWidget') as mocked_add_dock_method, \
@ -53,7 +54,7 @@ class TestMainWindow(TestCase):
mocked_value.side_effect = [True, 2]
# WHEN: Call the restore method.
Registry().execute('bootstrap_post_set_up')
self.main_window.restore_current_media_manager_item()
# THEN: The current widget should have been set.
self.main_window.media_tool_box.setCurrentIndex.assert_called_with(2)

View File

@ -34,28 +34,28 @@ class TestStartTimeDialog(TestCase):
"""
Test StartTimeDialog are defaults correct
"""
self.assertEqual(self.form.hourSpinBox.minimum(), 0, 'The minimum hour should stay the same as the dialog')
self.assertEqual(self.form.hourSpinBox.maximum(), 4, 'The maximum hour should stay the same as the dialog')
self.assertEqual(self.form.minuteSpinBox.minimum(), 0,
'The minimum minute should stay the same as the dialog')
self.assertEqual(self.form.minuteSpinBox.maximum(), 59,
'The maximum minute should stay the same as the dialog')
self.assertEqual(self.form.secondSpinBox.minimum(), 0,
'The minimum second should stay the same as the dialog')
self.assertEqual(self.form.secondSpinBox.maximum(), 59,
'The maximum second should stay the same as the dialog')
self.assertEqual(self.form.hourFinishSpinBox.minimum(), 0,
'The minimum finish hour should stay the same as the dialog')
self.assertEqual(self.form.hourFinishSpinBox.maximum(), 4,
'The maximum finish hour should stay the same as the dialog')
self.assertEqual(self.form.minuteFinishSpinBox.minimum(), 0,
'The minimum finish minute should stay the same as the dialog')
self.assertEqual(self.form.minuteFinishSpinBox.maximum(), 59,
'The maximum finish minute should stay the same as the dialog')
self.assertEqual(self.form.secondFinishSpinBox.minimum(), 0,
'The minimum finish second should stay the same as the dialog')
self.assertEqual(self.form.secondFinishSpinBox.maximum(), 59,
'The maximum finish second should stay the same as the dialog')
self.assertEqual(self.form.hour_spin_box.minimum(), 0, 'The minimum hour should stay the same as the dialog')
self.assertEqual(self.form.hour_spin_box.maximum(), 4, 'The maximum hour should stay the same as the dialog')
self.assertEqual(self.form.minute_spin_box.minimum(), 0,
'The minimum minute should stay the same as the dialog')
self.assertEqual(self.form.minute_spin_box.maximum(), 59,
'The maximum minute should stay the same as the dialog')
self.assertEqual(self.form.second_spin_box.minimum(), 0,
'The minimum second should stay the same as the dialog')
self.assertEqual(self.form.second_spin_box.maximum(), 59,
'The maximum second should stay the same as the dialog')
self.assertEqual(self.form.hour_finish_spin_box.minimum(), 0,
'The minimum finish hour should stay the same as the dialog')
self.assertEqual(self.form.hour_finish_spin_box.maximum(), 4,
'The maximum finish hour should stay the same as the dialog')
self.assertEqual(self.form.minute_finish_spin_box.minimum(), 0,
'The minimum finish minute should stay the same as the dialog')
self.assertEqual(self.form.minute_finish_spin_box.maximum(), 59,
'The maximum finish minute should stay the same as the dialog')
self.assertEqual(self.form.second_finish_spin_box.minimum(), 0,
'The minimum finish second should stay the same as the dialog')
self.assertEqual(self.form.second_finish_spin_box.maximum(), 59,
'The maximum finish second should stay the same as the dialog')
def time_display_test(self):
"""
@ -75,22 +75,22 @@ class TestStartTimeDialog(TestCase):
QtTest.QTest.mouseClick(ok_widget, QtCore.Qt.LeftButton)
# THEN the following input values are returned
self.assertEqual(self.form.hourSpinBox.value(), 0)
self.assertEqual(self.form.minuteSpinBox.value(), 1)
self.assertEqual(self.form.secondSpinBox.value(), 1)
self.assertEqual(self.form.hour_spin_box.value(), 0)
self.assertEqual(self.form.minute_spin_box.value(), 1)
self.assertEqual(self.form.second_spin_box.value(), 1)
self.assertEqual(self.form.item['service_item'].start_time, 61, 'The start time should stay the same')
# WHEN displaying the UI, changing the time to 2min 3secs and pressing enter
self.form.item = {'service_item': mocked_serviceitem}
with patch('PyQt4.QtGui.QDialog.exec_'):
self.form.exec_()
self.form.minuteSpinBox.setValue(2)
self.form.secondSpinBox.setValue(3)
self.form.minute_spin_box.setValue(2)
self.form.second_spin_box.setValue(3)
ok_widget = self.form.button_box.button(self.form.button_box.Ok)
QtTest.QTest.mouseClick(ok_widget, QtCore.Qt.LeftButton)
# THEN the following values are returned
self.assertEqual(self.form.hourSpinBox.value(), 0)
self.assertEqual(self.form.minuteSpinBox.value(), 2)
self.assertEqual(self.form.secondSpinBox.value(), 3)
self.assertEqual(self.form.hour_spin_box.value(), 0)
self.assertEqual(self.form.minute_spin_box.value(), 2)
self.assertEqual(self.form.second_spin_box.value(), 3)
self.assertEqual(self.form.item['service_item'].start_time, 123, 'The start time should have changed')

View File

@ -33,6 +33,8 @@ import os
from unittest import TestCase
from tempfile import mkstemp
from PyQt4 import QtGui
from openlp.core.common import Registry, Settings
from openlp.core.ui import ThemeManager
from tests.functional import patch, MagicMock
@ -48,6 +50,7 @@ class TestThemeManager(TestCase):
"""
fd, self.ini_file = mkstemp('.ini')
Settings().set_filename(self.ini_file)
self.app = QtGui.QApplication([])
Registry.create()
self.theme_manager = ThemeManager()
@ -57,6 +60,7 @@ class TestThemeManager(TestCase):
"""
os.unlink(self.ini_file)
os.unlink(Settings().fileName())
del self.app
def initialise_test(self):
"""