Changed the way we create and initialise MediaManagerItems so that we can test things better.

This commit is contained in:
Raoul Snyman 2013-10-02 23:07:20 +02:00
parent 3503c54ce4
commit 1347ad61d1
13 changed files with 104 additions and 48 deletions

View File

@ -82,10 +82,17 @@ class MediaManagerItem(QtGui.QWidget):
""" """
Constructor to create the media manager item. Constructor to create the media manager item.
""" """
super(MediaManagerItem, self).__init__() super(MediaManagerItem, self).__init__(parent)
self.plugin = plugin
self._setup()
self.setup_item()
def _setup(self):
"""
Run some initial setup. This method is separate from __init__ in order to mock it out in tests.
"""
self.hide() self.hide()
self.whitespace = re.compile(r'[\W_]+', re.UNICODE) self.whitespace = re.compile(r'[\W_]+', re.UNICODE)
self.plugin = plugin
visible_title = self.plugin.get_string(StringContent.VisibleName) visible_title = self.plugin.get_string(StringContent.VisibleName)
self.title = str(visible_title['title']) self.title = str(visible_title['title'])
Registry().register(self.plugin.name, self) Registry().register(self.plugin.name, self)
@ -106,6 +113,12 @@ class MediaManagerItem(QtGui.QWidget):
QtCore.QObject.connect(self, QtCore.SIGNAL('%s_go_live' % self.plugin.name), self.go_live_remote) QtCore.QObject.connect(self, QtCore.SIGNAL('%s_go_live' % self.plugin.name), self.go_live_remote)
QtCore.QObject.connect(self, QtCore.SIGNAL('%s_add_to_service' % self.plugin.name), self.add_to_service_remote) QtCore.QObject.connect(self, QtCore.SIGNAL('%s_add_to_service' % self.plugin.name), self.add_to_service_remote)
def setup_item(self):
"""
Override this for additional Plugin setup
"""
pass
def required_icons(self): def required_icons(self):
""" """
This method is called to define the icons for the plugin. It provides a default set and the plugin is able to This method is called to define the icons for the plugin. It provides a default set and the plugin is able to

View File

