diff --git a/openlp/core/common/settings.py b/openlp/core/common/settings.py index a3804c1c0..8fa15abca 100644 --- a/openlp/core/common/settings.py +++ b/openlp/core/common/settings.py @@ -213,6 +213,7 @@ class Settings(QtCore.QSettings): 'bibles/second bibles': True, 'bibles/status': PluginStatus.Inactive, 'bibles/primary bible': '', + 'bibles/second bible': None, 'bibles/bible theme': '', 'bibles/verse separator': '', 'bibles/range separator': '', diff --git a/openlp/plugins/bibles/lib/biblestab.py b/openlp/plugins/bibles/lib/biblestab.py index 9347d8c47..502424f50 100644 --- a/openlp/plugins/bibles/lib/biblestab.py +++ b/openlp/plugins/bibles/lib/biblestab.py @@ -366,41 +366,45 @@ class BiblesTab(SettingsTab): self.layout_style_combo_box.setCurrentIndex(self.layout_style) self.bible_second_check_box.setChecked(self.second_bibles) verse_separator = self.settings.value('bibles/verse separator') - if (verse_separator.strip('|') == '') or (verse_separator == get_reference_separator('sep_v_default')): + if verse_separator.strip('|') == '': self.verse_separator_line_edit.setText(get_reference_separator('sep_v_default')) self.verse_separator_line_edit.setPalette(self.get_grey_text_palette(True)) self.verse_separator_check_box.setChecked(False) else: self.verse_separator_line_edit.setText(verse_separator) self.verse_separator_line_edit.setPalette(self.get_grey_text_palette(False)) - self.verse_separator_check_box.setChecked(True) + verse_separator_set = self.settings.contains('bibles/verse separator') + self.verse_separator_check_box.setChecked(verse_separator_set) range_separator = self.settings.value('bibles/range separator') - if (range_separator.strip('|') == '') or (range_separator == get_reference_separator('sep_r_default')): + if range_separator.strip('|') == '': self.range_separator_line_edit.setText(get_reference_separator('sep_r_default')) self.range_separator_line_edit.setPalette(self.get_grey_text_palette(True)) self.range_separator_check_box.setChecked(False) else: self.range_separator_line_edit.setText(range_separator) self.range_separator_line_edit.setPalette(self.get_grey_text_palette(False)) - self.range_separator_check_box.setChecked(True) + range_separator_set = self.settings.contains('bibles/range separator') + self.range_separator_check_box.setChecked(range_separator_set) list_separator = self.settings.value('bibles/list separator') - if (list_separator.strip('|') == '') or (list_separator == get_reference_separator('sep_l_default')): + if list_separator.strip('|') == '': self.list_separator_line_edit.setText(get_reference_separator('sep_l_default')) self.list_separator_line_edit.setPalette(self.get_grey_text_palette(True)) self.list_separator_check_box.setChecked(False) else: self.list_separator_line_edit.setText(list_separator) self.list_separator_line_edit.setPalette(self.get_grey_text_palette(False)) - self.list_separator_check_box.setChecked(True) + list_separator_set = self.settings.contains('bibles/list separator') + self.list_separator_check_box.setChecked(list_separator_set) end_separator = self.settings.value('bibles/end separator') - if (end_separator.strip('|') == '') or (end_separator == get_reference_separator('sep_e_default')): + if end_separator.strip('|') == '': self.end_separator_line_edit.setText(get_reference_separator('sep_e_default')) self.end_separator_line_edit.setPalette(self.get_grey_text_palette(True)) self.end_separator_check_box.setChecked(False) else: self.end_separator_line_edit.setText(end_separator) self.end_separator_line_edit.setPalette(self.get_grey_text_palette(False)) - self.end_separator_check_box.setChecked(True) + end_separator_set = self.settings.contains('bibles/end separator') + self.end_separator_check_box.setChecked(end_separator_set) self.language_selection = self.settings.value('bibles/book name language') self.language_selection_combo_box.setCurrentIndex(self.language_selection) self.reset_to_combined_quick_search = self.settings.value('bibles/reset to combined quick search') diff --git a/openlp/plugins/bibles/lib/mediaitem.py b/openlp/plugins/bibles/lib/mediaitem.py index 4ece90568..acfc75403 100755 --- a/openlp/plugins/bibles/lib/mediaitem.py +++ b/openlp/plugins/bibles/lib/mediaitem.py @@ -329,6 +329,8 @@ class BibleMediaItem(MediaManagerItem): :return: None """ log.debug('Loading Bibles') + self.version_combo_box.blockSignals(True) + self.second_combo_box.blockSignals(True) self.version_combo_box.clear() self.second_combo_box.clear() self.second_combo_box.addItem('', None) @@ -336,14 +338,16 @@ class BibleMediaItem(MediaManagerItem): bibles = self.plugin.manager.get_bibles() bibles = [(_f, bibles[_f]) for _f in bibles if _f] bibles.sort(key=lambda k: get_locale_key(k[0])) - self.version_combo_box.blockSignals(True) for bible in bibles: self.version_combo_box.addItem(bible[0], bible[1]) self.second_combo_box.addItem(bible[0], bible[1]) self.version_combo_box.blockSignals(False) + self.second_combo_box.blockSignals(False) # set the default value bible = self.settings.value('bibles/primary bible') + second_bible = self.settings.value('bibles/second bible') find_and_set_in_combo_box(self.version_combo_box, bible) + find_and_set_in_combo_box(self.second_combo_box, second_bible) # make sure the selected bible ripples down to other gui elements self.on_version_combo_box_index_changed() @@ -591,8 +595,10 @@ class BibleMediaItem(MediaManagerItem): self.second_bible = new_selection if new_selection is None: self.style_combo_box.setEnabled(True) + self.settings.setValue('bibles/second bible', None) else: self.style_combo_box.setEnabled(False) + self.settings.setValue('bibles/second bible', self.second_bible.name) self.initialise_advanced_bible(self.select_book_combo_box.currentData()) def on_advanced_book_combo_box(self): @@ -729,7 +735,7 @@ class BibleMediaItem(MediaManagerItem): verse_refs = self.plugin.manager.parse_ref(self.bible.name, search_text) self.search_results = self.plugin.manager.get_verses(self.bible.name, verse_refs, True) if self.second_bible and self.search_results: - self.search_results = self.plugin.manager.get_verses(self.second_bible.name, verse_refs, True) + self.second_search_results = self.plugin.manager.get_verses(self.second_bible.name, verse_refs, True) self.display_results() def on_text_search(self, text): @@ -909,7 +915,7 @@ class BibleMediaItem(MediaManagerItem): Generate the slide data. Needs to be implemented by the plugin. :param service_item: The service item to be built on - :param item: The Song item to be used + :param item: The Bible items to be used :param remote: Triggered from remote :param context: Why is it being generated :param kwargs: Consume other unused args specified by the base implementation, but not use by this one. @@ -950,6 +956,24 @@ class BibleMediaItem(MediaManagerItem): bible_text = '{bible} {verse}{data[text]}'.format(bible=bible_text, verse=verse_text, data=data) bible_text = bible_text.strip(' ') old_chapter = data['chapter'] + # Add service item data (handy things for http api) + # Bibles in array to make api compatible with any number of bibles. + bibles = [] + if data['version']: + bibles.append({ + 'version': data['version'], + 'copyright': data['copyright'], + 'permissions': data['permissions'] + }) + if data['second_bible']: + bibles.append({ + 'version': data['second_version'], + 'copyright': data['second_copyright'], + 'permissions': data['second_permissions'] + }) + service_item.data_string = { + 'bibles': bibles + } # Add footer service_item.raw_footer.append(verses.format_verses()) if data['second_bible']: diff --git a/tests/functional/openlp_plugins/bibles/test_mediaitem.py b/tests/functional/openlp_plugins/bibles/test_mediaitem.py index 37ba7c325..ff9129609 100644 --- a/tests/functional/openlp_plugins/bibles/test_mediaitem.py +++ b/tests/functional/openlp_plugins/bibles/test_mediaitem.py @@ -322,23 +322,26 @@ def test_populate_bible_combo_boxes(media_item): bible_1 = MagicMock() bible_2 = MagicMock() bible_3 = MagicMock() - media_item.settings.value = lambda key: {'bibles/primary bible': bible_2}[key] + media_item.settings.value = lambda key: {'bibles/primary bible': bible_2, 'bibles/second bible': bible_3}[key] media_item.version_combo_box = MagicMock() media_item.second_combo_box = MagicMock() media_item.plugin.manager.get_bibles.return_value = \ {'Bible 2': bible_2, 'Bible 1': bible_1, 'Bible 3': bible_3} with patch('openlp.plugins.bibles.lib.mediaitem.get_locale_key', side_effect=lambda x: x), \ - patch('openlp.plugins.bibles.lib.mediaitem.find_and_set_in_combo_box'), \ + patch('openlp.plugins.bibles.lib.mediaitem.find_and_set_in_combo_box') as mocked_set_combo_box, \ patch.object(media_item, 'on_version_combo_box_index_changed'): # WHEN: Calling populate_bible_combo_boxes media_item.populate_bible_combo_boxes() # THEN: The bible combo boxes should be filled with the bible names and data, in a sorted order. + # Also check the correct combo box has been selected according to the settings media_item.version_combo_box.addItem.assert_has_calls( [call('Bible 1', bible_1), call('Bible 2', bible_2), call('Bible 3', bible_3)]) media_item.second_combo_box.addItem.assert_has_calls( [call('', None), call('Bible 1', bible_1), call('Bible 2', bible_2), call('Bible 3', bible_3)]) + mocked_set_combo_box.assert_has_calls( + [call(media_item.version_combo_box, bible_2), call(media_item.second_combo_box, bible_3)]) def test_reload_bibles(media_item): @@ -819,6 +822,7 @@ def test_on_second_combo_box_index_changed_mode_not_changed(media_item): assert mocked_critical_error_message_box.called is False media_item.style_combo_box.setEnabled.assert_called_once_with(False) assert media_item.second_bible == mocked_bible_2 + media_item.settings.setValue.assert_called_once_with('bibles/second bible', 'Bible 2') def test_on_second_combo_box_index_changed_single_to_dual_user_abort(media_item): @@ -846,6 +850,7 @@ def test_on_second_combo_box_index_changed_single_to_dual_user_abort(media_item) assert media_item.second_combo_box.setCurrentIndex.called is True assert media_item.style_combo_box.setEnabled.called is False assert media_item.second_bible is None + media_item.settings.setValue.assert_not_called() def test_on_second_combo_box_index_changed_single_to_dual(media_item): @@ -875,6 +880,7 @@ def test_on_second_combo_box_index_changed_single_to_dual(media_item): media_item.style_combo_box.setEnabled.assert_called_once_with(False) assert mocked_initialise_advanced_bible.called is True assert media_item.second_bible == mocked_bible_1 + media_item.settings.setValue.assert_called_once_with('bibles/second bible', 'Bible 1') def test_on_second_combo_box_index_changed_dual_to_single(media_item): @@ -903,6 +909,7 @@ def test_on_second_combo_box_index_changed_dual_to_single(media_item): media_item.style_combo_box.setEnabled.assert_called_once_with(True) assert mocked_initialise_advanced_bible.called is False assert media_item.second_bible is None + media_item.settings.setValue.assert_called_once_with('bibles/second bible', None) def test_on_advanced_book_combo_box(media_item): @@ -1319,12 +1326,17 @@ def test_text_reference_search_dual_bible(media_item): with patch.object(media_item, 'display_results') as mocked_display_results: media_item.bible = mocked_bible_1 media_item.second_bible = mocked_bible_2 + media_item.search_results = '' + media_item.second_search_results = '' + media_item.plugin.manager.get_verses.side_effect = lambda x, y, z: x # WHEN: Calling text_reference_search with two bibles selected media_item.text_reference_search('Search Text') # THEN: reference_search should be called twice assert media_item.plugin.manager.get_verses.call_count == 2 + assert media_item.search_results == 'Bible 1' + assert media_item.second_search_results == 'Bible 2' mocked_display_results.assert_called_once_with() @@ -1580,3 +1592,82 @@ def test_set_search_option_invalid_value(media_item): assert result is False media_item.settings.setValue.assert_not_called() populate_bible_combo_boxes.assert_not_called() + + +def test_generate_slide_data_data_string(media_item): + """ + Test that the generated_slide_data provides data values for the api + """ + # GIVEN: Mocked service item and some pretend bible slide data + mocked_service_item = MagicMock() + slide_data = { + 'book': 'Matthew', + 'chapter': '1', + 'verse': '2', + 'version': 'Bible version 104', + 'copyright': 'copywrong', + 'permissions': 'all the permissions', + 'second_bible': 'Second bible thing', + 'second_copyright': 'copywrite', + 'second_permissions': 'no use allowed', + 'second_version': 'Bible version 4567', + 'text': 'text from matthew 1:2', + 'second_text': 'different text from matthew 1:2' + } + mocked_items = [MagicMock(**{'data.return_value': slide_data})] + media_item.format_verse = MagicMock() + media_item.settings_tab = MagicMock() + + # WHEN: Called generate_slide_data + media_item.generate_slide_data(mocked_service_item, item=mocked_items) + + # THEN: both primary and secondary bible info should be included in the returned service item data string + assert mocked_service_item.data_string == { + 'bibles': [ + { + 'version': 'Bible version 104', + 'copyright': 'copywrong', + 'permissions': 'all the permissions' + }, + { + 'version': 'Bible version 4567', + 'copyright': 'copywrite', + 'permissions': 'no use allowed' + } + ] + } + + +def test_generate_slide_data_data_string_one_bible(media_item): + """ + Test that the generated_slide_data provides data values for the api + """ + # GIVEN: Mocked service item and some pretend bible slide data + mocked_service_item = MagicMock() + slide_data = { + 'book': 'Matthew', + 'chapter': '1', + 'verse': '2', + 'version': 'Bible version 104', + 'copyright': 'copywrong', + 'permissions': 'all the permissions', + 'second_bible': '', + 'text': 'text from matthew 1:2' + } + mocked_items = [MagicMock(**{'data.return_value': slide_data})] + media_item.format_verse = MagicMock() + media_item.settings_tab = MagicMock() + + # WHEN: Called generate_slide_data + media_item.generate_slide_data(mocked_service_item, item=mocked_items) + + # THEN: both primary and secondary bible info should be included in the returned service item data string + assert mocked_service_item.data_string == { + 'bibles': [ + { + 'version': 'Bible version 104', + 'copyright': 'copywrong', + 'permissions': 'all the permissions' + } + ] + } diff --git a/tests/functional/openlp_plugins/songs/test_songstab.py b/tests/functional/openlp_plugins/songs/test_songstab.py index cc7fb399d..7bafa00f2 100644 --- a/tests/functional/openlp_plugins/songs/test_songstab.py +++ b/tests/functional/openlp_plugins/songs/test_songstab.py @@ -19,7 +19,7 @@ # along with this program. If not, see . # ########################################################################## """ -This module contains tests for the lib submodule of the Images plugin. +This module contains tests for the lib submodule of the Songs plugin. """ import pytest from unittest.mock import MagicMock, patch diff --git a/tests/interfaces/openlp_plugins/bibles/test_lib_parse_reference.py b/tests/interfaces/openlp_plugins/bibles/test_lib_parse_reference.py index e97a99cc3..8b63b776c 100644 --- a/tests/interfaces/openlp_plugins/bibles/test_lib_parse_reference.py +++ b/tests/interfaces/openlp_plugins/bibles/test_lib_parse_reference.py @@ -25,17 +25,28 @@ import pytest from unittest.mock import MagicMock, patch from openlp.core.common.registry import Registry -from openlp.plugins.bibles.lib import parse_reference +from openlp.plugins.bibles.lib import parse_reference, update_reference_separators from openlp.plugins.bibles.lib.manager import BibleManager from tests.utils.constants import TEST_RESOURCES_PATH +__default_settings__ = { + 'bibles/verse separator': '', + 'bibles/range separator': '', + 'bibles/list separator': '', + 'bibles/end separator': '' +} + + @pytest.fixture() def manager(settings): Registry().register('service_list', MagicMock()) + # set default separators to the empty default values + Registry().get('settings').extend_default_settings(__default_settings__) with patch('openlp.core.common.applocation.AppLocation.get_section_data_path') as mocked_get_data_path, \ patch('openlp.core.common.applocation.AppLocation.get_files') as mocked_get_files: # GIVEN: A mocked out AppLocation.get_files() + update_reference_separators() mocked_get_files.return_value = ["tests.sqlite"] mocked_get_data_path.return_value = TEST_RESOURCES_PATH + "/bibles" return BibleManager(MagicMock()) diff --git a/tests/openlp_plugins/bibles/test_biblestab.py b/tests/openlp_plugins/bibles/test_biblestab.py new file mode 100644 index 000000000..34e045929 --- /dev/null +++ b/tests/openlp_plugins/bibles/test_biblestab.py @@ -0,0 +1,84 @@ +# -*- coding: utf-8 -*- + +########################################################################## +# OpenLP - Open Source Lyrics Projection # +# ---------------------------------------------------------------------- # +# Copyright (c) 2008-2021 OpenLP Developers # +# ---------------------------------------------------------------------- # +# 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, either version 3 of the License, or # +# (at your option) any later version. # +# # +# 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, see . # +########################################################################## +""" +This module contains tests for the lib submodule of the Bible plugin. +""" +import pytest +from unittest.mock import MagicMock + +from openlp.core.common.registry import Registry +from openlp.plugins.bibles.lib.biblestab import BiblesTab + +__default_settings__ = { + 'bibles/verse separator': 'verse separator', + 'bibles/range separator': 'range separator', + 'bibles/list separator': 'list separator', + 'bibles/end separator': 'end separator' +} + + +@pytest.fixture() +def form(settings): + Registry().register('settings_form', MagicMock()) + Registry().get('settings').extend_default_settings(__default_settings__) + frm = BiblesTab(None, 'Songs', None, None) + frm.settings_form.register_post_process = MagicMock() + return frm + + +def test_load_when_seperators_set_on_default(form): + """ + Test that the separator checkboxes are still checked even when the default is used + """ + # GIVEN: Seperator settings set as the default + form.settings.setValue('bibles/verse separator', form.settings.value('bibles/verse separator')) + form.settings.setValue('bibles/range separator', form.settings.value('bibles/range separator')) + form.settings.setValue('bibles/list separator', form.settings.value('bibles/list separator')) + form.settings.setValue('bibles/end separator', form.settings.value('bibles/end separator')) + + # WHEN: Load is invoked + form.load() + + # THEN: The checkboxes should be checked + assert form.verse_separator_check_box.isChecked() is True + assert form.range_separator_check_box.isChecked() is True + assert form.list_separator_check_box.isChecked() is True + assert form.end_separator_check_box.isChecked() is True + + +def test_load_when_seperators_unset(form): + """ + Test that the separator checkboxes are not checked when the setting is not set + """ + # GIVEN: Seperator settings non existant + form.settings.remove('bibles/verse separator') + form.settings.remove('bibles/range separator') + form.settings.remove('bibles/list separator') + form.settings.remove('bibles/end separator') + + # WHEN: Load is invoked + form.load() + + # THEN: The checkboxes should be checked + assert form.verse_separator_check_box.isChecked() is False + assert form.range_separator_check_box.isChecked() is False + assert form.list_separator_check_box.isChecked() is False + assert form.end_separator_check_box.isChecked() is False