Esempio n. 1
0
    def test_add_from_command_for_a_presentation(self):
        """
        Test the Service Item - adding a presentation
        """
        # GIVEN: A service item, a mocked icon and presentation data
        service_item = ServiceItem(None)
        presentation_name = 'test.pptx'
        image = MagicMock()
        display_title = 'DisplayTitle'
        notes = 'Note1\nNote2\n'
        frame = {
            'title': presentation_name,
            'image': image,
            'path': TEST_PATH,
            'display_title': display_title,
            'notes': notes,
            'thumbnail': image
        }

        # WHEN: adding presentation to service_item
        service_item.add_from_command(TEST_PATH, presentation_name, image,
                                      display_title, notes)

        # THEN: verify that it is setup as a Command and that the frame data matches
        assert service_item.service_item_type == ServiceItemType.Command, 'It should be a Command'
        assert service_item.get_frames()[0] == frame, 'Frames should match'
Esempio n. 2
0
    def test_add_from_command_for_a_presentation_thumb(
            self, mocked_get_section_data_path, mocked_image_manager):
        """
        Test the Service Item - adding a presentation, updating the thumb path & adding the thumb to image_manager
        """
        # GIVEN: A service item, a mocked AppLocation and presentation data
        mocked_get_section_data_path.return_value = Path(
            'mocked') / 'section' / 'path'
        service_item = ServiceItem(None)
        service_item.add_capability(ItemCapabilities.HasThumbnails)
        service_item.has_original_files = False
        service_item.name = 'presentations'
        presentation_name = 'test.pptx'
        thumb = Path('tmp') / 'test' / 'thumb.png'
        display_title = 'DisplayTitle'
        notes = 'Note1\nNote2\n'
        expected_thumb_path = Path('mocked') / 'section' / 'path' / 'thumbnails' / \
            md5_hash(str(TEST_PATH / presentation_name).encode('utf8')) / 'thumb.png'
        frame = {
            'title': presentation_name,
            'image': str(expected_thumb_path),
            'path': str(TEST_PATH),
            'display_title': display_title,
            'notes': notes,
            'thumbnail': str(expected_thumb_path)
        }

        # WHEN: adding presentation to service_item
        service_item.add_from_command(str(TEST_PATH), presentation_name, thumb,
                                      display_title, notes)

        # THEN: verify that it is setup as a Command and that the frame data matches
        assert service_item.service_item_type == ServiceItemType.Command, 'It should be a Command'
        assert service_item.get_frames()[0] == frame, 'Frames should match'
Esempio n. 3
0
    def test_service_item_load_song_and_audio_from_service(self):
        """
        Test the Service Item - adding a song slide from a saved service
        """
        # GIVEN: A new service item and a mocked add icon function
        service_item = ServiceItem(None)
        service_item.add_icon = MagicMock()
        FormattingTags.load_tags()

        # WHEN: We add a custom from a saved service
        line = convert_file_service_item(TEST_PATH,
                                         'serviceitem-song-linked-audio.osj')
        service_item.set_from_service(line, Path('/test/'))

        # THEN: We should get back a valid service item
        assert service_item.is_valid is True, 'The new service item should be valid'
        assert len(service_item.display_slides
                   ) == 6, 'The service item should have 6 display slides'
        assert len(service_item.capabilities
                   ) == 7, 'There should be 7 default custom item capabilities'
        assert 'Amazing Grace' == service_item.get_display_title(
        ), 'The title should be "Amazing Grace"'
        assert CLEANED_VERSE[:-1] == service_item.get_frames()[0]['text'], \
            'The returned text matches the input, except the last line feed'
        assert 'Amazing Grace! how sweet the s' == service_item.get_frame_title(0), \
            '"Amazing Grace! how sweet the s" has been returned as the title'
        assert '’Twas grace that taught my hea' == service_item.get_frame_title(1), \
            '"’Twas grace that taught my hea" has been returned as the title'
        assert Path('/test/amazing_grace.mp3') == service_item.background_audio[0], \
            '"/test/amazing_grace.mp3" should be in the background_audio list'
Esempio n. 4
0
    def test_service_item_basic(self):
        """
        Test the Service Item - basic test
        """
        # GIVEN: A new service item

        # WHEN: A service item is created (without a plugin)
        service_item = ServiceItem(None)

        # THEN: We should get back a valid service item
        assert service_item.is_valid is True, 'The new service item should be valid'
        assert service_item.missing_frames(
        ) is True, 'There should not be any frames in the service item'
Esempio n. 5
0
 def test_change_slide(self):
     """
     Test the change_slide method.
     """
     # GIVEN: A ServiceItem with two frames content.
     service_item = ServiceItem(None)
     service = read_service_from_file('serviceitem_image_3.osj')
     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.
     assert self.preview_widget.current_slide_number(
     ) == 1, 'The current slide number should  be 1.'
Esempio n. 6
0
    def test_auto_start_context_menu(self):
        """
        Test the context_menu() method with can auto start
        """
        # GIVEN: A service item added
        self.service_manager.setup_ui(self.service_manager)
        with patch('PyQt5.QtWidgets.QTreeWidget.itemAt') as mocked_item_at_method, \
                patch('PyQt5.QtWidgets.QWidget.mapToGlobal'), \
                patch('PyQt5.QtWidgets.QMenu.exec'):
            mocked_item = MagicMock()
            mocked_item.parent.return_value = None
            mocked_item_at_method.return_value = mocked_item
            # We want 1 to be returned for the position
            mocked_item.data.return_value = 1
            # A service item without capabilities.
            service_item = ServiceItem()
            service_item.add_capability(ItemCapabilities.CanAutoStartForLive)
            self.service_manager.service_items = [{
                'service_item': service_item
            }]
            q_point = None
            # Mocked actions.
            self.service_manager.edit_action.setVisible = MagicMock()
            self.service_manager.create_custom_action.setVisible = MagicMock()
            self.service_manager.maintain_action.setVisible = MagicMock()
            self.service_manager.notes_action.setVisible = MagicMock()
            self.service_manager.time_action.setVisible = MagicMock()
            self.service_manager.auto_start_action.setVisible = MagicMock()
            self.service_manager.rename_action.setVisible = MagicMock()

            # WHEN: Show the context menu.
            self.service_manager.context_menu(q_point)

            # THEN: The following actions should be not visible.
            self.service_manager.edit_action.setVisible.assert_called_once_with(False), \
                'The action should be set invisible.'
            self.service_manager.create_custom_action.setVisible.assert_called_once_with(False), \
                'The action should be set invisible.'
            self.service_manager.maintain_action.setVisible.assert_called_once_with(False), \
                'The action should be set invisible.'
            self.service_manager.notes_action.setVisible.assert_called_with(
                True), 'The action should be set visible.'
            self.service_manager.time_action.setVisible.assert_called_once_with(False), \
                'The action should be set invisible.'
            self.service_manager.auto_start_action.setVisible.assert_called_with(True), \
                'The action should be set visible.'
            self.service_manager.rename_action.setVisible.assert_called_once_with(False), \
                'The action should be set invisible.'