@ -67,6 +67,9 @@ __default_settings__ = {
class BiblePlugin(Plugin): class BiblePlugin(Plugin):
"""
The Bible plugin provides a plugin for managing and displaying Bibles.
"""
log.info('Bible Plugin loaded') log.info('Bible Plugin loaded')
def __init__(self): def __init__(self):
@ -74,13 +77,14 @@ class BiblePlugin(Plugin):
self.weight = -9 self.weight = -9
self.icon_path = ':/plugins/plugin_bibles.png' self.icon_path = ':/plugins/plugin_bibles.png'
self.icon = build_icon(self.icon_path) self.icon = build_icon(self.icon_path)
self.manager = None self.manager = BibleManager(self)
def initialise(self): def initialise(self):
"""
Initialise the Bible plugin.
"""
log.info('bibles Initialising') log.info('bibles Initialising')
if self.manager is None: super(BiblePlugin, self).initialise()
self.manager = BibleManager(self)
Plugin.initialise(self)
self.import_bible_item.setVisible(True) self.import_bible_item.setVisible(True)
action_list = ActionList.get_instance() action_list = ActionList.get_instance()
action_list.add_action(self.import_bible_item, UiStrings().Import) action_list.add_action(self.import_bible_item, UiStrings().Import)
@ -107,7 +111,7 @@ class BiblePlugin(Plugin):
""" """
Perform tasks on application startup Perform tasks on application startup
""" """
Plugin.app_startup(self) super(BiblePlugin, self).app_startup()
if self.manager.old_bible_databases: if self.manager.old_bible_databases:
if QtGui.QMessageBox.information(self.main_window, if QtGui.QMessageBox.information(self.main_window,
translate('OpenLP', 'Information'), translate('OpenLP', 'Information'),

View File

@ -64,6 +64,11 @@ class BibleMediaItem(MediaManagerItem):
self.lock_icon = build_icon(':/bibles/bibles_search_lock.png') self.lock_icon = build_icon(':/bibles/bibles_search_lock.png')
self.unlock_icon = build_icon(':/bibles/bibles_search_unlock.png') self.unlock_icon = build_icon(':/bibles/bibles_search_unlock.png')
MediaManagerItem.__init__(self, parent, plugin) MediaManagerItem.__init__(self, parent, plugin)
def setup_item(self):
"""
Do some additional setup.
"""
# Place to store the search results for both bibles. # Place to store the search results for both bibles.
self.settings = self.plugin.settings_tab self.settings = self.plugin.settings_tab
self.quick_preview_allowed = True self.quick_preview_allowed = True

View File

@ -58,6 +58,11 @@ class CustomMediaItem(MediaManagerItem):
def __init__(self, parent, plugin): def __init__(self, parent, plugin):
self.icon_path = 'custom/custom' self.icon_path = 'custom/custom'
super(CustomMediaItem, self).__init__(parent, plugin) super(CustomMediaItem, self).__init__(parent, plugin)
def setup_item(self):
"""
Do some additional setup.
"""
self.edit_custom_form = EditCustomForm(self, self.main_window, self.plugin.manager) self.edit_custom_form = EditCustomForm(self, self.main_window, self.plugin.manager)
self.single_service_item = False self.single_service_item = False
self.quick_preview_allowed = True self.quick_preview_allowed = True
@ -65,7 +70,7 @@ class CustomMediaItem(MediaManagerItem):
# Holds information about whether the edit is remotely triggered and # Holds information about whether the edit is remotely triggered and
# which Custom is required. # which Custom is required.
self.remote_custom = -1 self.remote_custom = -1
self.manager = plugin.manager self.manager = self.plugin.manager
def add_end_header_bar(self): def add_end_header_bar(self):
self.toolbar.addSeparator() self.toolbar.addSeparator()

View File

@ -52,10 +52,18 @@ class ImageMediaItem(MediaManagerItem):
def __init__(self, parent, plugin): def __init__(self, parent, plugin):
self.icon_path = 'images/image' self.icon_path = 'images/image'
self.manager = None
self.choose_group_form = None
self.add_group_form = None
super(ImageMediaItem, self).__init__(parent, plugin) super(ImageMediaItem, self).__init__(parent, plugin)
def setup_item(self):
"""
Do some additional setup.
"""
self.quick_preview_allowed = True self.quick_preview_allowed = True
self.has_search = True self.has_search = True
self.manager = plugin.manager self.manager = self.plugin.manager
self.choose_group_form = ChooseGroupForm(self) self.choose_group_form = ChooseGroupForm(self)
self.add_group_form = AddGroupForm(self) self.add_group_form = AddGroupForm(self)
self.fill_groups_combobox(self.choose_group_form.group_combobox) self.fill_groups_combobox(self.choose_group_form.group_combobox)
@ -91,8 +99,8 @@ class ImageMediaItem(MediaManagerItem):
self.list_view.setIconSize(QtCore.QSize(88, 50)) self.list_view.setIconSize(QtCore.QSize(88, 50))
self.list_view.setIndentation(self.list_view.default_indentation) self.list_view.setIndentation(self.list_view.default_indentation)
self.list_view.allow_internal_dnd = True self.list_view.allow_internal_dnd = True
self.servicePath = os.path.join(AppLocation.get_section_data_path(self.settings_section), 'thumbnails') self.service_path = os.path.join(AppLocation.get_section_data_path(self.settings_section), 'thumbnails')
check_directory_exists(self.servicePath) check_directory_exists(self.service_path)
# Load images from the database # Load images from the database
self.load_full_list( self.load_full_list(
self.manager.get_all_objects(ImageFilenames, order_by_ref=ImageFilenames.filename), initial_load=True) self.manager.get_all_objects(ImageFilenames, order_by_ref=ImageFilenames.filename), initial_load=True)
@ -193,7 +201,7 @@ class ImageMediaItem(MediaManagerItem):
""" """
images = self.manager.get_all_objects(ImageFilenames, ImageFilenames.group_id == image_group.id) images = self.manager.get_all_objects(ImageFilenames, ImageFilenames.group_id == image_group.id)
for image in images: for image in images:
delete_file(os.path.join(self.servicePath, os.path.split(image.filename)[1])) delete_file(os.path.join(self.service_path, os.path.split(image.filename)[1]))
self.manager.delete_object(ImageFilenames, image.id) self.manager.delete_object(ImageFilenames, image.id)
image_groups = self.manager.get_all_objects(ImageGroups, ImageGroups.parent_id == image_group.id) image_groups = self.manager.get_all_objects(ImageGroups, ImageGroups.parent_id == image_group.id)
for group in image_groups: for group in image_groups:
@ -215,7 +223,7 @@ class ImageMediaItem(MediaManagerItem):
if row_item: if row_item:
item_data = row_item.data(0, QtCore.Qt.UserRole) item_data = row_item.data(0, QtCore.Qt.UserRole)
if isinstance(item_data, ImageFilenames): if isinstance(item_data, ImageFilenames):
delete_file(os.path.join(self.servicePath, row_item.text(0))) delete_file(os.path.join(self.service_path, row_item.text(0)))
if item_data.group_id == 0: if item_data.group_id == 0:
self.list_view.takeTopLevelItem(self.list_view.indexOfTopLevelItem(row_item)) self.list_view.takeTopLevelItem(self.list_view.indexOfTopLevelItem(row_item))
else: else:
@ -339,7 +347,7 @@ class ImageMediaItem(MediaManagerItem):
for imageFile in images: for imageFile in images:
log.debug('Loading image: %s', imageFile.filename) log.debug('Loading image: %s', imageFile.filename)
filename = os.path.split(imageFile.filename)[1] filename = os.path.split(imageFile.filename)[1]
thumb = os.path.join(self.servicePath, filename) thumb = os.path.join(self.service_path, filename)
if not os.path.exists(imageFile.filename): if not os.path.exists(imageFile.filename):
icon = build_icon(':/general/general_delete.png') icon = build_icon(':/general/general_delete.png')
else: else:
@ -672,7 +680,16 @@ class ImageMediaItem(MediaManagerItem):
translate('ImagePlugin.MediaItem', 'There was a problem replacing your background, ' translate('ImagePlugin.MediaItem', 'There was a problem replacing your background, '
'the image file "%s" no longer exists.') % filename) 'the image file "%s" no longer exists.') % filename)
def search(self, string, showError): def search(self, string, show_error=True):
"""
Perform a search on the image file names.
``string``
The glob to search for
``show_error``
Unused.
"""
files = self.manager.get_all_objects(ImageFilenames, filter_clause=ImageFilenames.filename.contains(string), files = self.manager.get_all_objects(ImageFilenames, filter_clause=ImageFilenames.filename.contains(string),
order_by_ref=ImageFilenames.filename) order_by_ref=ImageFilenames.filename)
results = [] results = []

View File

@ -61,10 +61,15 @@ class MediaMediaItem(MediaManagerItem):
self.background = False self.background = False
self.automatic = '' self.automatic = ''
super(MediaMediaItem, self).__init__(parent, plugin) super(MediaMediaItem, self).__init__(parent, plugin)
def setup_item(self):
"""
Do some additional setup.
"""
self.single_service_item = False self.single_service_item = False
self.has_search = True self.has_search = True
self.media_object = None self.media_object = None
self.display_controller = DisplayController(parent) self.display_controller = DisplayController(self.parent())
self.display_controller.controller_layout = QtGui.QVBoxLayout() self.display_controller.controller_layout = QtGui.QVBoxLayout()
self.media_controller.register_controller(self.display_controller) self.media_controller.register_controller(self.display_controller)
self.media_controller.set_controls_visible(self.display_controller, False) self.media_controller.set_controls_visible(self.display_controller, False)

View File

@ -52,14 +52,26 @@ class PresentationMediaItem(MediaManagerItem):
""" """
log.info('Presentations Media Item loaded') log.info('Presentations Media Item loaded')
def __init__(self, parent, plugin, icon, controllers): def __init__(self, parent, plugin, controllers):
""" """
Constructor. Setup defaults Constructor. Setup defaults
""" """
self.controllers = controllers
self.icon_path = 'presentations/presentation' self.icon_path = 'presentations/presentation'
self.Automatic = '' self.controllers = controllers
super(PresentationMediaItem, self).__init__(parent, plugin) super(PresentationMediaItem, self).__init__(parent, plugin)
def retranslateUi(self):
"""
The name of the plugin media displayed in UI
"""
self.on_new_prompt = translate('PresentationPlugin.MediaItem', 'Select Presentation(s)')
self.automatic = translate('PresentationPlugin.MediaItem', 'Automatic')
self.display_type_label.setText(translate('PresentationPlugin.MediaItem', 'Present using:'))
def setup_item(self):
"""
Do some additional setup.
"""
self.message_listener = MessageListener(self) self.message_listener = MessageListener(self)
self.has_search = True self.has_search = True
self.single_service_item = False self.single_service_item = False
@ -68,14 +80,6 @@ class PresentationMediaItem(MediaManagerItem):
# Allow DnD from the desktop # Allow DnD from the desktop
self.list_view.activateDnD() self.list_view.activateDnD()
def retranslateUi(self):
"""
The name of the plugin media displayed in UI
"""
self.on_new_prompt = translate('PresentationPlugin.MediaItem', 'Select Presentation(s)')
self.Automatic = translate('PresentationPlugin.MediaItem', 'Automatic')
self.display_type_label.setText(translate('PresentationPlugin.MediaItem', 'Present using:'))
def build_file_mask_string(self): def build_file_mask_string(self):
""" """
Build the list of file extensions to be used in the Open file dialog. Build the list of file extensions to be used in the Open file dialog.
@ -137,7 +141,7 @@ class PresentationMediaItem(MediaManagerItem):
if self.controllers[item].enabled(): if self.controllers[item].enabled():
self.display_type_combo_box.addItem(item) self.display_type_combo_box.addItem(item)
if self.display_type_combo_box.count() > 1: if self.display_type_combo_box.count() > 1:
self.display_type_combo_box.insertItem(0, self.Automatic) self.display_type_combo_box.insertItem(0, self.automatic)
self.display_type_combo_box.setCurrentIndex(0) self.display_type_combo_box.setCurrentIndex(0)
if Settings().value(self.settings_section + '/override app') == QtCore.Qt.Checked: if Settings().value(self.settings_section + '/override app') == QtCore.Qt.Checked:
self.presentation_widget.show() self.presentation_widget.show()
@ -253,7 +257,7 @@ class PresentationMediaItem(MediaManagerItem):
(path, name) = os.path.split(filename) (path, name) = os.path.split(filename)
service_item.title = name service_item.title = name
if os.path.exists(filename): if os.path.exists(filename):
if service_item.processor == self.Automatic: if service_item.processor == self.automatic:
service_item.processor = self.findControllerByType(filename) service_item.processor = self.findControllerByType(filename)
if not service_item.processor: if not service_item.processor:
return False return False

View File

@ -109,8 +109,7 @@ class PresentationPlugin(Plugin):
""" """
Create the Media Manager List. Create the Media Manager List.
""" """
self.media_item = PresentationMediaItem( self.media_item = PresentationMediaItem(self.main_window.media_dock_manager.media_dock, self, self.controllers)
self.main_window.media_dock_manager.media_dock, self, self.icon, self.controllers)
def register_controllers(self, controller): def register_controllers(self, controller):
""" """

View File

@ -72,6 +72,11 @@ class SongMediaItem(MediaManagerItem):
def __init__(self, parent, plugin): def __init__(self, parent, plugin):
self.icon_path = 'songs/song' self.icon_path = 'songs/song'
super(SongMediaItem, self).__init__(parent, plugin) super(SongMediaItem, self).__init__(parent, plugin)
def setup_item(self):
"""
Do some additional setup.
"""
self.single_service_item = False self.single_service_item = False
# Holds information about whether the edit is remotely triggered and which Song is required. # Holds information about whether the edit is remotely triggered and which Song is required.
self.remote_song = -1 self.remote_song = -1

View File

@ -95,9 +95,9 @@ class TestServiceItem(TestCase):
# THEN: The frames should also be valid # THEN: The frames should also be valid
self.assertEqual('Test Custom', service_item.get_display_title(), 'The title should be "Test Custom"') self.assertEqual('Test Custom', service_item.get_display_title(), 'The title should be "Test Custom"')
self.assertEqual(VERSE[:-1], service_item.get_frames()[0]['text'], self.assertEqual(VERSE[:-1], service_item.get_frames()[0]['text'],
'The returned text matches the input, except the last line feed') 'The returned text matches the input, except the last line feed')
self.assertEqual(VERSE.split('\n', 1)[0], service_item.get_rendered_frame(1), self.assertEqual(VERSE.split('\n', 1)[0], service_item.get_rendered_frame(1),
'The first line has been returned') 'The first line has been returned')
self.assertEqual('Slide 1', service_item.get_frame_title(0), '"Slide 1" has been returned as the title') self.assertEqual('Slide 1', service_item.get_frame_title(0), '"Slide 1" has been returned as the title')
self.assertEqual('Slide 2', service_item.get_frame_title(1), '"Slide 2" has been returned as the title') self.assertEqual('Slide 2', service_item.get_frame_title(1), '"Slide 2" has been returned as the title')
self.assertEqual('', service_item.get_frame_title(2), 'Blank has been returned as the title of slide 3') self.assertEqual('', service_item.get_frame_title(2), 'Blank has been returned as the title of slide 3')

View File

@ -48,11 +48,10 @@ class TestImageMediaItem(TestCase):
Registry().register('service_list', MagicMock()) Registry().register('service_list', MagicMock())
Registry().register('main_window', self.mocked_main_window) Registry().register('main_window', self.mocked_main_window)
Registry().register('live_controller', MagicMock()) Registry().register('live_controller', MagicMock())
mocked_parent = MagicMock()
mocked_plugin = MagicMock() mocked_plugin = MagicMock()
with patch('openlp.plugins.images.lib.mediaitem.ImageMediaItem.__init__') as mocked_init: with patch('openlp.plugins.images.lib.mediaitem.MediaManagerItem._setup'), \
mocked_init.return_value = None patch('openlp.plugins.images.lib.mediaitem.ImageMediaItem.setup_item'):
self.media_item = ImageMediaItem(mocked_parent, mocked_plugin) self.media_item = ImageMediaItem(None, mocked_plugin)
def save_new_images_list_empty_list_test(self): def save_new_images_list_empty_list_test(self):
""" """
@ -160,7 +159,7 @@ class TestImageMediaItem(TestCase):
ImageGroups.parent_id = 1 ImageGroups.parent_id = 1
self.media_item.manager = MagicMock() self.media_item.manager = MagicMock()
self.media_item.manager.get_all_objects.side_effect = self._recursively_delete_group_side_effect self.media_item.manager.get_all_objects.side_effect = self._recursively_delete_group_side_effect
self.media_item.servicePath = "" self.media_item.service_path = ""
test_group = ImageGroups() test_group = ImageGroups()
test_group.id = 1 test_group.id = 1

View File

@ -49,11 +49,9 @@ class TestMediaItem(TestCase):
Registry.create() Registry.create()
Registry().register('service_manager', MagicMock()) Registry().register('service_manager', MagicMock())
Registry().register('main_window', MagicMock()) Registry().register('main_window', MagicMock())
with patch('openlp.plugins.presentations.lib.mediaitem.MediaManagerItem._setup'), \
with patch('openlp.plugins.presentations.lib.mediaitem.PresentationMediaItem.__init__') as mocked_init: patch('openlp.plugins.presentations.lib.mediaitem.PresentationMediaItem.setup_item'):
mocked_init.return_value = None self.media_item = PresentationMediaItem(None, MagicMock, MagicMock())
self.media_item = PresentationMediaItem(MagicMock(), MagicMock, MagicMock(), MagicMock())
self.application = QtGui.QApplication.instance() self.application = QtGui.QApplication.instance()
def tearDown(self): def tearDown(self):
@ -89,6 +87,8 @@ class TestMediaItem(TestCase):
mocked_translate.side_effect = lambda module, string_to_translate: string_to_translate mocked_translate.side_effect = lambda module, string_to_translate: string_to_translate
self.media_item.build_file_mask_string() self.media_item.build_file_mask_string()
# THEN: The file mask should be generated. # THEN: The file mask should be generated correctly
assert self.media_item.on_new_file_masks == 'Presentations (*.odp *.ppt )', \ self.assertIn('*.odp', self.media_item.on_new_file_masks,
'The file mask should contain the odp and ppt extensions' 'The file mask should contain the odp extension')
self.assertIn('*.ppt', self.media_item.on_new_file_masks,
'The file mask should contain the ppt extension')

View File

@ -23,9 +23,9 @@ class TestMediaItem(TestCase):
Registry.create() Registry.create()
Registry().register('service_list', MagicMock()) Registry().register('service_list', MagicMock())
Registry().register('main_window', MagicMock()) Registry().register('main_window', MagicMock())
with patch('openlp.core.lib.mediamanageritem.MediaManagerItem.__init__'), \ with patch('openlp.core.lib.mediamanageritem.MediaManagerItem._setup'), \
patch('openlp.plugins.songs.forms.editsongform.EditSongForm.__init__'): patch('openlp.plugins.songs.forms.editsongform.EditSongForm.__init__'):
self.media_item = SongMediaItem(MagicMock(), MagicMock()) self.media_item = SongMediaItem(None, MagicMock())
fd, self.ini_file = mkstemp('.ini') fd, self.ini_file = mkstemp('.ini')
Settings().set_filename(self.ini_file) Settings().set_filename(self.ini_file)