Esempio n. 7
0
    def test_build_song_footer_base_ccli(self):
        """
        Test build songs footer with basic song and a CCLI number
        """
        # GIVEN: A Song and a Service Item and a configured CCLI license
        mock_song = MagicMock()
        mock_song.title = 'My Song'
        mock_song.copyright = 'My copyright'
        mock_song.songbook_entries = []
        service_item = ServiceItem(None)
        self.settings.setValue('core/ccli number', '1234')

        # WHEN: I generate the Footer with default settings
        self.media_item.generate_footer(service_item, mock_song)

        # THEN: I get the following Array returned
        assert service_item.raw_footer == ['My Song', '© My copyright', 'CCLI License: 1234'], \
            'The array should be returned correctly with a song, an author, copyright and ccli'

        # WHEN: I amend the CCLI value
        self.settings.setValue('core/ccli number', '4321')
        self.media_item.generate_footer(service_item, mock_song)

        # THEN: I would get an amended footer string
        assert service_item.raw_footer == ['My Song', '© My copyright', 'CCLI License: 4321'], \
            'The array should be returned correctly with a song, an author, copyright and amended ccli'
Esempio n. 8
0
 def test_replace_service_item(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('serviceitem_image_3.osj')
     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.
     assert self.preview_widget.slide_count(
     ) == 2, 'The slide count should be 2.'
     assert self.preview_widget.current_slide_number(
     ) == 1, 'The current slide number should  be 1.'
Esempio n. 9
0
    def test_build_song_footer_base_songbook(self):
        """
        Test build songs footer with basic song and multiple songbooks
        """
        # GIVEN: A Song and a Service Item
        song = Song()
        song.title = 'My Song'
        song.alternate_title = ''
        song.copyright = 'My copyright'
        song.authors_songs = []
        song.songbook_entries = []
        song.alternate_title = ''
        song.topics = []
        song.ccli_number = ''
        book1 = MagicMock()
        book1.name = 'My songbook'
        book2 = MagicMock()
        book2.name = 'Thy songbook'
        song.songbookentries = []
        song.add_songbook_entry(book1, '12')
        song.add_songbook_entry(book2, '502A')
        service_item = ServiceItem(None)

        # WHEN: I generate the Footer with default settings
        self.media_item.generate_footer(service_item, song)

        # THEN: The songbook should be in the footer
        assert service_item.raw_footer == [
            'My Song', '© My copyright', 'My songbook #12, Thy songbook #502A'
        ]
Esempio n. 10
0
 def _setup(self, screen_ratio):
     """
     Set up the widget
     """
     self.setColumnCount(1)
     self.horizontalHeader().setVisible(False)
     self.setColumnWidth(0, self.parent().width())
     self.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
     self.setSelectionMode(QtWidgets.QAbstractItemView.SingleSelection)
     self.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
     self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
     self.setAlternatingRowColors(True)
     # Initialize variables.
     self.service_item = ServiceItem()
     self.screen_ratio = screen_ratio
     self.auto_row_height = 100
     # Connect signals
     self.verticalHeader().sectionResized.connect(self.row_resized)
Esempio n. 11
0
def test_build_song_footer_one_author_show_written_by(mocked_media_item):
    """
    Test build songs footer with basic song and one author
    """
    # GIVEN: A Song and a Service Item, mocked settings

    mocked_media_item.settings.value.side_effect = [False, "", "0"]

    with patch('mako.template.Template.render_unicode') as MockedRenderer:
        mock_song = MagicMock()
        mock_song.title = 'My Song'
        mock_song.alternate_title = ''
        mock_song.ccli_number = ''
        mock_song.authors_songs = []
        mock_author = MagicMock()
        mock_author.display_name = 'my author'
        mock_author_song = MagicMock()
        mock_author_song.author = mock_author
        mock_song.authors_songs.append(mock_author_song)
        mock_song.copyright = 'My copyright'
        mock_song.songbook_entries = []
        service_item = ServiceItem(None)

        # WHEN: I generate the Footer with default settings
        author_list = mocked_media_item.generate_footer(
            service_item, mock_song)

        # THEN: The mako function was called with the following arguments
        args = {
            'authors_translation': [],
            'authors_music_label': 'Music',
            'copyright': 'My copyright',
            'songbook_entries': [],
            'alternate_title': '',
            'topics': [],
            'authors_music_all': [],
            'authors_words_label': 'Words',
            'authors_music': [],
            'authors_words_music': [],
            'ccli_number': '',
            'authors_none_label': 'Written by',
            'title': 'My Song',
            'authors_words_music_label': 'Words and Music',
            'authors_none': ['my author'],
            'ccli_license_label': 'CCLI License',
            'authors_words': [],
            'ccli_license': '0',
            'authors_translation_label': 'Translation',
            'authors_words_all': []
        }
        MockedRenderer.assert_called_once_with(**args)
        assert author_list == [
            'my author'
        ], 'The author list should be returned correctly with one author'
Esempio n. 12
0
    def test_service_item_get_theme_data_song_level_global_fallback(self):
        """
        Test the service item - get theme data when set to song theme level
                                but the song and service theme don't exist
        """
        # GIVEN: A service item with a theme and theme level set to song
        service_item = ServiceItem(None)
        mocked_theme_manager = MagicMock()
        mocked_theme_manager.global_theme = 'global_theme'
        mocked_theme_manager.get_theme_data = Mock(
            side_effect=lambda value: value)
        Registry().register('theme_manager', mocked_theme_manager)
        Settings().setValue('servicemanager/service theme', 'service_theme')
        Settings().setValue('themes/theme level', ThemeLevel.Song)

        # WHEN: Get theme data is run
        theme = service_item.get_theme_data()

        # THEN: theme should be the global theme
        assert theme == mocked_theme_manager.global_theme
Esempio n. 13
0
    def test_service_load_inactive(self):
        """
        Test the service load in custom with a default service item
        """
        # GIVEN: An empty Service Item
        service_item = ServiceItem(None)

        # WHEN: I search for the custom in the database
        item = self.media_item.service_load(service_item)

        # THEN: the processing should be ignored
        assert item is None, 'The Service item is inactive so processing should be bypassed'
Esempio n. 14
0
    def test_service_item_get_theme_data_service_level_service_defined(self):
        """
        Test the service item - get theme data when set to service theme level
        """
        # GIVEN: A service item with a theme and theme level set to service
        service_item = ServiceItem(None)
        service_item.theme = 'song_theme'
        service_item.from_service = True
        mocked_theme_manager = MagicMock()
        mocked_theme_manager.global_theme = 'global_theme'
        mocked_theme_manager.get_theme_data = Mock(
            side_effect=lambda value: value)
        Registry().register('theme_manager', mocked_theme_manager)
        Settings().setValue('servicemanager/service theme', 'service_theme')
        Settings().setValue('themes/theme level', ThemeLevel.Service)

        # WHEN: Get theme data is run
        theme = service_item.get_theme_data()

        # THEN: theme should be the service theme
        assert theme == Settings().value('servicemanager/service theme')
Esempio n. 15
0
    def test_service_load_basic_custom_true(self):
        """
        Test the service load in custom with a default service item and a requirement to add to the database
        """
        # GIVEN: An empty Service Item and an active plugin
        service_item = ServiceItem(None)
        service_item.raw_footer = FOOTER
        self.media_item.plugin = MagicMock()
        self.media_item.plugin.status = PluginStatus.Active
        self.media_item.plugin.db_manager = MagicMock()
        self.media_item.plugin.db_manager.get_object_filtered = MagicMock()
        self.media_item.plugin.db_manager.get_object_filtered.return_value = None

        with patch('openlp.plugins.custom.lib.mediaitem.CustomSlide'):
            # WHEN: I search for the custom in the database
            self.media_item.add_custom_from_service = True
            self.media_item.create_from_service_item = MagicMock()
            self.media_item.service_load(service_item)

            # THEN: the item should not be added to the database.
            assert self.media_item.create_from_service_item.call_count == 1, \
                'The item should have been added to the database'
Esempio n. 16
0
    def test_add_from_command_without_display_title_and_notes(self):
        """
        Test the Service Item - add from command, but not presentation
        """
        # GIVEN: A new service item, a mocked icon and image data
        service_item = ServiceItem(None)
        image_name = 'test.img'
        image = MagicMock()
        frame = {
            'title': image_name,
            'image': image,
            'path': TEST_PATH,
            'display_title': None,
            'notes': None,
            'thumbnail': image
        }

        # WHEN: adding image to service_item
        service_item.add_from_command(TEST_PATH, image_name, image)

        # THEN: verify that it is setup as a Command and that the frame data matches
        assert service_item.service_item_type == ServiceItemType.Command, 'It should be a Command'
        assert service_item.get_frames()[0] == frame, 'Frames should match'
Esempio n. 17
0
    def test_build_song_footer_copyright_disabled(self):
        """
        Test building song footer without displaying the copyright symbol
        """
        # GIVEN: A Song and a Service Item; displaying the copyright symbol should be disabled by default
        mock_song = MagicMock()
        mock_song.title = 'My Song'
        mock_song.copyright = 'My copyright'
        mock_song.songbook_entries = []
        service_item = ServiceItem(None)

        # WHEN: I generate the Footer with default settings
        self.media_item.generate_footer(service_item, mock_song)

        # THEN: The copyright symbol should not be in the footer
        assert service_item.raw_footer == ['My Song', '© My copyright']
Esempio n. 18
0
 def test_build_context_menu(self):
     """
     Test the creation of a context menu from a null service item.
     """
     # GIVEN: A new service manager instance and a default service item.
     service_manager = ServiceManager(None)
     item = MagicMock()
     item.parent.return_value = False
     item.data.return_value = 0
     service_manager.service_manager_list = MagicMock()
     service_manager.service_manager_list.itemAt.return_value = item
     service_item = ServiceItem(None)
     service_manager.service_items.insert(1, {'service_item': service_item})
     service_manager.edit_action = MagicMock()
     service_manager.rename_action = MagicMock()
     service_manager.create_custom_action = MagicMock()
     service_manager.maintain_action = MagicMock()
     service_manager.notes_action = MagicMock()
     service_manager.time_action = MagicMock()
     service_manager.auto_start_action = MagicMock()
     service_manager.auto_play_slides_menu = MagicMock()
     service_manager.auto_play_slides_once = MagicMock()
     service_manager.auto_play_slides_loop = MagicMock()
     service_manager.timed_slide_interval = MagicMock()
     service_manager.theme_menu = MagicMock()
     service_manager.menu = MagicMock()
     # WHEN I define a context menu
     service_manager.context_menu(1)
     # THEN the following calls should have occurred.
     assert service_manager.edit_action.setVisible.call_count == 1, 'Should have been called once'
     assert service_manager.rename_action.setVisible.call_count == 1, 'Should have been called once'
     assert service_manager.create_custom_action.setVisible.call_count == 1, 'Should have been called once'
     assert service_manager.maintain_action.setVisible.call_count == 1, 'Should have been called once'
     assert service_manager.notes_action.setVisible.call_count == 1, 'Should have been called once'
     assert service_manager.time_action.setVisible.call_count == 1, 'Should have been called once'
     assert service_manager.auto_start_action.setVisible.call_count == 1, 'Should have been called once'
     assert service_manager.auto_play_slides_menu.menuAction().setVisible.call_count == 1, \
         'Should have been called once'
     assert service_manager.auto_play_slides_once.setChecked.call_count == 0, 'Should not be called'
     assert service_manager.auto_play_slides_loop.setChecked.call_count == 0, 'Should not be called'
     assert service_manager.timed_slide_interval.setChecked.call_count == 0, 'Should not be called'
     assert service_manager.theme_menu.menuAction().setVisible.call_count == 1, \
         'Should have been called once'
Esempio n. 19
0
    def test_controller_text(self):
        """
        Remote API Tests : test the controller text method can be called with a real service item
        """
        # GIVEN: A mocked service with a dummy service item
        line = convert_file_service_item(TEST_PATH, 'serviceitem_custom_1.osj')
        self.mocked_live_controller.service_item = ServiceItem(None)
        State().load_settings()
        State().add_service("media", 0)
        State().update_pre_conditions("media", True)
        State().flush_preconditions()
        self.mocked_live_controller.service_item.set_from_service(line)
        self.mocked_live_controller.service_item._create_slides()
        # WHEN: I trigger the method
        ret = controller_text("SomeText")

        # THEN: I get a basic set of results
        results = ret['results']
        assert isinstance(ret, dict)
        assert len(results['slides']) == 2
Esempio n. 20
0
 def test_build_presentation_non_pdf_context_menu(self):
     """
     Test the creation of a context menu from service item of type Command with Impress from Presentation.
     """
     # GIVEN: A new service manager instance and a default service item.
     Registry().register('plugin_manager', MagicMock())
     Registry().register('renderer', MagicMock())
     service_manager = ServiceManager(None)
     item = MagicMock()
     item.parent.return_value = False
     item.data.return_value = 0
     service_manager.service_manager_list = MagicMock()
     service_manager.service_manager_list.itemAt.return_value = item
     service_item = ServiceItem(None)
     service_item.add_capability(ItemCapabilities.ProvidesOwnDisplay)
     service_item.service_item_type = ServiceItemType.Command
     service_item.edit_id = 1
     service_item.slides.append(MagicMock())
     service_manager.service_items.insert(1, {'service_item': service_item})
     service_manager.edit_action = MagicMock()
     service_manager.rename_action = MagicMock()
     service_manager.create_custom_action = MagicMock()
     service_manager.maintain_action = MagicMock()
     service_manager.notes_action = MagicMock()
     service_manager.time_action = MagicMock()
     service_manager.auto_start_action = MagicMock()
     service_manager.auto_play_slides_menu = MagicMock()
     service_manager.auto_play_slides_once = MagicMock()
     service_manager.auto_play_slides_loop = MagicMock()
     service_manager.timed_slide_interval = MagicMock()
     service_manager.theme_menu = MagicMock()
     service_manager.menu = MagicMock()
     # WHEN I define a context menu
     service_manager.context_menu(1)
     # THEN the following calls should have occurred.
     assert service_manager.edit_action.setVisible.call_count == 1, 'Should have be called once'
     assert service_manager.rename_action.setVisible.call_count == 1, 'Should have be called once'
     assert service_manager.create_custom_action.setVisible.call_count == 1, 'Should have be called once'
     assert service_manager.maintain_action.setVisible.call_count == 1, 'Should have be called once'
     assert service_manager.notes_action.setVisible.call_count == 1, 'Should have be called once'
     assert service_manager.time_action.setVisible.call_count == 1, 'Should have be called once'
     assert service_manager.auto_start_action.setVisible.call_count == 1, 'Should have be called once'
     assert service_manager.auto_play_slides_menu.menuAction().setVisible.call_count == 1, \
         'Should have be called once'
     assert service_manager.auto_play_slides_once.setChecked.call_count == 0, 'Should not be called'
     assert service_manager.auto_play_slides_loop.setChecked.call_count == 0, 'Should not be called'
     assert service_manager.timed_slide_interval.setChecked.call_count == 0, 'Should not be called'
     assert service_manager.theme_menu.menuAction().setVisible.call_count == 1, \
         'Should have be called once'
Esempio n. 21
0
    def test_build_song_footer_two_authors(self):
        """
        Test build songs footer with basic song and two authors
        """
        # GIVEN: A Song and a Service Item
        mock_song = MagicMock()
        mock_song.title = 'My Song'
        mock_song.authors_songs = []
        mock_author = MagicMock()
        mock_author.display_name = 'my author'
        mock_author_song = MagicMock()
        mock_author_song.author = mock_author
        mock_author_song.author_type = AuthorType.Music
        mock_song.authors_songs.append(mock_author_song)
        mock_author = MagicMock()
        mock_author.display_name = 'another author'
        mock_author_song = MagicMock()
        mock_author_song.author = mock_author
        mock_author_song.author_type = AuthorType.Words
        mock_song.authors_songs.append(mock_author_song)
        mock_author = MagicMock()
        mock_author.display_name = 'translator'
        mock_author_song = MagicMock()
        mock_author_song.author = mock_author
        mock_author_song.author_type = AuthorType.Translation
        mock_song.authors_songs.append(mock_author_song)
        mock_song.copyright = 'My copyright'
        mock_song.songbook_entries = []
        service_item = ServiceItem(None)

        # WHEN: I generate the Footer with default settings
        author_list = self.media_item.generate_footer(service_item, mock_song)

        # THEN: I get the following Array returned
        assert service_item.raw_footer == ['My Song', 'Words: another author', 'Music: my author',
                                           'Translation: translator', '© My copyright'], \
            'The array should be returned correctly with a song, two authors and copyright'
        assert author_list == ['another author', 'my author', 'translator'], \
            'The author list should be returned correctly with two authors'
Esempio n. 22
0
    def test_default_context_menu(self, mocked_exec, mocked_mapToGlobal,
                                  mocked_item_at_method):
        """
        Test the context_menu() method with a default service item
        """
        # GIVEN: A service item added
        mocked_item = MagicMock()
        mocked_item.parent.return_value = None
        mocked_item_at_method.return_value = mocked_item
        mocked_item.data.return_value = 1
        self.service_manager.setup_ui(self.service_manager)
        # A service item without capabilities.
        service_item = ServiceItem()
        self.service_manager.service_items = [{'service_item': service_item}]
        q_point = None
        # Mocked actions.
        self.service_manager.edit_action.setVisible = MagicMock()
        self.service_manager.create_custom_action.setVisible = MagicMock()
        self.service_manager.maintain_action.setVisible = MagicMock()
        self.service_manager.notes_action.setVisible = MagicMock()
        self.service_manager.time_action.setVisible = MagicMock()
        self.service_manager.auto_start_action.setVisible = MagicMock()

        # WHEN: Show the context menu.
        self.service_manager.context_menu(q_point)

        # THEN: The following actions should be not visible.
        self.service_manager.edit_action.setVisible.assert_called_once_with(False), \
            'The action should be set invisible.'
        self.service_manager.create_custom_action.setVisible.assert_called_once_with(False), \
            'The action should be set invisible.'
        self.service_manager.maintain_action.setVisible.assert_called_once_with(False), \
            'The action should be set invisible.'
        self.service_manager.notes_action.setVisible.assert_called_with(
            True), 'The action should be set visible.'
        self.service_manager.time_action.setVisible.assert_called_once_with(False), \
            'The action should be set invisible.'
        self.service_manager.auto_start_action.setVisible.assert_called_once_with(False), \
            'The action should be set invisible.'
Esempio n. 23
0
    def test_service_item_load_optical_media_from_service(self):
        """
        Test the Service Item - load an optical media item
        """
        # GIVEN: A new service item and a mocked add icon function
        service_item = ServiceItem(None)
        service_item.add_icon = MagicMock()

        # WHEN: We load a serviceitem with optical media
        line = convert_file_service_item(TEST_PATH, 'serviceitem-dvd.osj')
        with patch('openlp.core.ui.servicemanager.os.path.exists'
                   ) as mocked_exists:
            mocked_exists.return_value = True
            service_item.set_from_service(line)

        # THEN: We should get back a valid service item with optical media info
        assert service_item.is_valid is True, 'The service item should be valid'
        assert service_item.is_capable(
            ItemCapabilities.IsOptical) is True, 'The item should be Optical'
        assert service_item.start_time == 654.375, 'Start time should be 654.375'
        assert service_item.end_time == 672.069, 'End time should be 672.069'
        assert service_item.media_length == 17.694, 'Media length should be 17.694'
Esempio n. 24
0
    def test_service_item_load_custom_from_service(self):
        """
        Test the Service Item - adding a custom slide from a saved service
        """
        # GIVEN: A new service item and a mocked add icon function
        service_item = ServiceItem(None)
        service_item.add_icon = MagicMock()
        FormattingTags.load_tags()

        # WHEN: We add a custom from a saved serviceand set the media state
        line = convert_file_service_item(TEST_PATH, 'serviceitem_custom_1.osj')
        State().add_service("media", 0)
        State().update_pre_conditions("media", True)
        State().flush_preconditions()
        service_item.set_from_service(line)

        # THEN: We should get back a valid service item
        assert service_item.is_valid is True, 'The new service item should be valid'
        assert len(service_item.get_frames()
                   ) == 2, 'The service item should have 2 display frames'
        assert len(service_item.capabilities
                   ) == 5, 'There should be 5 default custom item capabilities'

        # THEN: The frames should also be valid
        assert 'Test Custom' == service_item.get_display_title(
        ), 'The title should be "Test Custom"'
        assert 'Slide 1' == service_item.get_frames()[0]['text']
        assert 'Slide 2' == service_item.get_rendered_frame(1)
        assert 'Slide 1' == service_item.get_frame_title(
            0), '"Slide 1" has been returned as the title'
        assert 'Slide 2' == service_item.get_frame_title(
            1), '"Slide 2" has been returned as the title'
        assert '' == service_item.get_frame_title(
            2), 'Blank has been returned as the title of slide 3'
Esempio n. 25
0
    def test_service_item_load_image_from_local_service(
            self, mocked_get_section_data_path, mocked_exists):
        """
        Test the Service Item - adding an image from a saved local service
        """
        # GIVEN: A new service item and a mocked add icon function
        mocked_get_section_data_path.return_value = Path('/path')
        mocked_exists.return_value = True
        image_name1 = 'image_1.jpg'
        image_name2 = 'image_2.jpg'
        test_file1 = os.path.join('/home', 'openlp', image_name1)
        test_file2 = os.path.join('/home', 'openlp', image_name2)
        frame_array1 = {'path': test_file1, 'title': image_name1}
        frame_array2 = {'path': test_file2, 'title': image_name2}
        service_item = ServiceItem(None)
        service_item.add_icon = MagicMock()
        service_item2 = ServiceItem(None)
        service_item2.add_icon = MagicMock()

        # WHEN: adding an image from a saved Service and mocked exists
        line = convert_file_service_item(TEST_PATH, 'serviceitem_image_2.osj')
        line2 = convert_file_service_item(TEST_PATH, 'serviceitem_image_2.osj',
                                          1)
        service_item2.set_from_service(line2)
        service_item.set_from_service(line)

        # THEN: We should get back a valid service item
        assert service_item.is_valid is True, 'The first service item should be valid'
        assert service_item2.is_valid is True, 'The second service item should be valid'
        # These test will fail on windows due to the difference in folder seperators
        if os.name != 'nt':
            assert test_file1 == service_item.get_rendered_frame(0), \
                'The first frame should match the path to the image'
            assert test_file2 == service_item2.get_rendered_frame(0), \
                'The Second frame should match the path to the image'
            assert frame_array1 == service_item.get_frames(
            )[0], 'The return should match the frame array1'
            assert frame_array2 == service_item2.get_frames(
            )[0], 'The return should match the frame array2'
            assert test_file1 == str(service_item.get_frame_path(0)), \
                'The frame path should match the full path to the image'
            assert test_file2 == str(service_item2.get_frame_path(0)), \
                'The frame path should match the full path to the image'
        assert image_name1 == service_item.get_frame_title(
            0), 'The 1st frame title should match the image name'
        assert image_name2 == service_item2.get_frame_title(
            0), 'The 2nd frame title should match the image name'
        assert service_item.name == service_item.title.lower(), \
            'The plugin name should match the display title, as there are > 1 Images'
        assert service_item.is_image(
        ) is True, 'This service item should be of an "image" type'
        assert service_item.is_capable(ItemCapabilities.CanMaintain) is True, \
            'This service item should be able to be Maintained'
        assert service_item.is_capable(ItemCapabilities.CanPreview) is True, \
            'This service item should be able to be be Previewed'
        assert service_item.is_capable(ItemCapabilities.CanLoop) is True, \
            'This service item should be able to be run in a can be made to Loop'
        assert service_item.is_capable(ItemCapabilities.CanAppend) is True, \
            'This service item should be able to have new items added to it'
Esempio n. 26
0
class ListPreviewWidget(QtWidgets.QTableWidget, RegistryProperties):
    """
    A special type of QTableWidget which lists the slides in the slide controller

    :param parent:
    :param screen_ratio:
    """
    def __init__(self, parent, screen_ratio):
        """
        Initializes the widget to default state.

        An empty ``ServiceItem`` is used by default. replace_service_manager_item() needs to be called to make this
        widget display something.
        """
        super().__init__(parent)
        self._setup(screen_ratio)

    def _setup(self, screen_ratio):
        """
        Set up the widget
        """
        self.setColumnCount(1)
        self.horizontalHeader().setVisible(False)
        self.setColumnWidth(0, self.parent().width())
        self.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
        self.setSelectionMode(QtWidgets.QAbstractItemView.SingleSelection)
        self.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
        self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
        self.setAlternatingRowColors(True)
        # Initialize variables.
        self.service_item = ServiceItem()
        self.screen_ratio = screen_ratio
        self.auto_row_height = 100
        # Connect signals
        self.verticalHeader().sectionResized.connect(self.row_resized)

    def resizeEvent(self, event):
        """
        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()
            # Sort out image heights.
            else:
                height = self.viewport().width() // self.screen_ratio
                max_img_row_height = Settings().value(
                    'advanced/slide max height')
                # Adjust for row height cap if in use.
                if isinstance(max_img_row_height, int):
                    if 0 < max_img_row_height < height:
                        height = max_img_row_height
                    elif max_img_row_height < 0:
                        # If auto setting, show that number of slides, or if the resulting slides too small, 100px.
                        # E.g. If setting is -4, 4 slides will be visible, unless those slides are < 100px high.
                        self.auto_row_height = max(
                            self.viewport().height() /
                            (-1 * max_img_row_height), 100)
                        height = min(height, self.auto_row_height)
                # Apply new height to slides
                for slide_index in range(len(self.service_item.slides)):
                    self.setRowHeight(slide_index, height)

    def row_resized(self, row, old_height, new_height):
        """
        Will scale non-image slides.
        """
        # Only for non-text slides when row height cap in use
        max_img_row_height = Settings().value('advanced/slide max height')
        if self.service_item.is_text() or not isinstance(
                max_img_row_height, int) or max_img_row_height == 0:
            return
        # Get and validate label widget containing slide & adjust max width
        try:
            self.cellWidget(row, 0).children()[1].setMaximumWidth(
                new_height * self.screen_ratio)
        except Exception:
            return

    def screen_size_changed(self, screen_ratio):
        """
        This method is called whenever the live screen size changes, which then makes a layout recalculation necessary

        :param screen_ratio: The new screen ratio
        """
        self.screen_ratio = screen_ratio
        self.__recalculate_layout()

    def clear_list(self):
        """
        Clear the preview list
        :return:
        """
        self.setRowCount(0)
        self.clear()

    def replace_service_item(self, service_item, width, slide_number):
        """
        Replace the current preview items with the ones in service_item and display the given slide

        :param service_item: The service item to insert
        :param width: The width of the column
        :param slide_number: The slide number to pre-select
        """
        self.service_item = service_item
        self.setRowCount(0)
        self.clear_list()
        row = 0
        text = []
        slides = self.service_item.display_slides if self.service_item.is_text(
        ) else self.service_item.slides
        for slide_index, slide in enumerate(slides):
            self.setRowCount(self.slide_count() + 1)
            item = QtWidgets.QTableWidgetItem()
            slide_height = 0
            if self.service_item.is_text():
                if slide['verse']:
                    # These tags are already translated.
                    verse_def = slide['verse']
                    verse_def = '%s%s' % (verse_def[0], verse_def[1:])
                    two_line_def = '%s\n%s' % (verse_def[0], verse_def[1:])
                    row = two_line_def
                else:
                    row += 1
                item.setText(slide['text'])
            else:
                label = QtWidgets.QLabel()
                label.setContentsMargins(4, 4, 4, 4)
                label.setAlignment(QtCore.Qt.AlignCenter)
                if not self.service_item.is_media():
                    label.setScaledContents(True)
                if self.service_item.is_command():
                    if self.service_item.is_capable(
                            ItemCapabilities.HasThumbnails):
                        pixmap = QtGui.QPixmap(str(slide['thumbnail']))
                    else:
                        if isinstance(slide['image'], QtGui.QIcon):
                            pixmap = slide['image'].pixmap(QtCore.QSize(
                                32, 32))
                        else:
                            pixmap = QtGui.QPixmap(str(slide['image']))
                else:
                    pixmap = QtGui.QPixmap(str(slide['path']))
                if pixmap.height() > 0:
                    pixmap_ratio = pixmap.width() / pixmap.height()
                else:
                    pixmap_ratio = 1
                label.setPixmap(pixmap)
                container = QtWidgets.QWidget()
                layout = AspectRatioLayout(container, pixmap_ratio)
                layout.setContentsMargins(0, 0, 0, 0)
                layout.addWidget(label)
                container.setLayout(layout)
                slide_height = width // self.screen_ratio
                max_img_row_height = Settings().value(
                    'advanced/slide max height')
                if isinstance(max_img_row_height, int):
                    if 0 < max_img_row_height < slide_height:
                        slide_height = max_img_row_height
                    elif max_img_row_height < 0:
                        # If auto setting, show that number of slides, or if the resulting slides too small, 100px.
                        # E.g. If setting is -4, 4 slides will be visible, unless those slides are < 100px high.
                        self.auto_row_height = max(
                            self.viewport().height() /
                            (-1 * max_img_row_height), 100)
                        slide_height = min(slide_height, self.auto_row_height)
                self.setCellWidget(slide_index, 0, container)
                row += 1
            text.append(str(row))
            self.setItem(slide_index, 0, item)
            if slide_height:
                # First set the height to 1 and then to the right height. This makes the item display correctly.
                # If this is not done, sometimes the image item is displayed as blank.
                self.setRowHeight(slide_index, 1)
                self.setRowHeight(slide_index, slide_height)
        self.setVerticalHeaderLabels(text)
        if self.service_item.is_text():
            self.resizeRowsToContents()
        self.setColumnWidth(0, self.viewport().width())
        self.change_slide(slide_number)

    def change_slide(self, slide):
        """
        Switches to the given row.
        """
        # Retrieve setting
        auto_scrolling = Settings().value('advanced/autoscrolling')
        # Check if auto-scroll disabled (None) and validate value as dict containing 'dist' and 'pos'
        # 'dist' represents the slide to scroll to relative to the new slide (-1 = previous, 0 = current, 1 = next)
        # 'pos' represents the vert position of of the slide (0 = in view, 1 = top, 2 = middle, 3 = bottom)
        if not (isinstance(auto_scrolling, dict) and 'dist' in auto_scrolling
                and 'pos' in auto_scrolling
                and isinstance(auto_scrolling['dist'], int)
                and isinstance(auto_scrolling['pos'], int)):
            return
        # prevent scrolling past list bounds
        scroll_to_slide = slide + auto_scrolling['dist']
        if scroll_to_slide < 0:
            scroll_to_slide = 0
        if scroll_to_slide >= self.slide_count():
            scroll_to_slide = self.slide_count() - 1
        # Scroll to item if possible.
        self.scrollToItem(self.item(scroll_to_slide, 0), auto_scrolling['pos'])
        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()
Esempio n. 27
0
    def test_service_item_load_image_from_service(self):
        """
        Test the Service Item - adding an image from a saved service
        """
        # GIVEN: A new service item and a mocked add icon function
        image_name = 'image_1.jpg'
        test_file = TEST_PATH / image_name
        frame_array = {'path': test_file, 'title': image_name}

        service_item = ServiceItem(None)
        service_item.add_icon = MagicMock()

        # WHEN: adding an image from a saved Service and mocked exists
        line = convert_file_service_item(TEST_PATH, 'serviceitem_image_1.osj')
        with patch('openlp.core.ui.servicemanager.os.path.exists') as mocked_exists,\
                patch('openlp.core.lib.serviceitem.AppLocation.get_section_data_path') as \
                mocked_get_section_data_path:
            mocked_exists.return_value = True
            mocked_get_section_data_path.return_value = Path('/path/')
            service_item.set_from_service(line, TEST_PATH)

        # THEN: We should get back a valid service item
        assert service_item.is_valid is True, 'The new service item should be valid'
        assert test_file == service_item.get_rendered_frame(
            0), 'The first frame should match the path to the image'
        assert frame_array == service_item.get_frames(
        )[0], 'The return should match frame array1'
        assert test_file == service_item.get_frame_path(0), \
            'The frame path should match the full path to the image'
        assert image_name == service_item.get_frame_title(
            0), 'The frame title should match the image name'
        assert image_name == service_item.get_display_title(
        ), 'The display title should match the first image name'
        assert service_item.is_image(
        ) is True, 'This service item should be of an "image" type'
        assert service_item.is_capable(ItemCapabilities.CanMaintain) is True, \
            'This service item should be able to be Maintained'
        assert service_item.is_capable(ItemCapabilities.CanPreview) is True, \
            'This service item should be able to be be Previewed'
        assert service_item.is_capable(ItemCapabilities.CanLoop) is True, \
            'This service item should be able to be run in a can be made to Loop'
        assert service_item.is_capable(ItemCapabilities.CanAppend) is True, \
            'This service item should be able to have new items added to it'
Esempio n. 28
0
 def test_build_custom_context_menu(self):
     """
     Test the creation of a context menu from service item of type text from Custom.
     """
     # GIVEN: A new service manager instance and a default service item.
     mocked_renderer = MagicMock()
     mocked_renderer.theme_level = ThemeLevel.Song
     Registry().register('plugin_manager', MagicMock())
     Registry().register('renderer', mocked_renderer)
     service_manager = ServiceManager(None)
     item = MagicMock()
     item.parent.return_value = False
     item.data.return_value = 0
     service_manager.service_manager_list = MagicMock()
     service_manager.service_manager_list.itemAt.return_value = item
     service_item = ServiceItem(None)
     service_item.add_capability(ItemCapabilities.CanEdit)
     service_item.add_capability(ItemCapabilities.CanPreview)
     service_item.add_capability(ItemCapabilities.CanLoop)
     service_item.add_capability(ItemCapabilities.CanSoftBreak)
     service_item.add_capability(ItemCapabilities.OnLoadUpdate)
     service_item.service_item_type = ServiceItemType.Text
     service_item.edit_id = 1
     service_item._display_slides = []
     service_item._display_slides.append(MagicMock())
     service_manager.service_items.insert(1, {'service_item': service_item})
     service_manager.edit_action = MagicMock()
     service_manager.rename_action = MagicMock()
     service_manager.create_custom_action = MagicMock()
     service_manager.maintain_action = MagicMock()
     service_manager.notes_action = MagicMock()
     service_manager.time_action = MagicMock()
     service_manager.auto_start_action = MagicMock()
     service_manager.auto_play_slides_menu = MagicMock()
     service_manager.auto_play_slides_once = MagicMock()
     service_manager.auto_play_slides_loop = MagicMock()
     service_manager.timed_slide_interval = MagicMock()
     service_manager.theme_menu = MagicMock()
     service_manager.menu = MagicMock()
     # WHEN I define a context menu
     service_manager.context_menu(1)
     # THEN the following calls should have occurred.
     assert service_manager.edit_action.setVisible.call_count == 2, 'Should have be called twice'
     assert service_manager.rename_action.setVisible.call_count == 1, 'Should have be called once'
     assert service_manager.create_custom_action.setVisible.call_count == 1, 'Should have be called once'
     assert service_manager.maintain_action.setVisible.call_count == 1, 'Should have be called once'
     assert service_manager.notes_action.setVisible.call_count == 1, 'Should have be called once'
     assert service_manager.time_action.setVisible.call_count == 1, 'Should have be called once'
     assert service_manager.auto_start_action.setVisible.call_count == 1, 'Should have be called once'
     assert service_manager.auto_play_slides_menu.menuAction().setVisible.call_count == 1, \
         'Should have be called once'
     assert service_manager.auto_play_slides_once.setChecked.call_count == 0, 'Should not be called'
     assert service_manager.auto_play_slides_loop.setChecked.call_count == 0, 'Should not be called'
     assert service_manager.timed_slide_interval.setChecked.call_count == 0, 'Should not be called'
     assert service_manager.theme_menu.menuAction().setVisible.call_count == 2, \
         'Should have be called twice'
     # THEN we add a 2nd display frame
     service_item._display_slides.append(MagicMock())
     service_manager.context_menu(1)
     # THEN the following additional calls should have occurred.
     assert service_manager.auto_play_slides_menu.menuAction().setVisible.call_count == 2, \
         'Should have be called twice'
     assert service_manager.auto_play_slides_once.setChecked.call_count == 1, 'Should have be called once'
     assert service_manager.auto_play_slides_loop.setChecked.call_count == 1, 'Should have be called once'
     assert service_manager.timed_slide_interval.setChecked.call_count == 1, 'Should have be called once'
Esempio n. 29
0
 def test_build_media_context_menu(self):
     """
     Test the creation of a context menu from service item of type Command from Media.
     """
     # GIVEN: A new service manager instance and a default service item.
     Registry().register('plugin_manager', MagicMock())
     Registry().register('renderer', MagicMock())
     service_manager = ServiceManager(None)
     item = MagicMock()
     item.parent.return_value = False
     item.data.return_value = 0
     service_manager.service_manager_list = MagicMock()
     service_manager.service_manager_list.itemAt.return_value = item
     service_item = ServiceItem(None)
     service_item.add_capability(ItemCapabilities.CanAutoStartForLive)
     service_item.add_capability(ItemCapabilities.CanEditTitle)
     service_item.add_capability(ItemCapabilities.RequiresMedia)
     service_item.service_item_type = ServiceItemType.Command
     service_item.edit_id = 1
     service_item.slides.append(MagicMock())
     service_manager.service_items.insert(1, {'service_item': service_item})
     service_manager.edit_action = MagicMock()
     service_manager.rename_action = MagicMock()
     service_manager.create_custom_action = MagicMock()
     service_manager.maintain_action = MagicMock()
     service_manager.notes_action = MagicMock()
     service_manager.time_action = MagicMock()
     service_manager.auto_start_action = MagicMock()
     service_manager.auto_play_slides_menu = MagicMock()
     service_manager.auto_play_slides_once = MagicMock()
     service_manager.auto_play_slides_loop = MagicMock()
     service_manager.timed_slide_interval = MagicMock()
     service_manager.theme_menu = MagicMock()
     service_manager.menu = MagicMock()
     # WHEN I define a context menu
     service_manager.context_menu(1)
     # THEN the following calls should have occurred.
     assert service_manager.edit_action.setVisible.call_count == 1, 'Should have be called once'
     assert service_manager.rename_action.setVisible.call_count == 2, 'Should have be called twice'
     assert service_manager.create_custom_action.setVisible.call_count == 1, 'Should have be called once'
     assert service_manager.maintain_action.setVisible.call_count == 1, 'Should have be called once'
     assert service_manager.notes_action.setVisible.call_count == 1, 'Should have be called once'
     assert service_manager.time_action.setVisible.call_count == 1, 'Should have be called once'
     assert service_manager.auto_start_action.setVisible.call_count == 2, 'Should have be called twice'
     assert service_manager.auto_play_slides_menu.menuAction().setVisible.call_count == 1, \
         'Should have be called once'
     assert service_manager.auto_play_slides_once.setChecked.call_count == 0, 'Should not be called'
     assert service_manager.auto_play_slides_loop.setChecked.call_count == 0, 'Should not be called'
     assert service_manager.timed_slide_interval.setChecked.call_count == 0, 'Should not be called'
     assert service_manager.theme_menu.menuAction().setVisible.call_count == 1, \
         'Should have be called once'
     # THEN I change the length of the media and regenerate the menu.
     service_item.set_media_length(5)
     service_manager.context_menu(1)
     # THEN the following additional calls should have occurred.
     assert service_manager.time_action.setVisible.call_count == 3, 'Should have be called three times'