From 721bcc20e2ee5dc1dfaab0f1e722cd411c140e35 Mon Sep 17 00:00:00 2001 From: Jonathan Springer Date: Tue, 15 Apr 2014 16:51:55 -0400 Subject: [PATCH 01/42] Reorder imports --- tests/functional/openlp_core_ui/test_firsttimeform.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/functional/openlp_core_ui/test_firsttimeform.py b/tests/functional/openlp_core_ui/test_firsttimeform.py index 9fc6f5137..2e26c286a 100644 --- a/tests/functional/openlp_core_ui/test_firsttimeform.py +++ b/tests/functional/openlp_core_ui/test_firsttimeform.py @@ -31,12 +31,12 @@ Package to test the openlp.core.ui.firsttimeform package. """ from unittest import TestCase -from tests.functional import MagicMock - -from tests.helpers.testmixin import TestMixin from openlp.core.common import Registry from openlp.core.ui.firsttimeform import FirstTimeForm +from tests.functional import MagicMock +from tests.helpers.testmixin import TestMixin + class TestFirstTimeForm(TestCase, TestMixin): From aa6b75695610d3b959ef563863c18d8f08343f24 Mon Sep 17 00:00:00 2001 From: Jonathan Springer Date: Wed, 16 Apr 2014 16:26:49 -0400 Subject: [PATCH 02/42] Change how we define which menu items are included in the main menu on Mac OS X --- openlp/core/ui/mainwindow.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/openlp/core/ui/mainwindow.py b/openlp/core/ui/mainwindow.py index 81e822c16..4e1d28ef8 100644 --- a/openlp/core/ui/mainwindow.py +++ b/openlp/core/ui/mainwindow.py @@ -320,14 +320,14 @@ class Ui_MainWindow(object): # i18n add Language Actions add_actions(self.settings_language_menu, (self.auto_language_item, None)) add_actions(self.settings_language_menu, self.language_group.actions()) - # Order things differently in OS X so that Preferences menu item in the - # app menu is correct (this gets picked up automatically by Qt). + # Qt on OS X look for keywords in the menu items title to determine which menu items get added to the main menu. + # If we are running on Mac OS X the menu items whose title contains those keywords but don't belong in the main + # menu need to be marked as such with QAction.NoRole. if sys.platform == 'darwin': - add_actions(self.settings_menu, (self.settings_plugin_list_item, self.settings_language_menu.menuAction(), - None, self.settings_configure_item, self.settings_shortcuts_item, self.formatting_tag_item)) - else: - add_actions(self.settings_menu, (self.settings_plugin_list_item, self.settings_language_menu.menuAction(), - None, self.formatting_tag_item, self.settings_shortcuts_item, self.settings_configure_item)) + self.settings_shortcuts_item.setMenuRole(QtGui.QAction.NoRole) + self.formatting_tag_item.setMenuRole(QtGui.QAction.NoRole) + add_actions(self.settings_menu, (self.settings_plugin_list_item, self.settings_language_menu.menuAction(), + None, self.formatting_tag_item, self.settings_shortcuts_item, self.settings_configure_item)) add_actions(self.tools_menu, (self.tools_add_tool_item, None)) add_actions(self.tools_menu, (self.tools_open_data_folder, None)) add_actions(self.tools_menu, (self.tools_first_time_wizard, None)) From b6e0aa6c2eb4a49d36e4623f70ae667888b77a44 Mon Sep 17 00:00:00 2001 From: Jonathan Springer Date: Wed, 16 Apr 2014 16:44:22 -0400 Subject: [PATCH 03/42] PEP8 clean up in tests --- tests/functional/openlp_core_common/test_common.py | 5 +++-- tests/functional/openlp_core_lib/test_image_manager.py | 2 +- tests/functional/openlp_core_lib/test_ui.py | 2 +- tests/functional/openlp_core_ui/test_maindisplay.py | 2 +- tests/functional/openlp_plugins/songs/test_ewimport.py | 10 +++++----- tests/functional/openlp_plugins/songs/test_lib.py | 1 - .../openlp_plugins/songs/test_songbeamerimport.py | 6 +++--- .../openlp_plugins/songs/test_songshowplusimport.py | 10 +++++----- tests/helpers/songfileimport.py | 10 +++++----- .../openlp_plugins/bibles/test_lib_parse_reference.py | 2 +- 10 files changed, 25 insertions(+), 25 deletions(-) diff --git a/tests/functional/openlp_core_common/test_common.py b/tests/functional/openlp_core_common/test_common.py index 90b7d0520..993a4cede 100644 --- a/tests/functional/openlp_core_common/test_common.py +++ b/tests/functional/openlp_core_common/test_common.py @@ -40,6 +40,7 @@ class TestCommonFunctions(TestCase): """ A test suite to test out various functions in the openlp.core.common module. """ + def de_hump_conversion_test(self): """ Test the de_hump function with a class name @@ -79,5 +80,5 @@ class TestCommonFunctions(TestCase): trace_error_handler(mocked_logger) # THEN: The mocked_logger.error() method should have been called with the correct parameters - mocked_logger.error.assert_called_with('OpenLP Error trace\n File openlp.fake at line 56 \n\t called trace_error_handler_test') - + mocked_logger.error.assert_called_with( + 'OpenLP Error trace\n File openlp.fake at line 56 \n\t called trace_error_handler_test') diff --git a/tests/functional/openlp_core_lib/test_image_manager.py b/tests/functional/openlp_core_lib/test_image_manager.py index 37b6d6fdd..072978993 100644 --- a/tests/functional/openlp_core_lib/test_image_manager.py +++ b/tests/functional/openlp_core_lib/test_image_manager.py @@ -171,4 +171,4 @@ class TestImageManager(TestCase, TestMixin): self.lock.release() # The sleep time is adjusted in the test case. time.sleep(self.sleep_time) - return '' \ No newline at end of file + return '' diff --git a/tests/functional/openlp_core_lib/test_ui.py b/tests/functional/openlp_core_lib/test_ui.py index 91d59ab5a..025b1a638 100644 --- a/tests/functional/openlp_core_lib/test_ui.py +++ b/tests/functional/openlp_core_lib/test_ui.py @@ -162,7 +162,7 @@ class TestUi(TestCase): # WHEN: We create an action with some properties action = create_action(dialog, 'my_action', text='my text', icon=':/wizards/wizard_firsttime.bmp', - tooltip='my tooltip', statustip='my statustip') + tooltip='my tooltip', statustip='my statustip') # THEN: These properties should be set self.assertIsInstance(action, QtGui.QAction) diff --git a/tests/functional/openlp_core_ui/test_maindisplay.py b/tests/functional/openlp_core_ui/test_maindisplay.py index b1a4dc7f7..6d67a3b67 100644 --- a/tests/functional/openlp_core_ui/test_maindisplay.py +++ b/tests/functional/openlp_core_ui/test_maindisplay.py @@ -106,4 +106,4 @@ class TestMainDisplay(TestCase): self.assertEqual('QGraphicsView {}', main_display.styleSheet(), 'MainDisplay instance should not be transparent') self.assertFalse(main_display.testAttribute(QtCore.Qt.WA_TranslucentBackground), - 'MainDisplay hasnt translucent background') + 'MainDisplay hasnt translucent background') diff --git a/tests/functional/openlp_plugins/songs/test_ewimport.py b/tests/functional/openlp_plugins/songs/test_ewimport.py index c1b9db52d..984c87028 100644 --- a/tests/functional/openlp_plugins/songs/test_ewimport.py +++ b/tests/functional/openlp_plugins/songs/test_ewimport.py @@ -141,7 +141,7 @@ class TestEasyWorshipSongImport(TestCase): self.assertIsNotNone(field_desc_entry, 'Import should not be none') self.assertEqual(field_desc_entry.name, name, 'FieldDescEntry.name should be the same as the name argument') self.assertEqual(field_desc_entry.field_type, field_type, - 'FieldDescEntry.type should be the same as the type argument') + 'FieldDescEntry.type should be the same as the type argument') self.assertEqual(field_desc_entry.size, size, 'FieldDescEntry.size should be the same as the size argument') def create_importer_test(self): @@ -231,8 +231,8 @@ class TestEasyWorshipSongImport(TestCase): # THEN: get_field should return the known results self.assertEqual(return_value, result, - 'get_field should return "%s" when called with "%s"' % - (result, TEST_FIELDS[field_index])) + 'get_field should return "%s" when called with "%s"' % + (result, TEST_FIELDS[field_index])) def get_memo_field_test(self): """ @@ -404,10 +404,10 @@ class TestEasyWorshipSongImport(TestCase): self.assertEqual(importer.copyright, song_copyright) if ccli_number: self.assertEqual(importer.ccli_number, ccli_number, 'ccli_number for %s should be %s' - % (title, ccli_number)) + % (title, ccli_number)) for verse_text, verse_tag in add_verse_calls: mocked_add_verse.assert_any_call(verse_text, verse_tag) if verse_order_list: self.assertEqual(importer.verse_order_list, verse_order_list, - 'verse_order_list for %s should be %s' % (title, verse_order_list)) + 'verse_order_list for %s should be %s' % (title, verse_order_list)) mocked_finish.assert_called_with() diff --git a/tests/functional/openlp_plugins/songs/test_lib.py b/tests/functional/openlp_plugins/songs/test_lib.py index 2ab808bc9..b67c1a4be 100644 --- a/tests/functional/openlp_plugins/songs/test_lib.py +++ b/tests/functional/openlp_plugins/songs/test_lib.py @@ -129,7 +129,6 @@ class TestLib(TestCase): # THEN: The result should be a tuple of songs.. assert result == (self.song1, self.song2), 'The result should be the tuble of songs' - def songs_probably_equal_different_song_test(self): """ Test the songs_probably_equal function with two different songs. diff --git a/tests/functional/openlp_plugins/songs/test_songbeamerimport.py b/tests/functional/openlp_plugins/songs/test_songbeamerimport.py index f08cedec5..d95d49d80 100644 --- a/tests/functional/openlp_plugins/songs/test_songbeamerimport.py +++ b/tests/functional/openlp_plugins/songs/test_songbeamerimport.py @@ -91,7 +91,7 @@ class TestSongBeamerImport(TestCase): # THEN: do_import should return none and the progress bar maximum should not be set. self.assertIsNone(importer.do_import(), 'do_import should return None when import_source is not a list') self.assertEqual(mocked_import_wizard.progress_bar.setMaximum.called, False, - 'setMaxium on import_wizard.progress_bar should not have been called') + 'setMaxium on import_wizard.progress_bar should not have been called') def valid_import_source_test(self): """ @@ -149,10 +149,10 @@ class TestSongBeamerImport(TestCase): mocked_add_verse.assert_any_call(verse_text, verse_tag) if song_book_name: self.assertEqual(importer.song_book_name, song_book_name, 'song_book_name for %s should be "%s"' % - (song_file, song_book_name)) + (song_file, song_book_name)) if song_number: self.assertEqual(importer.song_number, song_number, 'song_number for %s should be %s' % - (song_file, song_number)) + (song_file, song_number)) mocked_finish.assert_called_with() def check_verse_marks_test(self): diff --git a/tests/functional/openlp_plugins/songs/test_songshowplusimport.py b/tests/functional/openlp_plugins/songs/test_songshowplusimport.py index f2839c332..63e5beb8a 100644 --- a/tests/functional/openlp_plugins/songs/test_songshowplusimport.py +++ b/tests/functional/openlp_plugins/songs/test_songshowplusimport.py @@ -96,7 +96,7 @@ class TestSongShowPlusImport(TestCase): # THEN: do_import should return none and the progress bar maximum should not be set. self.assertIsNone(importer.do_import(), 'do_import should return None when import_source is not a list') self.assertEqual(mocked_import_wizard.progress_bar.setMaximum.called, False, - 'setMaximum on import_wizard.progress_bar should not have been called') + 'setMaximum on import_wizard.progress_bar should not have been called') def valid_import_source_test(self): """ @@ -144,8 +144,8 @@ class TestSongShowPlusImport(TestCase): # THEN: The returned value should should correlate with the input arguments for original_tag, openlp_tag in test_values: self.assertEqual(importer.to_openlp_verse_tag(original_tag), openlp_tag, - 'SongShowPlusImport.to_openlp_verse_tag should return "%s" when called with "%s"' % - (openlp_tag, original_tag)) + 'SongShowPlusImport.to_openlp_verse_tag should return "%s" when called with "%s"' % + (openlp_tag, original_tag)) def to_openlp_verse_tag_verse_order_test(self): """ @@ -173,5 +173,5 @@ class TestSongShowPlusImport(TestCase): # THEN: The returned value should should correlate with the input arguments for original_tag, openlp_tag in test_values: self.assertEqual(importer.to_openlp_verse_tag(original_tag, ignore_unique=True), openlp_tag, - 'SongShowPlusImport.to_openlp_verse_tag should return "%s" when called with "%s"' % - (openlp_tag, original_tag)) + 'SongShowPlusImport.to_openlp_verse_tag should return "%s" when called with "%s"' % + (openlp_tag, original_tag)) diff --git a/tests/helpers/songfileimport.py b/tests/helpers/songfileimport.py index 49a09528c..b961b7d64 100644 --- a/tests/helpers/songfileimport.py +++ b/tests/helpers/songfileimport.py @@ -117,23 +117,23 @@ class SongImportTestHelper(TestCase): self.mocked_add_copyright.assert_called_with(song_copyright) if ccli_number: self.assertEqual(importer.ccli_number, ccli_number, 'ccli_number for %s should be %s' % - (source_file_name, ccli_number)) + (source_file_name, ccli_number)) for verse_text, verse_tag in add_verse_calls: self.mocked_add_verse.assert_any_call(verse_text, verse_tag) if topics: self.assertEqual(importer.topics, topics, 'topics for %s should be %s' % (source_file_name, topics)) if comments: self.assertEqual(importer.comments, comments, 'comments for %s should be "%s"' % - (source_file_name, comments)) + (source_file_name, comments)) if song_book_name: self.assertEqual(importer.song_book_name, song_book_name, 'song_book_name for %s should be "%s"' % - (source_file_name, song_book_name)) + (source_file_name, song_book_name)) if song_number: self.assertEqual(importer.song_number, song_number, 'song_number for %s should be %s' % - (source_file_name, song_number)) + (source_file_name, song_number)) if verse_order_list: self.assertEqual(importer.verse_order_list, [], 'verse_order_list for %s should be %s' % - (source_file_name, verse_order_list)) + (source_file_name, verse_order_list)) self.mocked_finish.assert_called_with() def _get_data(self, data, key): 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 84f80e7ed..b005992ff 100644 --- a/tests/interfaces/openlp_plugins/bibles/test_lib_parse_reference.py +++ b/tests/interfaces/openlp_plugins/bibles/test_lib_parse_reference.py @@ -104,4 +104,4 @@ class TestBibleManager(TestCase, TestMixin): results = parse_reference('1 Timothy 1:1-2:1', self.manager.db_cache['tests'], MagicMock(), 54) # THEN a verse array should be returned self.assertEqual([(54, 1, 1, -1), (54, 2, 1, 1)], results, "The bible verses should matches the expected " - "results") + "results") From 85fc53954d905488c5bec91680ebf80ef2c7cb0e Mon Sep 17 00:00:00 2001 From: Jonathan Springer Date: Wed, 16 Apr 2014 16:49:24 -0400 Subject: [PATCH 04/42] More PEP8 fixes --- openlp/core/ui/mainwindow.py | 2 +- openlp/plugins/songs/lib/songbeamerimport.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/openlp/core/ui/mainwindow.py b/openlp/core/ui/mainwindow.py index 4e1d28ef8..dca7bf815 100644 --- a/openlp/core/ui/mainwindow.py +++ b/openlp/core/ui/mainwindow.py @@ -320,7 +320,7 @@ class Ui_MainWindow(object): # i18n add Language Actions add_actions(self.settings_language_menu, (self.auto_language_item, None)) add_actions(self.settings_language_menu, self.language_group.actions()) - # Qt on OS X look for keywords in the menu items title to determine which menu items get added to the main menu. + # Qt on OS X look for keywords in the menu items title to determine which menu items get added to the main menu. # If we are running on Mac OS X the menu items whose title contains those keywords but don't belong in the main # menu need to be marked as such with QAction.NoRole. if sys.platform == 'darwin': diff --git a/openlp/plugins/songs/lib/songbeamerimport.py b/openlp/plugins/songs/lib/songbeamerimport.py index 5b86591e8..a0b166ded 100644 --- a/openlp/plugins/songs/lib/songbeamerimport.py +++ b/openlp/plugins/songs/lib/songbeamerimport.py @@ -137,7 +137,7 @@ class SongBeamerImport(SongImport): if line.startswith('#') and not read_verses: self.parseTags(line) elif line.startswith('--'): - # --- and -- allowed for page-breaks (difference in Songbeamer only in printout) + # --- and -- allowed for page-breaks (difference in Songbeamer only in printout) if self.current_verse: self.replace_html_tags() self.add_verse(self.current_verse, self.current_verse_type) From ef5b1cf4ac08062f80758bb539bdee3491b35c38 Mon Sep 17 00:00:00 2001 From: Jonathan Springer Date: Wed, 16 Apr 2014 17:19:22 -0400 Subject: [PATCH 05/42] Revert PEP8 clean ups as they were already done in a different branch --- openlp/core/ui/mainwindow.py | 2 +- openlp/plugins/songs/lib/songbeamerimport.py | 2 +- tests/functional/openlp_core_common/test_common.py | 5 ++--- tests/functional/openlp_core_lib/test_image_manager.py | 2 +- tests/functional/openlp_core_lib/test_ui.py | 2 +- tests/functional/openlp_core_ui/test_maindisplay.py | 2 +- tests/functional/openlp_plugins/songs/test_ewimport.py | 10 +++++----- tests/functional/openlp_plugins/songs/test_lib.py | 1 + .../openlp_plugins/songs/test_songbeamerimport.py | 6 +++--- .../openlp_plugins/songs/test_songshowplusimport.py | 10 +++++----- tests/helpers/songfileimport.py | 10 +++++----- .../openlp_plugins/bibles/test_lib_parse_reference.py | 2 +- 12 files changed, 27 insertions(+), 27 deletions(-) diff --git a/openlp/core/ui/mainwindow.py b/openlp/core/ui/mainwindow.py index dca7bf815..4e1d28ef8 100644 --- a/openlp/core/ui/mainwindow.py +++ b/openlp/core/ui/mainwindow.py @@ -320,7 +320,7 @@ class Ui_MainWindow(object): # i18n add Language Actions add_actions(self.settings_language_menu, (self.auto_language_item, None)) add_actions(self.settings_language_menu, self.language_group.actions()) - # Qt on OS X look for keywords in the menu items title to determine which menu items get added to the main menu. + # Qt on OS X look for keywords in the menu items title to determine which menu items get added to the main menu. # If we are running on Mac OS X the menu items whose title contains those keywords but don't belong in the main # menu need to be marked as such with QAction.NoRole. if sys.platform == 'darwin': diff --git a/openlp/plugins/songs/lib/songbeamerimport.py b/openlp/plugins/songs/lib/songbeamerimport.py index a0b166ded..5b86591e8 100644 --- a/openlp/plugins/songs/lib/songbeamerimport.py +++ b/openlp/plugins/songs/lib/songbeamerimport.py @@ -137,7 +137,7 @@ class SongBeamerImport(SongImport): if line.startswith('#') and not read_verses: self.parseTags(line) elif line.startswith('--'): - # --- and -- allowed for page-breaks (difference in Songbeamer only in printout) + # --- and -- allowed for page-breaks (difference in Songbeamer only in printout) if self.current_verse: self.replace_html_tags() self.add_verse(self.current_verse, self.current_verse_type) diff --git a/tests/functional/openlp_core_common/test_common.py b/tests/functional/openlp_core_common/test_common.py index 993a4cede..90b7d0520 100644 --- a/tests/functional/openlp_core_common/test_common.py +++ b/tests/functional/openlp_core_common/test_common.py @@ -40,7 +40,6 @@ class TestCommonFunctions(TestCase): """ A test suite to test out various functions in the openlp.core.common module. """ - def de_hump_conversion_test(self): """ Test the de_hump function with a class name @@ -80,5 +79,5 @@ class TestCommonFunctions(TestCase): trace_error_handler(mocked_logger) # THEN: The mocked_logger.error() method should have been called with the correct parameters - mocked_logger.error.assert_called_with( - 'OpenLP Error trace\n File openlp.fake at line 56 \n\t called trace_error_handler_test') + mocked_logger.error.assert_called_with('OpenLP Error trace\n File openlp.fake at line 56 \n\t called trace_error_handler_test') + diff --git a/tests/functional/openlp_core_lib/test_image_manager.py b/tests/functional/openlp_core_lib/test_image_manager.py index 072978993..37b6d6fdd 100644 --- a/tests/functional/openlp_core_lib/test_image_manager.py +++ b/tests/functional/openlp_core_lib/test_image_manager.py @@ -171,4 +171,4 @@ class TestImageManager(TestCase, TestMixin): self.lock.release() # The sleep time is adjusted in the test case. time.sleep(self.sleep_time) - return '' + return '' \ No newline at end of file diff --git a/tests/functional/openlp_core_lib/test_ui.py b/tests/functional/openlp_core_lib/test_ui.py index 025b1a638..91d59ab5a 100644 --- a/tests/functional/openlp_core_lib/test_ui.py +++ b/tests/functional/openlp_core_lib/test_ui.py @@ -162,7 +162,7 @@ class TestUi(TestCase): # WHEN: We create an action with some properties action = create_action(dialog, 'my_action', text='my text', icon=':/wizards/wizard_firsttime.bmp', - tooltip='my tooltip', statustip='my statustip') + tooltip='my tooltip', statustip='my statustip') # THEN: These properties should be set self.assertIsInstance(action, QtGui.QAction) diff --git a/tests/functional/openlp_core_ui/test_maindisplay.py b/tests/functional/openlp_core_ui/test_maindisplay.py index 6d67a3b67..b1a4dc7f7 100644 --- a/tests/functional/openlp_core_ui/test_maindisplay.py +++ b/tests/functional/openlp_core_ui/test_maindisplay.py @@ -106,4 +106,4 @@ class TestMainDisplay(TestCase): self.assertEqual('QGraphicsView {}', main_display.styleSheet(), 'MainDisplay instance should not be transparent') self.assertFalse(main_display.testAttribute(QtCore.Qt.WA_TranslucentBackground), - 'MainDisplay hasnt translucent background') + 'MainDisplay hasnt translucent background') diff --git a/tests/functional/openlp_plugins/songs/test_ewimport.py b/tests/functional/openlp_plugins/songs/test_ewimport.py index 984c87028..c1b9db52d 100644 --- a/tests/functional/openlp_plugins/songs/test_ewimport.py +++ b/tests/functional/openlp_plugins/songs/test_ewimport.py @@ -141,7 +141,7 @@ class TestEasyWorshipSongImport(TestCase): self.assertIsNotNone(field_desc_entry, 'Import should not be none') self.assertEqual(field_desc_entry.name, name, 'FieldDescEntry.name should be the same as the name argument') self.assertEqual(field_desc_entry.field_type, field_type, - 'FieldDescEntry.type should be the same as the type argument') + 'FieldDescEntry.type should be the same as the type argument') self.assertEqual(field_desc_entry.size, size, 'FieldDescEntry.size should be the same as the size argument') def create_importer_test(self): @@ -231,8 +231,8 @@ class TestEasyWorshipSongImport(TestCase): # THEN: get_field should return the known results self.assertEqual(return_value, result, - 'get_field should return "%s" when called with "%s"' % - (result, TEST_FIELDS[field_index])) + 'get_field should return "%s" when called with "%s"' % + (result, TEST_FIELDS[field_index])) def get_memo_field_test(self): """ @@ -404,10 +404,10 @@ class TestEasyWorshipSongImport(TestCase): self.assertEqual(importer.copyright, song_copyright) if ccli_number: self.assertEqual(importer.ccli_number, ccli_number, 'ccli_number for %s should be %s' - % (title, ccli_number)) + % (title, ccli_number)) for verse_text, verse_tag in add_verse_calls: mocked_add_verse.assert_any_call(verse_text, verse_tag) if verse_order_list: self.assertEqual(importer.verse_order_list, verse_order_list, - 'verse_order_list for %s should be %s' % (title, verse_order_list)) + 'verse_order_list for %s should be %s' % (title, verse_order_list)) mocked_finish.assert_called_with() diff --git a/tests/functional/openlp_plugins/songs/test_lib.py b/tests/functional/openlp_plugins/songs/test_lib.py index b67c1a4be..2ab808bc9 100644 --- a/tests/functional/openlp_plugins/songs/test_lib.py +++ b/tests/functional/openlp_plugins/songs/test_lib.py @@ -129,6 +129,7 @@ class TestLib(TestCase): # THEN: The result should be a tuple of songs.. assert result == (self.song1, self.song2), 'The result should be the tuble of songs' + def songs_probably_equal_different_song_test(self): """ Test the songs_probably_equal function with two different songs. diff --git a/tests/functional/openlp_plugins/songs/test_songbeamerimport.py b/tests/functional/openlp_plugins/songs/test_songbeamerimport.py index d95d49d80..f08cedec5 100644 --- a/tests/functional/openlp_plugins/songs/test_songbeamerimport.py +++ b/tests/functional/openlp_plugins/songs/test_songbeamerimport.py @@ -91,7 +91,7 @@ class TestSongBeamerImport(TestCase): # THEN: do_import should return none and the progress bar maximum should not be set. self.assertIsNone(importer.do_import(), 'do_import should return None when import_source is not a list') self.assertEqual(mocked_import_wizard.progress_bar.setMaximum.called, False, - 'setMaxium on import_wizard.progress_bar should not have been called') + 'setMaxium on import_wizard.progress_bar should not have been called') def valid_import_source_test(self): """ @@ -149,10 +149,10 @@ class TestSongBeamerImport(TestCase): mocked_add_verse.assert_any_call(verse_text, verse_tag) if song_book_name: self.assertEqual(importer.song_book_name, song_book_name, 'song_book_name for %s should be "%s"' % - (song_file, song_book_name)) + (song_file, song_book_name)) if song_number: self.assertEqual(importer.song_number, song_number, 'song_number for %s should be %s' % - (song_file, song_number)) + (song_file, song_number)) mocked_finish.assert_called_with() def check_verse_marks_test(self): diff --git a/tests/functional/openlp_plugins/songs/test_songshowplusimport.py b/tests/functional/openlp_plugins/songs/test_songshowplusimport.py index 63e5beb8a..f2839c332 100644 --- a/tests/functional/openlp_plugins/songs/test_songshowplusimport.py +++ b/tests/functional/openlp_plugins/songs/test_songshowplusimport.py @@ -96,7 +96,7 @@ class TestSongShowPlusImport(TestCase): # THEN: do_import should return none and the progress bar maximum should not be set. self.assertIsNone(importer.do_import(), 'do_import should return None when import_source is not a list') self.assertEqual(mocked_import_wizard.progress_bar.setMaximum.called, False, - 'setMaximum on import_wizard.progress_bar should not have been called') + 'setMaximum on import_wizard.progress_bar should not have been called') def valid_import_source_test(self): """ @@ -144,8 +144,8 @@ class TestSongShowPlusImport(TestCase): # THEN: The returned value should should correlate with the input arguments for original_tag, openlp_tag in test_values: self.assertEqual(importer.to_openlp_verse_tag(original_tag), openlp_tag, - 'SongShowPlusImport.to_openlp_verse_tag should return "%s" when called with "%s"' % - (openlp_tag, original_tag)) + 'SongShowPlusImport.to_openlp_verse_tag should return "%s" when called with "%s"' % + (openlp_tag, original_tag)) def to_openlp_verse_tag_verse_order_test(self): """ @@ -173,5 +173,5 @@ class TestSongShowPlusImport(TestCase): # THEN: The returned value should should correlate with the input arguments for original_tag, openlp_tag in test_values: self.assertEqual(importer.to_openlp_verse_tag(original_tag, ignore_unique=True), openlp_tag, - 'SongShowPlusImport.to_openlp_verse_tag should return "%s" when called with "%s"' % - (openlp_tag, original_tag)) + 'SongShowPlusImport.to_openlp_verse_tag should return "%s" when called with "%s"' % + (openlp_tag, original_tag)) diff --git a/tests/helpers/songfileimport.py b/tests/helpers/songfileimport.py index b961b7d64..49a09528c 100644 --- a/tests/helpers/songfileimport.py +++ b/tests/helpers/songfileimport.py @@ -117,23 +117,23 @@ class SongImportTestHelper(TestCase): self.mocked_add_copyright.assert_called_with(song_copyright) if ccli_number: self.assertEqual(importer.ccli_number, ccli_number, 'ccli_number for %s should be %s' % - (source_file_name, ccli_number)) + (source_file_name, ccli_number)) for verse_text, verse_tag in add_verse_calls: self.mocked_add_verse.assert_any_call(verse_text, verse_tag) if topics: self.assertEqual(importer.topics, topics, 'topics for %s should be %s' % (source_file_name, topics)) if comments: self.assertEqual(importer.comments, comments, 'comments for %s should be "%s"' % - (source_file_name, comments)) + (source_file_name, comments)) if song_book_name: self.assertEqual(importer.song_book_name, song_book_name, 'song_book_name for %s should be "%s"' % - (source_file_name, song_book_name)) + (source_file_name, song_book_name)) if song_number: self.assertEqual(importer.song_number, song_number, 'song_number for %s should be %s' % - (source_file_name, song_number)) + (source_file_name, song_number)) if verse_order_list: self.assertEqual(importer.verse_order_list, [], 'verse_order_list for %s should be %s' % - (source_file_name, verse_order_list)) + (source_file_name, verse_order_list)) self.mocked_finish.assert_called_with() def _get_data(self, data, key): 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 b005992ff..84f80e7ed 100644 --- a/tests/interfaces/openlp_plugins/bibles/test_lib_parse_reference.py +++ b/tests/interfaces/openlp_plugins/bibles/test_lib_parse_reference.py @@ -104,4 +104,4 @@ class TestBibleManager(TestCase, TestMixin): results = parse_reference('1 Timothy 1:1-2:1', self.manager.db_cache['tests'], MagicMock(), 54) # THEN a verse array should be returned self.assertEqual([(54, 1, 1, -1), (54, 2, 1, 1)], results, "The bible verses should matches the expected " - "results") + "results") From e86539888d2dfff0984e01e959cc01318659e692 Mon Sep 17 00:00:00 2001 From: Jonathan Springer Date: Thu, 17 Apr 2014 20:09:31 -0400 Subject: [PATCH 06/42] Fix typo --- openlp/core/ui/mainwindow.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openlp/core/ui/mainwindow.py b/openlp/core/ui/mainwindow.py index 4e1d28ef8..2b03c05cb 100644 --- a/openlp/core/ui/mainwindow.py +++ b/openlp/core/ui/mainwindow.py @@ -320,9 +320,9 @@ class Ui_MainWindow(object): # i18n add Language Actions add_actions(self.settings_language_menu, (self.auto_language_item, None)) add_actions(self.settings_language_menu, self.language_group.actions()) - # Qt on OS X look for keywords in the menu items title to determine which menu items get added to the main menu. - # If we are running on Mac OS X the menu items whose title contains those keywords but don't belong in the main - # menu need to be marked as such with QAction.NoRole. + # Qt on OS X looks for keywords in the menu items title to determine which menu items get added to the main + # menu. If we are running on Mac OS X the menu items whose title contains those keywords but don't belong in the + # main menu need to be marked as such with QAction.NoRole. if sys.platform == 'darwin': self.settings_shortcuts_item.setMenuRole(QtGui.QAction.NoRole) self.formatting_tag_item.setMenuRole(QtGui.QAction.NoRole) From 13fb4496f3114571c9f8ef35aca8e8c1f66a63ae Mon Sep 17 00:00:00 2001 From: Jonathan Springer Date: Wed, 23 Apr 2014 22:57:02 -0400 Subject: [PATCH 07/42] Change type to conform to expected type --- openlp/plugins/images/lib/mediaitem.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openlp/plugins/images/lib/mediaitem.py b/openlp/plugins/images/lib/mediaitem.py index c28f1e834..36df55dac 100644 --- a/openlp/plugins/images/lib/mediaitem.py +++ b/openlp/plugins/images/lib/mediaitem.py @@ -353,7 +353,7 @@ class ImageMediaItem(MediaManagerItem): icon = build_icon(thumb) else: icon = create_thumb(imageFile.filename, thumb) - item_name = QtGui.QTreeWidgetItem(filename) + item_name = QtGui.QTreeWidgetItem([filename]) item_name.setText(0, filename) item_name.setIcon(0, icon) item_name.setToolTip(0, imageFile.filename) From 1cd7d73d10b60ef5a0b058bcd5cbbc69a7e7d6bc Mon Sep 17 00:00:00 2001 From: Stefan Strasser Date: Fri, 25 Apr 2014 22:04:43 +0200 Subject: [PATCH 08/42] fixed bug #1312629 Error on entering invalid character in verse-order Fixes: https://launchpad.net/bugs/1312629 --- openlp/plugins/songs/lib/__init__.py | 6 ++-- .../openlp_plugins/songs/test_lib.py | 32 +++++++++++++++++-- 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/openlp/plugins/songs/lib/__init__.py b/openlp/plugins/songs/lib/__init__.py index dc198d4b7..343bc710b 100644 --- a/openlp/plugins/songs/lib/__init__.py +++ b/openlp/plugins/songs/lib/__init__.py @@ -206,14 +206,14 @@ class VerseType(object): Return the VerseType for a given tag :param verse_tag: The string to return a VerseType for - :param default: Default return value if no matching tag is found + :param default: Default return value if no matching tag is found (a valid VerseType or None) :return: A VerseType of the tag """ verse_tag = verse_tag[0].lower() for num, tag in enumerate(VerseType.tags): if verse_tag == tag: return num - if len(VerseType.names) > default: + if default in range(0,len(VerseType.names)) or default is None: return default else: return VerseType.Other @@ -231,7 +231,7 @@ class VerseType(object): for num, tag in enumerate(VerseType.translated_tags): if verse_tag == tag: return num - if len(VerseType.names) > default: + if default in range(0,len(VerseType.names)) or default is None: return default else: return VerseType.Other diff --git a/tests/functional/openlp_plugins/songs/test_lib.py b/tests/functional/openlp_plugins/songs/test_lib.py index b67c1a4be..b06a18a7c 100644 --- a/tests/functional/openlp_plugins/songs/test_lib.py +++ b/tests/functional/openlp_plugins/songs/test_lib.py @@ -445,9 +445,9 @@ class TestVerseType(TestCase): # THEN: The result should be VerseType.Chorus self.assertEqual(result, VerseType.Chorus, 'The result should be VerseType.Chorus, but was "%s"' % result) - def from_tag_with_invalid_default_test(self): + def from_tag_with_invalid_intdefault_test(self): """ - Test that the from_tag() method returns a sane default when passed an invalid tag and an invalid default. + Test that the from_tag() method returns a sane default when passed an invalid tag and an invalid int default. """ # GIVEN: A mocked out translate() function that just returns what it was given with patch('openlp.plugins.songs.lib.translate') as mocked_translate: @@ -458,3 +458,31 @@ class TestVerseType(TestCase): # THEN: The result should be VerseType.Other self.assertEqual(result, VerseType.Other, 'The result should be VerseType.Other, but was "%s"' % result) + + def from_tag_with_invalid_default_test(self): + """ + Test that the from_tag() method returns a sane default when passed an invalid tag and an invalid default. + """ + # GIVEN: A mocked out translate() function that just returns what it was given + with patch('openlp.plugins.songs.lib.translate') as mocked_translate: + mocked_translate.side_effect = lambda x, y: y + + # WHEN: We run the from_tag() method with an invalid verse type, we get the specified default back + result = VerseType.from_tag('@', 'asdf') + + # THEN: The result should be VerseType.Other + self.assertEqual(result, VerseType.Other, 'The result should be VerseType.Other, but was "%s"' % result) + + def from_tag_with_none_default_test(self): + """ + Test that the from_tag() method returns a sane default when passed an invalid tag and None as default. + """ + # GIVEN: A mocked out translate() function that just returns what it was given + with patch('openlp.plugins.songs.lib.translate') as mocked_translate: + mocked_translate.side_effect = lambda x, y: y + + # WHEN: We run the from_tag() method with an invalid verse type, we get the specified default back + result = VerseType.from_tag('m', None) + + # THEN: The result should be VerseType.Other + self.assertIsNone(result, 'The result should be None, but was "%s"' % result) From c2d1589dcb2787891faed11d2b77f8be08a62762 Mon Sep 17 00:00:00 2001 From: Stefan Strasser Date: Sat, 26 Apr 2014 07:07:08 +0200 Subject: [PATCH 09/42] fixed a pep-issue in songs-lib and corrected a comment in a test --- openlp/plugins/songs/lib/__init__.py | 4 ++-- tests/functional/openlp_plugins/songs/test_lib.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/openlp/plugins/songs/lib/__init__.py b/openlp/plugins/songs/lib/__init__.py index 343bc710b..a0a8e94bd 100644 --- a/openlp/plugins/songs/lib/__init__.py +++ b/openlp/plugins/songs/lib/__init__.py @@ -213,7 +213,7 @@ class VerseType(object): for num, tag in enumerate(VerseType.tags): if verse_tag == tag: return num - if default in range(0,len(VerseType.names)) or default is None: + if default in range(0, len(VerseType.names)) or default is None: return default else: return VerseType.Other @@ -231,7 +231,7 @@ class VerseType(object): for num, tag in enumerate(VerseType.translated_tags): if verse_tag == tag: return num - if default in range(0,len(VerseType.names)) or default is None: + if default in range(0, len(VerseType.names)) or default is None: return default else: return VerseType.Other diff --git a/tests/functional/openlp_plugins/songs/test_lib.py b/tests/functional/openlp_plugins/songs/test_lib.py index b06a18a7c..140126f26 100644 --- a/tests/functional/openlp_plugins/songs/test_lib.py +++ b/tests/functional/openlp_plugins/songs/test_lib.py @@ -484,5 +484,5 @@ class TestVerseType(TestCase): # WHEN: We run the from_tag() method with an invalid verse type, we get the specified default back result = VerseType.from_tag('m', None) - # THEN: The result should be VerseType.Other + # THEN: The result should be None self.assertIsNone(result, 'The result should be None, but was "%s"' % result) From 518d391e458ab22ad7e7c37588702d9bbe50fd2d Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Sun, 27 Apr 2014 16:38:48 +0100 Subject: [PATCH 10/42] Fix trunk --- openlp/plugins/songs/lib/upgrade.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openlp/plugins/songs/lib/upgrade.py b/openlp/plugins/songs/lib/upgrade.py index adb7d8af5..546343900 100644 --- a/openlp/plugins/songs/lib/upgrade.py +++ b/openlp/plugins/songs/lib/upgrade.py @@ -39,7 +39,7 @@ from sqlalchemy.sql.expression import func, false, null, text from openlp.core.lib.db import get_upgrade_op log = logging.getLogger(__name__) -__version__ = 3 +__version__ = 4 def upgrade_1(session, metadata): From bdf3109aaa9e02897568244297a70bb0e4f63af5 Mon Sep 17 00:00:00 2001 From: Samuel Mehrbrodt Date: Thu, 1 May 2014 10:46:45 +0200 Subject: [PATCH 11/42] Fix SongShowPlus Import for certain cases Fixes: https://launchpad.net/bugs/1310623 --- .../plugins/songs/lib/songshowplusimport.py | 7 +++-- .../songs/test_songshowplusimport.py | 2 ++ .../a mighty fortress is our god.json | 29 ++++++++++++++++++ .../a mighty fortress is our god.sbsong | Bin 0 -> 1342 bytes 4 files changed, 36 insertions(+), 2 deletions(-) create mode 100644 tests/resources/songshowplussongs/a mighty fortress is our god.json create mode 100644 tests/resources/songshowplussongs/a mighty fortress is our god.sbsong diff --git a/openlp/plugins/songs/lib/songshowplusimport.py b/openlp/plugins/songs/lib/songshowplusimport.py index 0a8dc4650..c1c6d04cb 100644 --- a/openlp/plugins/songs/lib/songshowplusimport.py +++ b/openlp/plugins/songs/lib/songshowplusimport.py @@ -121,7 +121,7 @@ class SongShowPlusImport(SongImport): null, verse_no, = struct.unpack("BB", song_data.read(2)) elif block_key == CUSTOM_VERSE: null, verse_name_length, = struct.unpack("BB", song_data.read(2)) - verse_name = song_data.read(verse_name_length) + verse_name = self.decode(song_data.read(verse_name_length)) length_descriptor_size, = struct.unpack("B", song_data.read(1)) log.debug(length_descriptor_size) # Detect if/how long the length descriptor is @@ -147,7 +147,10 @@ class SongShowPlusImport(SongImport): elif block_key == COPYRIGHT: self.add_copyright(self.decode(data)) elif block_key == CCLI_NO: - self.ccli_number = int(data) + try: + self.ccli_number = int(data) + except ValueError: + continue elif block_key == VERSE: self.add_verse(self.decode(data), "%s%s" % (VerseType.tags[VerseType.Verse], verse_no)) elif block_key == CHORUS: diff --git a/tests/functional/openlp_plugins/songs/test_songshowplusimport.py b/tests/functional/openlp_plugins/songs/test_songshowplusimport.py index 7292bb2b0..08400fdc5 100644 --- a/tests/functional/openlp_plugins/songs/test_songshowplusimport.py +++ b/tests/functional/openlp_plugins/songs/test_songshowplusimport.py @@ -57,6 +57,8 @@ class TestSongShowPlusFileImport(SongImportTestHelper): self.load_external_result_data(os.path.join(TEST_PATH, 'Amazing Grace.json'))) self.file_import(os.path.join(TEST_PATH, 'Beautiful Garden Of Prayer.sbsong'), self.load_external_result_data(os.path.join(TEST_PATH, 'Beautiful Garden Of Prayer.json'))) + self.file_import(os.path.join(TEST_PATH, 'a mighty fortress is our god.sbsong'), + self.load_external_result_data(os.path.join(TEST_PATH, 'a mighty fortress is our god.json'))) class TestSongShowPlusImport(TestCase): diff --git a/tests/resources/songshowplussongs/a mighty fortress is our god.json b/tests/resources/songshowplussongs/a mighty fortress is our god.json new file mode 100644 index 000000000..7e3d400b4 --- /dev/null +++ b/tests/resources/songshowplussongs/a mighty fortress is our god.json @@ -0,0 +1,29 @@ +{ + "authors": [ + "Martin Luther" + ], + "comments": "", + "copyright": "Public Domain", + "song_number": 0, + "title": "A Mighty Fortress is our God", + "topics": [], + "verse_order_list": [], + "verses": [ + [ + "A mighty fortress is our God, a bulwark never failing;\r\nOur helper He, amid the flood of mortal ills prevailing:\r\nFor still our ancient foe doth seek to work us woe;\r\nHis craft and power are great, and, armed with cruel hate,\r\nOn earth is not his equal.\r\n", + "v1" + ], + [ + "Did we in our own strength confide, our striving would be losing;\r\nWere not the right Man on our side, the Man of God’s own choosing:\r\nDost ask who that may be? Christ Jesus, it is He;\r\nLord Sabaoth, His Name, from age to age the same,\r\nAnd He must win the battle.\r\n", + "v2" + ], + [ + "And though this world, with devils filled, should threaten to undo us,\r\nWe will not fear, for God hath willed His truth to triumph through us:\r\nThe Prince of Darkness grim, we tremble not for him;\r\nHis rage we can endure, for lo, his doom is sure,\r\nOne little word shall fell him.\r\n", + "v3" + ], + [ + "That word above all earthly powers, no thanks to them, abideth;\r\nThe Spirit and the gifts are ours through Him Who with us sideth:\r\nLet goods and kindred go, this mortal life also;\r\nThe body they may kill: God’s truth abideth still,\r\nHis kingdom is forever.\r\n", + "v4" + ] + ] +} \ No newline at end of file diff --git a/tests/resources/songshowplussongs/a mighty fortress is our god.sbsong b/tests/resources/songshowplussongs/a mighty fortress is our god.sbsong new file mode 100644 index 0000000000000000000000000000000000000000..b66d52b2b73ef827e1427a90d8b54dfae1808508 GIT binary patch literal 1342 zcmZXU%We}f6o$j4Ekq3<=n5fp7F@cB5H01RvOrZM2&gTUTG6#9J~OuBv4ibNlpU|Z z>+vG+pP8tN#9}-iU(V(G&zTp!UT;&L+ppj6eYkAg%Eeze!JJ+-4nDw!{x%Go%V%ppMdqi~?Tls%%LsC>UZlU6oJkL2&sjRcU z`Z(x+NBD-_42xsN!P;s<;8eO0G=-9C*i(+IbBSh==iSZ2K_3t(WvsUdl%H7knaaSV zLpGF{r<4ON0=zZ}Z-%=uh)tp@GbyiW78dZUB2yJvWw`emL#$cT!otWTHtfi#%tM6g ziNV$gbssVry!mIN+^a!fh&)~+vcI#9uMv`2FhLDbDJ(n!j_fP39DHdtGL{{z+BtY2 z$i`_Zm|RF5pDRXm;!U7LK}@F#_BxZPH6dH=VkwpI=htsk1$<3RXsv+NC?sT@rnE2t zmQ_{;| zWGieWXN~L>!Y>&EY_51cTH|%Fvw^Qm(XPFqiZExAOKnlQWmnA*(YF%&DRPw=BXU)s zP_jX&lHkS6Mkp;EAQDx!%&F}H)FLjec#LgLS16ZO3p9|_S~g&G!kH>`C+@())OsDk zwnCn*gsX;iwv_NvSUD|%UW&VATY6K7b$DH^ohGXwyQT&rQ47{9-GKv4`F8-#OEjDO Nw;tl@?XG{w!aqH)mM#DQ literal 0 HcmV?d00001 From 41c950b819f05ce06eae4ace47e317f813dab97b Mon Sep 17 00:00:00 2001 From: Jonathan Springer Date: Thu, 1 May 2014 08:53:49 -0400 Subject: [PATCH 12/42] merge trunk From b993af2e90d84c98e05442f8b0f945fe4de797c8 Mon Sep 17 00:00:00 2001 From: Samuel Mehrbrodt Date: Fri, 2 May 2014 10:04:11 +0200 Subject: [PATCH 13/42] No newline at end of file... --- .../songshowplussongs/a mighty fortress is our god.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/resources/songshowplussongs/a mighty fortress is our god.json b/tests/resources/songshowplussongs/a mighty fortress is our god.json index 7e3d400b4..2ab95781d 100644 --- a/tests/resources/songshowplussongs/a mighty fortress is our god.json +++ b/tests/resources/songshowplussongs/a mighty fortress is our god.json @@ -26,4 +26,5 @@ "v4" ] ] -} \ No newline at end of file +} + From 5d63820b174157c8c7714c39dc0e250557810d9f Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Fri, 2 May 2014 23:07:56 +0200 Subject: [PATCH 14/42] Added support for importing EW songs even if RTF is not escaped as espected, also fixed importing og songs with unicode in metadata. Fixes: https://launchpad.net/bugs/1299837 --- openlp/plugins/songs/lib/ewimport.py | 25 +++++++++++++----- .../openlp_plugins/songs/test_ewimport.py | 24 ++++++++++++++++- tests/resources/easyworshipsongs/Songs.DB | Bin 6144 -> 6144 bytes tests/resources/easyworshipsongs/Songs.MB | Bin 12288 -> 20480 bytes 4 files changed, 42 insertions(+), 7 deletions(-) diff --git a/openlp/plugins/songs/lib/ewimport.py b/openlp/plugins/songs/lib/ewimport.py index faa4122c8..604a70d81 100644 --- a/openlp/plugins/songs/lib/ewimport.py +++ b/openlp/plugins/songs/lib/ewimport.py @@ -281,7 +281,7 @@ class EasyWorshipSongImport(SongImport): raw_record = db_file.read(record_size) self.fields = self.record_structure.unpack(raw_record) self.set_defaults() - self.title = self.get_field(fi_title).decode() + self.title = self.get_field(fi_title).decode('unicode-escape') # Get remaining fields. copy = self.get_field(fi_copy) admin = self.get_field(fi_admin) @@ -289,16 +289,16 @@ class EasyWorshipSongImport(SongImport): authors = self.get_field(fi_author) words = self.get_field(fi_words) if copy: - self.copyright = copy.decode() + self.copyright = copy.decode('unicode-escape') if admin: if copy: self.copyright += ', ' self.copyright += translate('SongsPlugin.EasyWorshipSongImport', - 'Administered by %s') % admin.decode() + 'Administered by %s') % admin.decode('unicode-escape') if ccli: - self.ccli_number = ccli.decode() + self.ccli_number = ccli.decode('unicode-escape') if authors: - authors = authors.decode() + authors = authors.decode('unicode-escape') else: authors = '' # Set the SongImport object members. @@ -328,7 +328,20 @@ class EasyWorshipSongImport(SongImport): self.add_author(author_name.strip()) if words: # Format the lyrics - result = strip_rtf(words.decode(), self.encoding) + result = None + decoded_words = None + try: + decoded_words = words.decode() + except UnicodeDecodeError: + log.debug('The unicode chars in the rtf was not escaped in the expected manor, doing it manually.') + newbytes = bytearray() + for b in words: + if b > 127: + newbytes += bytearray(b'\\\'') + bytearray(str(hex(b))[-2:].encode()) + else: + newbytes.append(b) + decoded_words = newbytes.decode() + result = strip_rtf(decoded_words, self.encoding) if result is None: return words, self.encoding = result diff --git a/tests/functional/openlp_plugins/songs/test_ewimport.py b/tests/functional/openlp_plugins/songs/test_ewimport.py index 49bc367cd..e93ce9517 100644 --- a/tests/functional/openlp_plugins/songs/test_ewimport.py +++ b/tests/functional/openlp_plugins/songs/test_ewimport.py @@ -67,7 +67,21 @@ SONG_TEST_DATA = [ 'Just to learn from His lips, words of comfort,\nIn the beautiful garden of prayer.', 'v2'), ('There\'s a garden where Jesus is waiting,\nAnd He bids you to come meet Him there,\n' 'Just to bow and receive a new blessing,\nIn the beautiful garden of prayer.', 'v3')], - 'verse_order_list': []}] + 'verse_order_list': []}, + {'title': 'Vi pløjed og vi så\'de', + 'authors': ['Matthias Claudius'], + 'copyright': 'Public Domain', + 'ccli_number': 0, + 'verses': + [('Vi pløjed og vi så\'de\nvor sæd i sorten jord,\nså bad vi ham os hjælpe,\nsom højt i Himlen bor,\n' + 'og han lod snefald hegne\nmod frosten barsk og hård,\nhan lod det tø og regne\nog varme mildt i vår.', + 'v1'), + ('Alle gode gaver\nde kommer ovenned,\nså tak da Gud, ja, pris dog Gud\nfor al hans kærlighed!', 'c1'), + ('Han er jo den, hvis vilje\nopholder alle ting,\nhan klæder markens lilje\nog runder himlens ring,\n' + 'ham lyder vind og vove,\nham rører ravnes nød,\nhvi skulle ej hans småbørn\nda og få dagligt brød?', 'v2'), + ('Ja, tak, du kære Fader,\nså mild, så rig, så rund,\nfor korn i hæs og lader,\nfor godt i allen stund!\n' + 'Vi kan jo intet give,\nsom nogen ting er værd,\nmen tag vort stakkels hjerte,\nså ringe som det er!', 'v3')], + 'verse_order_list': []}] EWS_SONG_TEST_DATA =\ {'title': 'Vi pløjed og vi så\'de', @@ -139,6 +153,14 @@ class TestEasyWorshipSongImport(TestCase): """ Test the functions in the :mod:`ewimport` module. """ + def setUp(self): + self.songimport_patcher = patch('openlp.plugins.songs.lib.ewimport.EasyWorshipSongImport.__init__') + self.mocked_songimport = self.songimport_patcher.start() + self.mocked_songimport.return_value = None + + def tearDown(self): + self.songimport_patcher.stop() + def create_field_desc_entry_test(self): """ Test creating an instance of the :class`FieldDescEntry` class. diff --git a/tests/resources/easyworshipsongs/Songs.DB b/tests/resources/easyworshipsongs/Songs.DB index 8c9679b86a8bacecdd559011139959ccbd0c155a..b6a13abc5b28bd7fbf670ba370ad6517fc2e7cb9 100644 GIT binary patch delta 492 zcmXZYKS/zXg?^7pjlLZH2RANuvX#*#CoOYx>+ z=~6ie-PEo7(T)xdF6y95?b2|dE)Ip#p@Nb=P~V3i@54L3zUiB#r37>&;sCVUq}biP zrkb;UD%JvGK#SqzbI2by)yY9~v-BXjecD?tZ;Dsze}*G

>7rSg&Lpd1xwil%9v zDkSJFeWWc4X_t=ZJ6+H(x}kI-Qdu&{qQ|sIit4mMK_M!uFDzf_fPT<9{ibWui;=oV zgY<}=lBD%w6n@Ye@sSwfn7}v^NFvQ=w4oh$(1A{Lp&LEOpoCsz(T9h@LNb>rViYDU zjA0VCwnYN7SnzY^Ed0Qh_6QXKXUbuB(jg_Y=HQ{hqmj9nyCeWV^ npLGpt*}cQFflF%`{;a4Pvv$=}BK+Jvu7!#Ael7fz{HFZ_Ud61z delta 356 zcmXZYJ4gdj5Czb?n|*O(;@{Qy0Sg;Nl!(Y$tjVSmI}uw!R*UdRWg)2yf&r@-6+uv} z)D(8Funh?5M69(?rxL703qjCZIKzQEOf^%^lrw(hz=dN2u>L#69K65kpemYi5?ubW zS=lg5i5cTF%Y`Z{#UVC6KO}7Yw*iEuo*`ZO! z0wS>@+er#5gx*O~Rg0ZNIyBhZYag6{uRl1r@y%No&UYIhdWG0X+&nZ<|MUHYetG-wSn_jQLpD zX@4---I}eN(ql*72b-@bDhk})6%G^{4&wMGE zGqujPx?`V~+%v}~B4eCQt?t_$b$79?kfE3K%($tonuv}W_Svt4( zBlr@Tyt6M$Yv4RqaedBEXcUO=EjUmr#^D2}xfL$JkteJ~JTk7V;MqAFnxIhJJe7-y zS5oLSwqxQUb?{uko$zb^o+jQ@D#aA6CioI|e*{P3UE0-=?@FQBRBVFm6m=oxQwv6# z5vDsi^PJ+S`yGC^lA_#|5(P`az<-moYaK8>-Zchm1EL*5lAiWB-rVbh)t6?%HGj ze^Uaww`;#vlRj1d|4V5sitGRZ;Mb;XOa;^gnb(RHP$Gmz&w&PNHfAQLy6;?sbddMo z<{ElCq^6|O8jb01d?Jlye9EOq*F-h;v0!E_^sF{6xEBEh_o=y;svFPn;bnpVN1sv$ zf)buD+=?KLlmJ8?rIW*PFP`PPC)FXHKmOv z=7!KH0(|_YhFXKJ6TQCGEVrg={Ho*_F+DXlbL0jn7daMR0=#_EH07Vx$3aTbhYn}* zG4f|B!T7nU$tR>2L4Schd@L)9JsT2d3s0vc-r{DE0)-@XifJ*05DN_=EFmp-anu|h za32>SvLfdy!%};p1Nf`}gloyY(U<~z&?(2e_(XYSpKK!>)42b%aVK|vTwRWcE57AeQ9;2qs96$q7amy z8Pq&f?TL^Cdp$^gn~YOE)Twd|w#8zK23PXZC!6h|aRsz3`7!r12oz_LkZ z*o?DQpL~y%6;tN~IKk$p<{g1a9FWQ>ds|937MPY#v~Wz*-yu-}=Q1~{$t&V)Hi2D5 zsV8mjq`OZ;L>a;=CoDuXUkq Date: Fri, 2 May 2014 23:48:59 +0200 Subject: [PATCH 15/42] fixes for tests --- openlp/plugins/songs/lib/ewimport.py | 2 +- .../openlp_plugins/songs/test_ewimport.py | 37 +++++++++++++++++- tests/resources/easyworshipsongs/Songs.DB | Bin 6144 -> 10240 bytes tests/resources/easyworshipsongs/Songs.MB | Bin 20480 -> 32768 bytes 4 files changed, 37 insertions(+), 2 deletions(-) diff --git a/openlp/plugins/songs/lib/ewimport.py b/openlp/plugins/songs/lib/ewimport.py index 604a70d81..e12b7e181 100644 --- a/openlp/plugins/songs/lib/ewimport.py +++ b/openlp/plugins/songs/lib/ewimport.py @@ -333,7 +333,7 @@ class EasyWorshipSongImport(SongImport): try: decoded_words = words.decode() except UnicodeDecodeError: - log.debug('The unicode chars in the rtf was not escaped in the expected manor, doing it manually.') + # The unicode chars in the rtf was not escaped in the expected manor, doing it manually. newbytes = bytearray() for b in words: if b > 127: diff --git a/tests/functional/openlp_plugins/songs/test_ewimport.py b/tests/functional/openlp_plugins/songs/test_ewimport.py index e93ce9517..e6344e39b 100644 --- a/tests/functional/openlp_plugins/songs/test_ewimport.py +++ b/tests/functional/openlp_plugins/songs/test_ewimport.py @@ -153,13 +153,14 @@ class TestEasyWorshipSongImport(TestCase): """ Test the functions in the :mod:`ewimport` module. """ - def setUp(self): + """def setUp(self): self.songimport_patcher = patch('openlp.plugins.songs.lib.ewimport.EasyWorshipSongImport.__init__') self.mocked_songimport = self.songimport_patcher.start() self.mocked_songimport.return_value = None def tearDown(self): self.songimport_patcher.stop() + """ def create_field_desc_entry_test(self): """ @@ -489,3 +490,37 @@ class TestEasyWorshipSongImport(TestCase): for verse_text, verse_tag in EWS_SONG_TEST_DATA['verses']: mocked_add_verse.assert_any_call(verse_text, verse_tag) mocked_finish.assert_called_with() + + def import_rtf_unescaped_unicode_test(self): + """ + Test import of rtf without the expected escaping of unicode + """ + + # GIVEN: Test files with a mocked out SongImport class, a mocked out "manager", a mocked out "import_wizard", + # and mocked out "author", "add_copyright", "add_verse", "finish" methods. + with patch('openlp.plugins.songs.lib.ewimport.SongImport'), \ + patch('openlp.plugins.songs.lib.ewimport.strip_rtf') as mocked_strip_rtf, \ + patch('openlp.plugins.songs.lib.ewimport.retrieve_windows_encoding') \ + as mocked_retrieve_windows_encoding: + mocked_retrieve_windows_encoding.return_value = 'cp1252' + mocked_manager = MagicMock() + mocked_import_wizard = MagicMock() + mocked_add_author = MagicMock() + mocked_add_verse = MagicMock() + mocked_finish = MagicMock() + mocked_title = MagicMock() + mocked_finish.return_value = True + importer = EasyWorshipSongImportLogger(mocked_manager) + importer.import_wizard = mocked_import_wizard + importer.stop_import_flag = False + importer.add_author = mocked_add_author + importer.add_verse = mocked_add_verse + importer.title = mocked_title + importer.finish = mocked_finish + importer.topics = [] + + # WHEN: running set_song_import_object on a verse string without the needed escaping + importer.set_song_import_object('Test Author', b'Det som var fr\x86n begynnelsen') + + # THEN: The escaping shoud be added + mocked_strip_rtf.assert_called_with("Det som var fr\'86n begynnelsen", 'cp1252') diff --git a/tests/resources/easyworshipsongs/Songs.DB b/tests/resources/easyworshipsongs/Songs.DB index b6a13abc5b28bd7fbf670ba370ad6517fc2e7cb9..3476950578a9374493f8fc0c2d318652526ec414 100644 GIT binary patch delta 246 zcmZoLXb9j%8!klf8XU#5V8;V(DHl*R^zh6V z%#&<;1EYq?j9j9d?YR{hIT?V;fslb=b0*Ij7Kp)ou jiKl~+Re*tE6ZhtLzFelwnLKA$Hs?$HV&1H;dXWhL78Mjk diff --git a/tests/resources/easyworshipsongs/Songs.MB b/tests/resources/easyworshipsongs/Songs.MB index f5c7ad54cd12d287485e8e254e2ee1c1db26590e..949d7755c20d8efd6d91c96f791d26cb61069c44 100644 GIT binary patch delta 1089 zcmZXT&u$Yj5XN`Yw2D+DQd*U?gk%8GKT?HKK`TT!KsnHIq!Jf;ak}1(6R$V2ofWx- z69+Cx%LDKVG-sr~2QSfMFG$STi6C&vX6^BBzV93F_**z0m%cn*UT6hDDOjimLHK?D z$IVJP3@(;~AedCD*Ud_~6x3JUTkE=c(R#RAwjXS#xLmDIb{~HYi>sZL;&NxH__@`7 zaB78=40iCn2syV%#Q&YYISt$~SY&k;Gh?CKqg^@R8jF)h)T;ROe3vBNcqbyHE9f#6 z(Z(8yw0e{zU1aA%DXv}XdaM~DNwi^7&^E_ou3!#{u3yd^r%pY2&PhVzBFM3o_Ks^g z(~NW`$P(U4pGoODu3%2Sq19*G@u9IKa3eeKg0Zv^QGD^ChCjdt?@cwj3d;?tq$4q6 z=X7oyp-BeA!C(*YlomMy#iOa+`=nO`9`0*F5Ca1#`qr_!R5k~5qaN4V_35a+amv!o z6lX3XM)I3Zi<52Wx6dGPZ}`M{JL8)vkC=jpVJZggq$$&2P{$OZM%MNi#9o*iHFcu9 zbYShAE;v<8TkvKK8o{)YhqjC)ydN!TA_4}kVW_br!U{_Tb2R7jWV79zx^zQT$RvP! zk^L-H&ZxiNM4kFDa_G~OD&tjV?yzj_x>StHk zCF^r1^#XH|I9yB@&!ZDcf4wuZ%s`sq*Ml``#7bfCYq?l#y(*5Yx5E9&`|6#g;>FhO a85J!bO|I78hW{)sO~$p)|1X|w%EjL)3vt%~ delta 38 ucmZo@U}{*vIKg6L+#>#o32Gcnj0~H&85kHha|ry9-xQ!Kyjj)xHV**mn+vJ{ From e8c7547ab25a956f23a2ce071efc8d6c61f91f26 Mon Sep 17 00:00:00 2001 From: Samuel Mehrbrodt Date: Sat, 3 May 2014 10:47:31 +0200 Subject: [PATCH 16/42] Try to get ccli number even if there is text in the field --- openlp/plugins/songs/lib/songshowplusimport.py | 8 ++++---- .../songshowplussongs/a mighty fortress is our god.json | 1 + 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/openlp/plugins/songs/lib/songshowplusimport.py b/openlp/plugins/songs/lib/songshowplusimport.py index c1c6d04cb..fe81b61a2 100644 --- a/openlp/plugins/songs/lib/songshowplusimport.py +++ b/openlp/plugins/songs/lib/songshowplusimport.py @@ -147,10 +147,10 @@ class SongShowPlusImport(SongImport): elif block_key == COPYRIGHT: self.add_copyright(self.decode(data)) elif block_key == CCLI_NO: - try: - self.ccli_number = int(data) - except ValueError: - continue + # Try to get the CCLI number even if the field contains additional text + match = re.search(r'\d+', self.decode(data)) + if match: + self.ccli_number = int(match.group()) elif block_key == VERSE: self.add_verse(self.decode(data), "%s%s" % (VerseType.tags[VerseType.Verse], verse_no)) elif block_key == CHORUS: diff --git a/tests/resources/songshowplussongs/a mighty fortress is our god.json b/tests/resources/songshowplussongs/a mighty fortress is our god.json index 2ab95781d..2788ad05c 100644 --- a/tests/resources/songshowplussongs/a mighty fortress is our god.json +++ b/tests/resources/songshowplussongs/a mighty fortress is our god.json @@ -2,6 +2,7 @@ "authors": [ "Martin Luther" ], + "ccli_number": 12456, "comments": "", "copyright": "Public Domain", "song_number": 0, From e0d813db3f6ed8ad8dc88b4c7c886561f1145e98 Mon Sep 17 00:00:00 2001 From: Samuel Mehrbrodt Date: Sat, 3 May 2014 12:03:50 +0200 Subject: [PATCH 17/42] Add an option to display the songbook in the footer --- openlp/plugins/songs/lib/mediaitem.py | 8 +++++--- openlp/plugins/songs/lib/songstab.py | 11 +++++++++++ openlp/plugins/songs/songsplugin.py | 1 + 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/openlp/plugins/songs/lib/mediaitem.py b/openlp/plugins/songs/lib/mediaitem.py index 32730ce3c..e2cb0f141 100644 --- a/openlp/plugins/songs/lib/mediaitem.py +++ b/openlp/plugins/songs/lib/mediaitem.py @@ -36,8 +36,8 @@ from PyQt4 import QtCore, QtGui from sqlalchemy.sql import or_ from openlp.core.common import Registry, AppLocation, Settings, check_directory_exists, UiStrings, translate -from openlp.core.lib import MediaManagerItem, ItemCapabilities, PluginStatus, ServiceItemContext, check_item_selected, \ - create_separated_list +from openlp.core.lib import MediaManagerItem, ItemCapabilities, PluginStatus, ServiceItem, ServiceItemContext, \ + check_item_selected, create_separated_list from openlp.core.lib.ui import create_widget_action from openlp.plugins.songs.forms.editsongform import EditSongForm from openlp.plugins.songs.forms.songmaintenanceform import SongMaintenanceForm @@ -460,7 +460,7 @@ class SongMediaItem(MediaManagerItem): service_item.background_audio = [m.file_name for m in song.media_files] return True - def generate_footer(self, item, song): + def generate_footer(self, item: ServiceItem, song: Song): """ Generates the song footer based on a song and adds details to a service item. @@ -506,6 +506,8 @@ class SongMediaItem(MediaManagerItem): item.raw_footer.append("%s: %s" % (AuthorType.Types[AuthorType.Translation], create_separated_list(authors_translation))) item.raw_footer.append(song.copyright) + if Settings().value('songs/display songbook') and song.book: + item.raw_footer.append("%s #%s" % (song.book.name, song.song_number)) if Settings().value('core/ccli number'): item.raw_footer.append(translate('SongsPlugin.MediaItem', 'CCLI License: ') + Settings().value('core/ccli number')) diff --git a/openlp/plugins/songs/lib/songstab.py b/openlp/plugins/songs/lib/songstab.py index bf74a4e7c..1cf06d047 100644 --- a/openlp/plugins/songs/lib/songstab.py +++ b/openlp/plugins/songs/lib/songstab.py @@ -59,6 +59,9 @@ class SongsTab(SettingsTab): self.add_from_service_check_box = QtGui.QCheckBox(self.mode_group_box) self.add_from_service_check_box.setObjectName('add_from_service_check_box') self.mode_layout.addWidget(self.add_from_service_check_box) + self.display_songbook_check_box = QtGui.QCheckBox(self.mode_group_box) + self.display_songbook_check_box.setObjectName('songbook_check_box') + self.mode_layout.addWidget(self.display_songbook_check_box) self.left_layout.addWidget(self.mode_group_box) self.left_layout.addStretch() self.right_layout.addStretch() @@ -66,6 +69,7 @@ class SongsTab(SettingsTab): self.tool_bar_active_check_box.stateChanged.connect(self.on_tool_bar_active_check_box_changed) self.update_on_edit_check_box.stateChanged.connect(self.on_update_on_edit_check_box_changed) self.add_from_service_check_box.stateChanged.connect(self.on_add_from_service_check_box_changed) + self.display_songbook_check_box.stateChanged.connect(self.on_songbook_check_box_changed) def retranslateUi(self): self.mode_group_box.setTitle(translate('SongsPlugin.SongsTab', 'Songs Mode')) @@ -75,6 +79,7 @@ class SongsTab(SettingsTab): self.update_on_edit_check_box.setText(translate('SongsPlugin.SongsTab', 'Update service from song edit')) self.add_from_service_check_box.setText(translate('SongsPlugin.SongsTab', 'Import missing songs from service files')) + self.display_songbook_check_box.setText(translate('SongsPlugin.SongsTab', 'Display songbook in footer')) def on_search_as_type_check_box_changed(self, check_state): self.song_search = (check_state == QtCore.Qt.Checked) @@ -88,6 +93,9 @@ class SongsTab(SettingsTab): def on_add_from_service_check_box_changed(self, check_state): self.update_load = (check_state == QtCore.Qt.Checked) + def on_songbook_check_box_changed(self, check_state): + self.display_songbook = (check_state == QtCore.Qt.Checked) + def load(self): settings = Settings() settings.beginGroup(self.settings_section) @@ -95,10 +103,12 @@ class SongsTab(SettingsTab): self.tool_bar = settings.value('display songbar') self.update_edit = settings.value('update service on edit') self.update_load = settings.value('add song from service') + self.display_songbook = settings.value('display songbook') self.search_as_type_check_box.setChecked(self.song_search) self.tool_bar_active_check_box.setChecked(self.tool_bar) self.update_on_edit_check_box.setChecked(self.update_edit) self.add_from_service_check_box.setChecked(self.update_load) + self.display_songbook_check_box.setChecked(self.display_songbook) settings.endGroup() def save(self): @@ -108,6 +118,7 @@ class SongsTab(SettingsTab): settings.setValue('display songbar', self.tool_bar) settings.setValue('update service on edit', self.update_edit) settings.setValue('add song from service', self.update_load) + settings.setValue('display songbook', self.display_songbook) settings.endGroup() if self.tab_visited: self.settings_form.register_post_process('songs_config_updated') diff --git a/openlp/plugins/songs/songsplugin.py b/openlp/plugins/songs/songsplugin.py index b1ddaf412..79fc282a6 100644 --- a/openlp/plugins/songs/songsplugin.py +++ b/openlp/plugins/songs/songsplugin.py @@ -63,6 +63,7 @@ __default_settings__ = { 'songs/search as type': False, 'songs/add song from service': True, 'songs/display songbar': True, + 'songs/display songbook': False, 'songs/last directory import': '', 'songs/last directory export': '', 'songs/songselect username': '', From a98ea19306d59217e802f8a1362167481b073735 Mon Sep 17 00:00:00 2001 From: Samuel Mehrbrodt Date: Sat, 3 May 2014 12:42:18 +0200 Subject: [PATCH 18/42] Add test for songbook display --- openlp/plugins/songs/lib/mediaitem.py | 5 ++-- .../openlp_plugins/songs/test_mediaitem.py | 29 +++++++++++++++++-- 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/openlp/plugins/songs/lib/mediaitem.py b/openlp/plugins/songs/lib/mediaitem.py index e2cb0f141..413498af6 100644 --- a/openlp/plugins/songs/lib/mediaitem.py +++ b/openlp/plugins/songs/lib/mediaitem.py @@ -124,7 +124,8 @@ class SongMediaItem(MediaManagerItem): log.debug('config_updated') self.search_as_you_type = Settings().value(self.settings_section + '/search as type') self.update_service_on_edit = Settings().value(self.settings_section + '/update service on edit') - self.add_song_from_service = Settings().value(self.settings_section + '/add song from service',) + self.add_song_from_service = Settings().value(self.settings_section + '/add song from service') + self.display_songbook = Settings().value(self.settings_section + '/display songbook') def retranslateUi(self): self.search_text_label.setText('%s:' % UiStrings().Search) @@ -506,7 +507,7 @@ class SongMediaItem(MediaManagerItem): item.raw_footer.append("%s: %s" % (AuthorType.Types[AuthorType.Translation], create_separated_list(authors_translation))) item.raw_footer.append(song.copyright) - if Settings().value('songs/display songbook') and song.book: + if self.display_songbook and song.book: item.raw_footer.append("%s #%s" % (song.book.name, song.song_number)) if Settings().value('core/ccli number'): item.raw_footer.append(translate('SongsPlugin.MediaItem', diff --git a/tests/functional/openlp_plugins/songs/test_mediaitem.py b/tests/functional/openlp_plugins/songs/test_mediaitem.py index 308881c2e..824b57a20 100644 --- a/tests/functional/openlp_plugins/songs/test_mediaitem.py +++ b/tests/functional/openlp_plugins/songs/test_mediaitem.py @@ -1,8 +1,6 @@ """ This module contains tests for the lib submodule of the Songs plugin. """ -import os -from tempfile import mkstemp from unittest import TestCase from PyQt4 import QtCore, QtGui @@ -29,6 +27,7 @@ class TestMediaItem(TestCase, TestMixin): with patch('openlp.core.lib.mediamanageritem.MediaManagerItem._setup'), \ patch('openlp.plugins.songs.forms.editsongform.EditSongForm.__init__'): self.media_item = SongMediaItem(None, MagicMock()) + self.media_item.display_songbook = False self.get_application() self.build_settings() QtCore.QLocale.setDefault(QtCore.QLocale('en_GB')) @@ -128,3 +127,29 @@ class TestMediaItem(TestCase, TestMixin): # THEN: I would get an amended footer string self.assertEqual(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') + + def build_song_footer_base_songbook_test(self): + """ + Test build songs footer with basic song and a songbook + """ + # 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.book = MagicMock() + mock_song.book.name = "My songbook" + mock_song.song_number = 12 + service_item = ServiceItem(None) + + # WHEN: I generate the Footer with default settings + self.media_item.generate_footer(service_item, mock_song) + + # THEN: The songbook should not be in the footer + self.assertEqual(service_item.raw_footer, ['My Song', 'My copyright']) + + # WHEN: I activate the "display songbook" option + self.media_item.display_songbook = True + self.media_item.generate_footer(service_item, mock_song) + + # THEN: The songbook should be in the footer + self.assertEqual(service_item.raw_footer, ['My Song', 'My copyright', 'My songbook #12']) From 922bbc3b57219b1789a1e4b7da81d185c549e35a Mon Sep 17 00:00:00 2001 From: Samuel Mehrbrodt Date: Sat, 3 May 2014 12:53:51 +0200 Subject: [PATCH 19/42] Typo, remove annotations --- openlp/plugins/songs/lib/mediaitem.py | 2 +- tests/functional/openlp_plugins/songs/test_mediaitem.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/openlp/plugins/songs/lib/mediaitem.py b/openlp/plugins/songs/lib/mediaitem.py index 413498af6..699f812e3 100644 --- a/openlp/plugins/songs/lib/mediaitem.py +++ b/openlp/plugins/songs/lib/mediaitem.py @@ -461,7 +461,7 @@ class SongMediaItem(MediaManagerItem): service_item.background_audio = [m.file_name for m in song.media_files] return True - def generate_footer(self, item: ServiceItem, song: Song): + def generate_footer(self, item, song): """ Generates the song footer based on a song and adds details to a service item. diff --git a/tests/functional/openlp_plugins/songs/test_mediaitem.py b/tests/functional/openlp_plugins/songs/test_mediaitem.py index 824b57a20..22291c6a6 100644 --- a/tests/functional/openlp_plugins/songs/test_mediaitem.py +++ b/tests/functional/openlp_plugins/songs/test_mediaitem.py @@ -132,7 +132,7 @@ class TestMediaItem(TestCase, TestMixin): """ Test build songs footer with basic song and a songbook """ - # GIVEN: A Song and a Service Item and a configured CCLI license + # GIVEN: A Song and a Service Item mock_song = MagicMock() mock_song.title = 'My Song' mock_song.copyright = 'My copyright' From 8b76dcc216526619c82616193887c7a0dbc6d425 Mon Sep 17 00:00:00 2001 From: Samuel Mehrbrodt Date: Sat, 3 May 2014 14:56:58 +0200 Subject: [PATCH 20/42] Fix bug 1310523 --- openlp/plugins/songs/lib/xml.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openlp/plugins/songs/lib/xml.py b/openlp/plugins/songs/lib/xml.py index b856cb53f..87e5da21e 100644 --- a/openlp/plugins/songs/lib/xml.py +++ b/openlp/plugins/songs/lib/xml.py @@ -310,9 +310,9 @@ class OpenLyrics(object): verse_tag = verse[0]['type'][0].lower() verse_number = verse[0]['label'] verse_def = verse_tag + verse_number - verse_tags.append(verse_def) # Create the letter from the number of duplicates - verse[0]['suffix'] = chr(96 + verse_tags.count(verse_def)) + verse[0][u'suffix'] = chr(97 + (verse_tags.count(verse_def) % 26)) + verse_tags.append(verse_def) # If the verse tag is a duplicate use the suffix letter for verse in verse_list: verse_tag = verse[0]['type'][0].lower() From 938f59416d2b89d20e41730d3ea8f1b6f14f913b Mon Sep 17 00:00:00 2001 From: Samuel Mehrbrodt Date: Sat, 3 May 2014 15:46:48 +0200 Subject: [PATCH 21/42] Fix bug 1199639 Fixes: https://launchpad.net/bugs/1199639 --- openlp/plugins/songs/forms/editsongform.py | 36 ++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/openlp/plugins/songs/forms/editsongform.py b/openlp/plugins/songs/forms/editsongform.py index 1814655ea..81a66e3f7 100644 --- a/openlp/plugins/songs/forms/editsongform.py +++ b/openlp/plugins/songs/forms/editsongform.py @@ -107,6 +107,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog, RegistryProperties): self.audio_list_widget.setAlternatingRowColors(True) self.find_verse_split = re.compile('---\[\]---\n', re.UNICODE) self.whitespace = re.compile(r'\W+', re.UNICODE) + self.find_tags = re.compile(u'\{/?\w+\}', re.UNICODE) def _load_objects(self, cls, combo, cache): """ @@ -234,8 +235,43 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog, RegistryProperties): self.manager.save_object(book) else: return False + # Validate tags (lp#1199639) + misplaced_tags = [] + for i in range(self.verse_list_widget.rowCount()): + item = self.verse_list_widget.item(i, 0) + tags = self.find_tags.findall(item.text()) + if not self._validate_tags(tags): + field = item.data(QtCore.Qt.UserRole) + misplaced_tags.append('%s %s' % (VerseType.translated_name(field[0]), field[1:])) + if misplaced_tags: + critical_error_message_box( + message=translate('SongsPlugin.EditSongForm', + 'There are misplaced formatting tags in the following verses:\n\n%s\n\n' + 'Please correct these tags before continuing.' % ', '.join(misplaced_tags))) + return False return True + def _validate_tags(self, _tags): + """ + Validates a list of tags + Deletes the first affiliated tag pair which is located side by side in the list + and call itself recursively with the shortened tag list. + If there is any misplaced tag in the list, either the length of the tag list is not even, + or the function won't find any tag pairs side by side. + If there is no misplaced tag, the length of the list will be zero on any recursive run. + + :return: True if the function can't find any mismatched tags. Else False. + """ + if len(_tags) == 0: + return True + if len(_tags) % 2 != 0: + return False + for i in range(len(_tags)-1): + if _tags[i+1] == "{/" + _tags[i][1:]: + del _tags[i:i+2] + return self._validate_tags(_tags) + return False + def _process_lyrics(self): """ Process the lyric data entered by the user into the OpenLP XML format. From a7bdb9dfa0962b96c411859037707cedb4d13e1f Mon Sep 17 00:00:00 2001 From: Samuel Mehrbrodt Date: Sat, 3 May 2014 15:56:32 +0200 Subject: [PATCH 22/42] Fix bug 1310523 Fixes: https://launchpad.net/bugs/1310523 --- openlp/plugins/songs/forms/editsongform.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/openlp/plugins/songs/forms/editsongform.py b/openlp/plugins/songs/forms/editsongform.py index 81a66e3f7..992cb533c 100644 --- a/openlp/plugins/songs/forms/editsongform.py +++ b/openlp/plugins/songs/forms/editsongform.py @@ -237,11 +237,13 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog, RegistryProperties): return False # Validate tags (lp#1199639) misplaced_tags = [] + verse_tags = [] for i in range(self.verse_list_widget.rowCount()): item = self.verse_list_widget.item(i, 0) tags = self.find_tags.findall(item.text()) + field = item.data(QtCore.Qt.UserRole) + verse_tags.append(field) if not self._validate_tags(tags): - field = item.data(QtCore.Qt.UserRole) misplaced_tags.append('%s %s' % (VerseType.translated_name(field[0]), field[1:])) if misplaced_tags: critical_error_message_box( @@ -249,6 +251,17 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog, RegistryProperties): 'There are misplaced formatting tags in the following verses:\n\n%s\n\n' 'Please correct these tags before continuing.' % ', '.join(misplaced_tags))) return False + for tag in verse_tags: + if verse_tags.count(tag) > 26: + # lp#1310523: OpenLyrics allows only a-z variants of one verse: + # http://openlyrics.info/dataformat.html#verse-name + critical_error_message_box(message=translate( + 'SongsPlugin.EditSongForm', 'You have %(count)s verses named %(name)s %(number)s. ' + 'You can have at most 26 verses with the same name' % + {'count': verse_tags.count(tag), + 'name': VerseType.translated_name(tag[0]), + 'number': tag[1:]})) + return False return True def _validate_tags(self, _tags): From afaf9480c317c8336a1a722a0813e515b047f810 Mon Sep 17 00:00:00 2001 From: Samuel Mehrbrodt Date: Sat, 3 May 2014 15:58:31 +0200 Subject: [PATCH 23/42] Rename variable --- openlp/plugins/songs/forms/editsongform.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/openlp/plugins/songs/forms/editsongform.py b/openlp/plugins/songs/forms/editsongform.py index 992cb533c..ae47a110f 100644 --- a/openlp/plugins/songs/forms/editsongform.py +++ b/openlp/plugins/songs/forms/editsongform.py @@ -264,7 +264,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog, RegistryProperties): return False return True - def _validate_tags(self, _tags): + def _validate_tags(self, tags): """ Validates a list of tags Deletes the first affiliated tag pair which is located side by side in the list @@ -273,16 +273,17 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog, RegistryProperties): or the function won't find any tag pairs side by side. If there is no misplaced tag, the length of the list will be zero on any recursive run. + :param tags: A list of tags :return: True if the function can't find any mismatched tags. Else False. """ - if len(_tags) == 0: + if len(tags) == 0: return True - if len(_tags) % 2 != 0: + if len(tags) % 2 != 0: return False - for i in range(len(_tags)-1): - if _tags[i+1] == "{/" + _tags[i][1:]: - del _tags[i:i+2] - return self._validate_tags(_tags) + for i in range(len(tags)-1): + if tags[i+1] == "{/" + tags[i][1:]: + del tags[i:i+2] + return self._validate_tags(tags) return False def _process_lyrics(self): From 635ab98f7301dedd8c5c820490e8b610a55cad34 Mon Sep 17 00:00:00 2001 From: Samuel Mehrbrodt Date: Sat, 3 May 2014 16:19:29 +0200 Subject: [PATCH 24/42] Fix bug 1216234 Fixes: https://launchpad.net/bugs/1216234 --- openlp/plugins/bibles/lib/mediaitem.py | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/openlp/plugins/bibles/lib/mediaitem.py b/openlp/plugins/bibles/lib/mediaitem.py index dd14c6409..76f91071a 100644 --- a/openlp/plugins/bibles/lib/mediaitem.py +++ b/openlp/plugins/bibles/lib/mediaitem.py @@ -60,7 +60,6 @@ class BibleMediaItem(MediaManagerItem): log.info('Bible Media Item loaded') def __init__(self, parent, plugin): - self.icon_path = 'songs/song' self.lock_icon = build_icon(':/bibles/bibles_search_lock.png') self.unlock_icon = build_icon(':/bibles/bibles_search_unlock.png') MediaManagerItem.__init__(self, parent, plugin) @@ -172,6 +171,7 @@ class BibleMediaItem(MediaManagerItem): self.page_layout.addWidget(tab) tab.setVisible(False) lock_button.toggled.connect(self.on_lock_button_toggled) + second_combo_box.currentIndexChanged.connect(self.on_second_bible_combobox_index_changed) setattr(self, prefix + 'VersionLabel', version_label) setattr(self, prefix + 'VersionComboBox', version_combo_box) setattr(self, prefix + 'SecondLabel', second_label) @@ -263,11 +263,15 @@ class BibleMediaItem(MediaManagerItem): def config_update(self): log.debug('config_update') if Settings().value(self.settings_section + '/second bibles'): + self.quickSecondLabel.setVisible(True) + self.quickSecondComboBox.setVisible(True) self.advancedSecondLabel.setVisible(True) self.advancedSecondComboBox.setVisible(True) self.quickSecondLabel.setVisible(True) self.quickSecondComboBox.setVisible(True) else: + self.quickSecondLabel.setVisible(False) + self.quickSecondComboBox.setVisible(False) self.advancedSecondLabel.setVisible(False) self.advancedSecondComboBox.setVisible(False) self.quickSecondLabel.setVisible(False) @@ -459,6 +463,17 @@ class BibleMediaItem(MediaManagerItem): books.sort(key=get_locale_key) set_case_insensitive_completer(books, self.quick_search_edit) + def on_second_bible_combobox_index_changed(self, selection): + """ + Activate the style combobox only when no second bible is selected + """ + if selection == 0: + self.quickStyleComboBox.setEnabled(True) + self.advancedStyleComboBox.setEnabled(True) + else: + self.quickStyleComboBox.setEnabled(False) + self.advancedStyleComboBox.setEnabled(False) + def on_import_click(self): if not hasattr(self, 'import_wizard'): self.import_wizard = BibleImportForm(self, self.plugin.manager, self.plugin) From a6a08bcfdd1b10cbfc0febb29766aaa5e05afe6a Mon Sep 17 00:00:00 2001 From: Samuel Mehrbrodt Date: Sat, 3 May 2014 17:01:43 +0200 Subject: [PATCH 25/42] Fix bug 1157938 Fixes: https://launchpad.net/bugs/1157938 --- .bzrignore | 1 + openlp/core/ui/aboutdialog.py | 2 +- openlp/core/ui/exceptiondialog.py | 3 ++- openlp/core/ui/filerenamedialog.py | 3 ++- openlp/core/ui/firsttimelanguagedialog.py | 2 ++ openlp/core/ui/firsttimewizard.py | 2 ++ openlp/core/ui/formattingtagdialog.py | 1 + openlp/core/ui/mainwindow.py | 2 +- openlp/core/ui/plugindialog.py | 2 ++ openlp/core/ui/printservicedialog.py | 1 + openlp/core/ui/serviceitemeditdialog.py | 2 ++ openlp/core/ui/settingsdialog.py | 2 +- openlp/core/ui/shortcutlistdialog.py | 1 + openlp/core/ui/starttimedialog.py | 2 ++ openlp/core/ui/themelayoutdialog.py | 2 ++ openlp/core/ui/themewizard.py | 1 + openlp/core/ui/wizard.py | 1 + openlp/plugins/alerts/forms/alertdialog.py | 2 +- openlp/plugins/bibles/forms/booknamedialog.py | 2 ++ openlp/plugins/bibles/forms/editbibledialog.py | 2 +- openlp/plugins/bibles/forms/languagedialog.py | 2 ++ openlp/plugins/custom/forms/editcustomdialog.py | 2 +- openlp/plugins/custom/forms/editcustomslidedialog.py | 3 ++- openlp/plugins/songs/forms/authorsdialog.py | 2 +- openlp/plugins/songs/forms/editsongdialog.py | 2 +- openlp/plugins/songs/forms/editversedialog.py | 1 + openlp/plugins/songs/forms/mediafilesdialog.py | 2 +- openlp/plugins/songs/forms/songbookdialog.py | 3 ++- openlp/plugins/songs/forms/songmaintenancedialog.py | 1 + openlp/plugins/songs/forms/topicsdialog.py | 3 ++- openlp/plugins/songusage/forms/songusagedeletedialog.py | 2 ++ openlp/plugins/songusage/forms/songusagedetaildialog.py | 1 + 32 files changed, 46 insertions(+), 14 deletions(-) diff --git a/.bzrignore b/.bzrignore index 6377150e0..a0c3f0b4f 100644 --- a/.bzrignore +++ b/.bzrignore @@ -32,3 +32,4 @@ tests.kdev4 *.orig __pycache__ *.dll +.directory diff --git a/openlp/core/ui/aboutdialog.py b/openlp/core/ui/aboutdialog.py index 276a073bb..251e0657c 100644 --- a/openlp/core/ui/aboutdialog.py +++ b/openlp/core/ui/aboutdialog.py @@ -44,7 +44,7 @@ class Ui_AboutDialog(object): Set up the UI for the dialog. """ about_dialog.setObjectName('about_dialog') - about_dialog.setWindowIcon(build_icon(':/icon/openlp-logo-16x16.png')) + about_dialog.setWindowIcon(build_icon(':/icon/openlp-logo.svg')) self.about_dialog_layout = QtGui.QVBoxLayout(about_dialog) self.about_dialog_layout.setObjectName('about_dialog_layout') self.logo_label = QtGui.QLabel(about_dialog) diff --git a/openlp/core/ui/exceptiondialog.py b/openlp/core/ui/exceptiondialog.py index b8b3941cd..329ed7797 100644 --- a/openlp/core/ui/exceptiondialog.py +++ b/openlp/core/ui/exceptiondialog.py @@ -32,7 +32,7 @@ The GUI widgets of the exception dialog. from PyQt4 import QtGui -from openlp.core.lib import translate +from openlp.core.lib import translate, build_icon from openlp.core.lib.ui import create_button, create_button_box @@ -45,6 +45,7 @@ class Ui_ExceptionDialog(object): Set up the UI. """ exception_dialog.setObjectName('exception_dialog') + exception_dialog.setWindowIcon(build_icon(u':/icon/openlp-logo.svg')) self.exception_layout = QtGui.QVBoxLayout(exception_dialog) self.exception_layout.setObjectName('exception_layout') self.message_layout = QtGui.QHBoxLayout() diff --git a/openlp/core/ui/filerenamedialog.py b/openlp/core/ui/filerenamedialog.py index 0900b82c3..4a316aece 100644 --- a/openlp/core/ui/filerenamedialog.py +++ b/openlp/core/ui/filerenamedialog.py @@ -31,7 +31,7 @@ The UI widgets for the rename dialog """ from PyQt4 import QtCore, QtGui -from openlp.core.lib import translate +from openlp.core.lib import translate, build_icon from openlp.core.lib.ui import create_button_box @@ -44,6 +44,7 @@ class Ui_FileRenameDialog(object): Set up the UI """ file_rename_dialog.setObjectName('file_rename_dialog') + file_rename_dialog.setWindowIcon(build_icon(u':/icon/openlp-logo.svg')) file_rename_dialog.resize(300, 10) self.dialog_layout = QtGui.QGridLayout(file_rename_dialog) self.dialog_layout.setObjectName('dialog_layout') diff --git a/openlp/core/ui/firsttimelanguagedialog.py b/openlp/core/ui/firsttimelanguagedialog.py index 10b341c2c..b4263e498 100644 --- a/openlp/core/ui/firsttimelanguagedialog.py +++ b/openlp/core/ui/firsttimelanguagedialog.py @@ -32,6 +32,7 @@ The UI widgets of the language selection dialog. from PyQt4 import QtGui from openlp.core.common import translate +from openlp.core.lib import build_icon from openlp.core.lib.ui import create_button_box @@ -44,6 +45,7 @@ class Ui_FirstTimeLanguageDialog(object): Set up the UI. """ language_dialog.setObjectName('language_dialog') + language_dialog.setWindowIcon(build_icon(u':/icon/openlp-logo.svg')) language_dialog.resize(300, 50) self.dialog_layout = QtGui.QVBoxLayout(language_dialog) self.dialog_layout.setContentsMargins(8, 8, 8, 8) diff --git a/openlp/core/ui/firsttimewizard.py b/openlp/core/ui/firsttimewizard.py index 1a270f931..35623ded2 100644 --- a/openlp/core/ui/firsttimewizard.py +++ b/openlp/core/ui/firsttimewizard.py @@ -34,6 +34,7 @@ from PyQt4 import QtCore, QtGui import sys from openlp.core.common import translate +from openlp.core.lib import build_icon from openlp.core.lib.ui import add_welcome_page @@ -60,6 +61,7 @@ class Ui_FirstTimeWizard(object): Set up the UI. """ first_time_wizard.setObjectName('first_time_wizard') + first_time_wizard.setWindowIcon(build_icon(u':/icon/openlp-logo.svg')) first_time_wizard.resize(550, 386) first_time_wizard.setModal(True) first_time_wizard.setWizardStyle(QtGui.QWizard.ModernStyle) diff --git a/openlp/core/ui/formattingtagdialog.py b/openlp/core/ui/formattingtagdialog.py index 387bca0a7..569405a05 100644 --- a/openlp/core/ui/formattingtagdialog.py +++ b/openlp/core/ui/formattingtagdialog.py @@ -45,6 +45,7 @@ class Ui_FormattingTagDialog(object): Set up the UI """ formatting_tag_dialog.setObjectName('formatting_tag_dialog') + formatting_tag_dialog.setWindowIcon(build_icon(u':/icon/openlp-logo.svg')) formatting_tag_dialog.resize(725, 548) self.list_data_grid_layout = QtGui.QVBoxLayout(formatting_tag_dialog) self.list_data_grid_layout.setMargin(8) diff --git a/openlp/core/ui/mainwindow.py b/openlp/core/ui/mainwindow.py index 9c193b079..5b5aa0781 100644 --- a/openlp/core/ui/mainwindow.py +++ b/openlp/core/ui/mainwindow.py @@ -89,7 +89,7 @@ class Ui_MainWindow(object): Set up the user interface """ main_window.setObjectName('MainWindow') - main_window.setWindowIcon(build_icon(':/icon/openlp-logo-64x64.png')) + main_window.setWindowIcon(build_icon(':/icon/openlp-logo.svg')) main_window.setDockNestingEnabled(True) # Set up the main container, which contains all the other form widgets. self.main_content = QtGui.QWidget(main_window) diff --git a/openlp/core/ui/plugindialog.py b/openlp/core/ui/plugindialog.py index f4d2d991b..40311677e 100644 --- a/openlp/core/ui/plugindialog.py +++ b/openlp/core/ui/plugindialog.py @@ -32,6 +32,7 @@ The UI widgets of the plugin view dialog from PyQt4 import QtCore, QtGui from openlp.core.common import UiStrings, translate +from openlp.core.lib import build_icon from openlp.core.lib.ui import create_button_box @@ -44,6 +45,7 @@ class Ui_PluginViewDialog(object): Set up the UI """ pluginViewDialog.setObjectName('pluginViewDialog') + pluginViewDialog.setWindowIcon(build_icon(u':/icon/openlp-logo.svg')) pluginViewDialog.setWindowModality(QtCore.Qt.ApplicationModal) self.plugin_layout = QtGui.QVBoxLayout(pluginViewDialog) self.plugin_layout.setObjectName('plugin_layout') diff --git a/openlp/core/ui/printservicedialog.py b/openlp/core/ui/printservicedialog.py index f59dcb044..0873a0b4a 100644 --- a/openlp/core/ui/printservicedialog.py +++ b/openlp/core/ui/printservicedialog.py @@ -56,6 +56,7 @@ class Ui_PrintServiceDialog(object): Set up the UI """ print_service_dialog.setObjectName('print_service_dialog') + print_service_dialog.setWindowIcon(build_icon(u':/icon/openlp-logo.svg')) print_service_dialog.resize(664, 594) self.main_layout = QtGui.QVBoxLayout(print_service_dialog) self.main_layout.setSpacing(0) diff --git a/openlp/core/ui/serviceitemeditdialog.py b/openlp/core/ui/serviceitemeditdialog.py index 76139c875..1fa19eb31 100644 --- a/openlp/core/ui/serviceitemeditdialog.py +++ b/openlp/core/ui/serviceitemeditdialog.py @@ -32,6 +32,7 @@ The UI widgets for the service item edit dialog from PyQt4 import QtGui from openlp.core.common import translate +from openlp.core.lib import build_icon from openlp.core.lib.ui import create_button_box, create_button @@ -44,6 +45,7 @@ class Ui_ServiceItemEditDialog(object): Set up the UI """ serviceItemEditDialog.setObjectName('serviceItemEditDialog') + serviceItemEditDialog.setWindowIcon(build_icon(u':/icon/openlp-logo.svg')) self.dialog_layout = QtGui.QGridLayout(serviceItemEditDialog) self.dialog_layout.setContentsMargins(8, 8, 8, 8) self.dialog_layout.setSpacing(8) diff --git a/openlp/core/ui/settingsdialog.py b/openlp/core/ui/settingsdialog.py index f625680d6..fbac6a155 100644 --- a/openlp/core/ui/settingsdialog.py +++ b/openlp/core/ui/settingsdialog.py @@ -45,8 +45,8 @@ class Ui_SettingsDialog(object): Set up the UI """ settings_dialog.setObjectName('settings_dialog') + settings_dialog.setWindowIcon(build_icon(u':/icon/openlp-logo.svg')) settings_dialog.resize(800, 500) - settings_dialog.setWindowIcon(build_icon(':/system/system_settings.png')) self.dialog_layout = QtGui.QGridLayout(settings_dialog) self.dialog_layout.setObjectName('dialog_layout') self.dialog_layout.setMargin(8) diff --git a/openlp/core/ui/shortcutlistdialog.py b/openlp/core/ui/shortcutlistdialog.py index 54433da24..ef2dc4056 100644 --- a/openlp/core/ui/shortcutlistdialog.py +++ b/openlp/core/ui/shortcutlistdialog.py @@ -66,6 +66,7 @@ class Ui_ShortcutListDialog(object): Set up the UI """ shortcutListDialog.setObjectName('shortcutListDialog') + shortcutListDialog.setWindowIcon(build_icon(u':/icon/openlp-logo.svg')) shortcutListDialog.resize(500, 438) self.shortcut_list_layout = QtGui.QVBoxLayout(shortcutListDialog) self.shortcut_list_layout.setObjectName('shortcut_list_layout') diff --git a/openlp/core/ui/starttimedialog.py b/openlp/core/ui/starttimedialog.py index 54e0629a4..cfd507bb2 100644 --- a/openlp/core/ui/starttimedialog.py +++ b/openlp/core/ui/starttimedialog.py @@ -32,6 +32,7 @@ The UI widgets for the time dialog from PyQt4 import QtCore, QtGui from openlp.core.common import UiStrings, translate +from openlp.core.lib import build_icon from openlp.core.lib.ui import create_button_box @@ -44,6 +45,7 @@ class Ui_StartTimeDialog(object): Set up the UI """ StartTimeDialog.setObjectName('StartTimeDialog') + StartTimeDialog.setWindowIcon(build_icon(u':/icon/openlp-logo.svg')) StartTimeDialog.resize(350, 10) self.dialog_layout = QtGui.QGridLayout(StartTimeDialog) self.dialog_layout.setObjectName('dialog_layout') diff --git a/openlp/core/ui/themelayoutdialog.py b/openlp/core/ui/themelayoutdialog.py index 023d6259c..d3fbeed2d 100644 --- a/openlp/core/ui/themelayoutdialog.py +++ b/openlp/core/ui/themelayoutdialog.py @@ -32,6 +32,7 @@ The layout of the theme from PyQt4 import QtGui from openlp.core.common import translate +from openlp.core.lib import build_icon from openlp.core.lib.ui import create_button_box @@ -44,6 +45,7 @@ class Ui_ThemeLayoutDialog(object): Set up the UI """ themeLayoutDialog.setObjectName('themeLayoutDialogDialog') + themeLayoutDialog.setWindowIcon(build_icon(u':/icon/openlp-logo.svg')) self.preview_layout = QtGui.QVBoxLayout(themeLayoutDialog) self.preview_layout.setObjectName('preview_layout') self.preview_area = QtGui.QWidget(themeLayoutDialog) diff --git a/openlp/core/ui/themewizard.py b/openlp/core/ui/themewizard.py index 77ccb0663..bda52c807 100644 --- a/openlp/core/ui/themewizard.py +++ b/openlp/core/ui/themewizard.py @@ -46,6 +46,7 @@ class Ui_ThemeWizard(object): Set up the UI """ themeWizard.setObjectName('OpenLP.ThemeWizard') + themeWizard.setWindowIcon(build_icon(u':/icon/openlp-logo.svg')) themeWizard.setModal(True) themeWizard.setWizardStyle(QtGui.QWizard.ModernStyle) themeWizard.setOptions(QtGui.QWizard.IndependentPages | diff --git a/openlp/core/ui/wizard.py b/openlp/core/ui/wizard.py index 5996296b5..908981dc6 100644 --- a/openlp/core/ui/wizard.py +++ b/openlp/core/ui/wizard.py @@ -118,6 +118,7 @@ class OpenLPWizard(QtGui.QWizard, RegistryProperties): """ Set up the wizard UI. """ + self.setWindowIcon(build_icon(u':/icon/openlp-logo.svg')) self.setModal(True) self.setWizardStyle(QtGui.QWizard.ModernStyle) self.setOptions(QtGui.QWizard.IndependentPages | diff --git a/openlp/plugins/alerts/forms/alertdialog.py b/openlp/plugins/alerts/forms/alertdialog.py index e4fd29a39..47e61365a 100644 --- a/openlp/plugins/alerts/forms/alertdialog.py +++ b/openlp/plugins/alerts/forms/alertdialog.py @@ -46,7 +46,7 @@ class Ui_AlertDialog(object): """ alert_dialog.setObjectName('alert_dialog') alert_dialog.resize(400, 300) - alert_dialog.setWindowIcon(build_icon(':/icon/openlp-logo-16x16.png')) + alert_dialog.setWindowIcon(build_icon(u':/icon/openlp-logo.svg')) self.alert_dialog_layout = QtGui.QGridLayout(alert_dialog) self.alert_dialog_layout.setObjectName('alert_dialog_layout') self.alert_text_layout = QtGui.QFormLayout() diff --git a/openlp/plugins/bibles/forms/booknamedialog.py b/openlp/plugins/bibles/forms/booknamedialog.py index 5903391c3..120caeff0 100644 --- a/openlp/plugins/bibles/forms/booknamedialog.py +++ b/openlp/plugins/bibles/forms/booknamedialog.py @@ -30,12 +30,14 @@ from PyQt4 import QtCore, QtGui from openlp.core.common import translate +from openlp.core.lib import build_icon from openlp.core.lib.ui import create_button_box class Ui_BookNameDialog(object): def setupUi(self, book_name_dialog): book_name_dialog.setObjectName('book_name_dialog') + book_name_dialog.setWindowIcon(build_icon(u':/icon/openlp-logo.svg')) book_name_dialog.resize(400, 271) self.book_name_layout = QtGui.QVBoxLayout(book_name_dialog) self.book_name_layout.setSpacing(8) diff --git a/openlp/plugins/bibles/forms/editbibledialog.py b/openlp/plugins/bibles/forms/editbibledialog.py index 1fbaa2f1e..e9e39a053 100644 --- a/openlp/plugins/bibles/forms/editbibledialog.py +++ b/openlp/plugins/bibles/forms/editbibledialog.py @@ -39,8 +39,8 @@ from openlp.plugins.bibles.lib.db import BiblesResourcesDB class Ui_EditBibleDialog(object): def setupUi(self, edit_bible_dialog): edit_bible_dialog.setObjectName('edit_bible_dialog') + edit_bible_dialog.setWindowIcon(build_icon(u':/icon/openlp-logo.svg')) edit_bible_dialog.resize(520, 400) - edit_bible_dialog.setWindowIcon(build_icon(':/icon/openlp-logo-16x16.png')) edit_bible_dialog.setModal(True) self.dialog_layout = QtGui.QVBoxLayout(edit_bible_dialog) self.dialog_layout.setSpacing(8) diff --git a/openlp/plugins/bibles/forms/languagedialog.py b/openlp/plugins/bibles/forms/languagedialog.py index 10382ea13..ab40503d2 100644 --- a/openlp/plugins/bibles/forms/languagedialog.py +++ b/openlp/plugins/bibles/forms/languagedialog.py @@ -30,12 +30,14 @@ from PyQt4 import QtGui from openlp.core.common import translate +from openlp.core.lib import build_icon from openlp.core.lib.ui import create_button_box class Ui_LanguageDialog(object): def setupUi(self, language_dialog): language_dialog.setObjectName('language_dialog') + language_dialog.setWindowIcon(build_icon(u':/icon/openlp-logo.svg')) language_dialog.resize(400, 165) self.language_layout = QtGui.QVBoxLayout(language_dialog) self.language_layout.setSpacing(8) diff --git a/openlp/plugins/custom/forms/editcustomdialog.py b/openlp/plugins/custom/forms/editcustomdialog.py index 22a33d921..5ed92f95e 100644 --- a/openlp/plugins/custom/forms/editcustomdialog.py +++ b/openlp/plugins/custom/forms/editcustomdialog.py @@ -41,8 +41,8 @@ class Ui_CustomEditDialog(object): :param custom_edit_dialog: The Dialog """ custom_edit_dialog.setObjectName('custom_edit_dialog') + custom_edit_dialog.setWindowIcon(build_icon(u':/icon/openlp-logo.svg')) custom_edit_dialog.resize(450, 350) - custom_edit_dialog.setWindowIcon(build_icon(':/icon/openlp-logo-16x16.png')) self.dialog_layout = QtGui.QVBoxLayout(custom_edit_dialog) self.dialog_layout.setObjectName('dialog_layout') self.title_layout = QtGui.QHBoxLayout() diff --git a/openlp/plugins/custom/forms/editcustomslidedialog.py b/openlp/plugins/custom/forms/editcustomslidedialog.py index 3b74566fc..c59cc4cd1 100644 --- a/openlp/plugins/custom/forms/editcustomslidedialog.py +++ b/openlp/plugins/custom/forms/editcustomslidedialog.py @@ -30,13 +30,14 @@ from PyQt4 import QtGui from openlp.core.common import UiStrings, translate -from openlp.core.lib import SpellTextEdit +from openlp.core.lib import SpellTextEdit, build_icon from openlp.core.lib.ui import create_button, create_button_box class Ui_CustomSlideEditDialog(object): def setupUi(self, custom_slide_edit_dialog): custom_slide_edit_dialog.setObjectName('custom_slide_edit_dialog') + custom_slide_edit_dialog.setWindowIcon(build_icon(u':/icon/openlp-logo.svg')) custom_slide_edit_dialog.resize(350, 300) self.dialog_layout = QtGui.QVBoxLayout(custom_slide_edit_dialog) self.slide_text_edit = SpellTextEdit(self) diff --git a/openlp/plugins/songs/forms/authorsdialog.py b/openlp/plugins/songs/forms/authorsdialog.py index 65fb169b0..c5a93894b 100644 --- a/openlp/plugins/songs/forms/authorsdialog.py +++ b/openlp/plugins/songs/forms/authorsdialog.py @@ -43,8 +43,8 @@ class Ui_AuthorsDialog(object): Set up the UI for the dialog. """ authors_dialog.setObjectName('authors_dialog') + authorsDialog.setWindowIcon(build_icon(u':/icon/openlp-logo.svg')) authors_dialog.resize(300, 10) - authors_dialog.setWindowIcon(build_icon(':/icon/openlp-logo-16x16.png')) authors_dialog.setModal(True) self.dialog_layout = QtGui.QVBoxLayout(authors_dialog) self.dialog_layout.setObjectName('dialog_layout') diff --git a/openlp/plugins/songs/forms/editsongdialog.py b/openlp/plugins/songs/forms/editsongdialog.py index d0fb51a2d..a9ca71946 100644 --- a/openlp/plugins/songs/forms/editsongdialog.py +++ b/openlp/plugins/songs/forms/editsongdialog.py @@ -43,8 +43,8 @@ class Ui_EditSongDialog(object): """ def setupUi(self, edit_song_dialog): edit_song_dialog.setObjectName('edit_song_dialog') + edit_song_dialog.setWindowIcon(build_icon(u':/icon/openlp-logo.svg')) edit_song_dialog.resize(650, 400) - edit_song_dialog.setWindowIcon(build_icon(':/icon/openlp-logo-16x16.png')) edit_song_dialog.setModal(True) self.dialog_layout = QtGui.QVBoxLayout(edit_song_dialog) self.dialog_layout.setSpacing(8) diff --git a/openlp/plugins/songs/forms/editversedialog.py b/openlp/plugins/songs/forms/editversedialog.py index f1901b203..1dc3d9182 100644 --- a/openlp/plugins/songs/forms/editversedialog.py +++ b/openlp/plugins/songs/forms/editversedialog.py @@ -37,6 +37,7 @@ from openlp.plugins.songs.lib import VerseType class Ui_EditVerseDialog(object): def setupUi(self, edit_verse_dialog): edit_verse_dialog.setObjectName('edit_verse_dialog') + edit_verse_dialog.setWindowIcon(build_icon(u':/icon/openlp-logo.svg')) edit_verse_dialog.resize(400, 400) edit_verse_dialog.setModal(True) self.dialog_layout = QtGui.QVBoxLayout(edit_verse_dialog) diff --git a/openlp/plugins/songs/forms/mediafilesdialog.py b/openlp/plugins/songs/forms/mediafilesdialog.py index 3a1db39ed..495e08883 100644 --- a/openlp/plugins/songs/forms/mediafilesdialog.py +++ b/openlp/plugins/songs/forms/mediafilesdialog.py @@ -42,10 +42,10 @@ class Ui_MediaFilesDialog(object): Set up the user interface. """ media_files_dialog.setObjectName('media_files_dialog') + media_files_dialog.setWindowIcon(build_icon(u':/icon/openlp-logo.svg')) media_files_dialog.setWindowModality(QtCore.Qt.ApplicationModal) media_files_dialog.resize(400, 300) media_files_dialog.setModal(True) - media_files_dialog.setWindowIcon(build_icon(':/icon/openlp-logo-16x16.png')) self.files_vertical_layout = QtGui.QVBoxLayout(media_files_dialog) self.files_vertical_layout.setSpacing(8) self.files_vertical_layout.setMargin(8) diff --git a/openlp/plugins/songs/forms/songbookdialog.py b/openlp/plugins/songs/forms/songbookdialog.py index 8cacef1a2..1ed79a4eb 100644 --- a/openlp/plugins/songs/forms/songbookdialog.py +++ b/openlp/plugins/songs/forms/songbookdialog.py @@ -29,7 +29,7 @@ from PyQt4 import QtGui -from openlp.core.lib import translate +from openlp.core.lib import translate, build_icon from openlp.core.lib.ui import create_button_box @@ -42,6 +42,7 @@ class Ui_SongBookDialog(object): Set up the user interface. """ song_book_dialog.setObjectName('song_book_dialog') + song_book_dialog.setWindowIcon(build_icon(u':/icon/openlp-logo.svg')) song_book_dialog.resize(300, 10) self.dialog_layout = QtGui.QVBoxLayout(song_book_dialog) self.dialog_layout.setObjectName('dialog_layout') diff --git a/openlp/plugins/songs/forms/songmaintenancedialog.py b/openlp/plugins/songs/forms/songmaintenancedialog.py index 84e3535d3..893ae9c1c 100644 --- a/openlp/plugins/songs/forms/songmaintenancedialog.py +++ b/openlp/plugins/songs/forms/songmaintenancedialog.py @@ -44,6 +44,7 @@ class Ui_SongMaintenanceDialog(object): Set up the user interface for the song maintenance dialog """ song_maintenance_dialog.setObjectName('song_maintenance_dialog') + song_maintenance_dialog.setWindowIcon(build_icon(u':/icon/openlp-logo.svg')) song_maintenance_dialog.setWindowModality(QtCore.Qt.ApplicationModal) song_maintenance_dialog.resize(10, 350) self.dialog_layout = QtGui.QGridLayout(song_maintenance_dialog) diff --git a/openlp/plugins/songs/forms/topicsdialog.py b/openlp/plugins/songs/forms/topicsdialog.py index eb6229bf6..ffa7da333 100644 --- a/openlp/plugins/songs/forms/topicsdialog.py +++ b/openlp/plugins/songs/forms/topicsdialog.py @@ -29,7 +29,7 @@ from PyQt4 import QtGui -from openlp.core.lib import translate +from openlp.core.lib import translate, build_icon from openlp.core.lib.ui import create_button_box @@ -42,6 +42,7 @@ class Ui_TopicsDialog(object): Set up the user interface for the topics dialog. """ topics_dialog.setObjectName('topics_dialog') + topics_dialog.setWindowIcon(build_icon(u':/icon/openlp-logo.svg')) topics_dialog.resize(300, 10) self.dialog_layout = QtGui.QVBoxLayout(topics_dialog) self.dialog_layout.setObjectName('dialog_layout') diff --git a/openlp/plugins/songusage/forms/songusagedeletedialog.py b/openlp/plugins/songusage/forms/songusagedeletedialog.py index 01597a790..190292678 100644 --- a/openlp/plugins/songusage/forms/songusagedeletedialog.py +++ b/openlp/plugins/songusage/forms/songusagedeletedialog.py @@ -30,6 +30,7 @@ from PyQt4 import QtCore, QtGui from openlp.core.common import translate +from openlp.core.lib import build_icon from openlp.core.lib.ui import create_button_box @@ -44,6 +45,7 @@ class Ui_SongUsageDeleteDialog(object): :param song_usage_delete_dialog: """ song_usage_delete_dialog.setObjectName('song_usage_delete_dialog') + song_usage_delete_dialog.setWindowIcon(build_icon(u':/icon/openlp-logo.svg')) song_usage_delete_dialog.resize(291, 243) self.vertical_layout = QtGui.QVBoxLayout(song_usage_delete_dialog) self.vertical_layout.setSpacing(8) diff --git a/openlp/plugins/songusage/forms/songusagedetaildialog.py b/openlp/plugins/songusage/forms/songusagedetaildialog.py index ede5075a0..9431c7894 100644 --- a/openlp/plugins/songusage/forms/songusagedetaildialog.py +++ b/openlp/plugins/songusage/forms/songusagedetaildialog.py @@ -45,6 +45,7 @@ class Ui_SongUsageDetailDialog(object): :param song_usage_detail_dialog: """ song_usage_detail_dialog.setObjectName('song_usage_detail_dialog') + song_usage_detail_dialog.setWindowIcon(build_icon(u':/icon/openlp-logo.svg')) song_usage_detail_dialog.resize(609, 413) self.vertical_layout = QtGui.QVBoxLayout(song_usage_detail_dialog) self.vertical_layout.setSpacing(8) From b02fc541a348610513d477a32d559e6392d016fb Mon Sep 17 00:00:00 2001 From: Samuel Mehrbrodt Date: Sat, 3 May 2014 17:22:10 +0200 Subject: [PATCH 26/42] Reorganize tests --- tests/functional/openlp_core_lib/test_ui.py | 64 ++++++++++----------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/tests/functional/openlp_core_lib/test_ui.py b/tests/functional/openlp_core_lib/test_ui.py index 025b1a638..1002550d2 100644 --- a/tests/functional/openlp_core_lib/test_ui.py +++ b/tests/functional/openlp_core_lib/test_ui.py @@ -82,6 +82,21 @@ class TestUi(TestCase): self.assertEqual(1, len(btnbox.buttons())) self.assertEqual(QtGui.QDialogButtonBox.HelpRole, btnbox.buttonRole(btnbox.buttons()[0])) + def test_create_horizontal_adjusting_combo_box(self): + """ + Test creating a horizontal adjusting combo box + """ + # GIVEN: A dialog + dialog = QtGui.QDialog() + + # WHEN: We create the combobox + combo = create_horizontal_adjusting_combo_box(dialog, 'combo1') + + # THEN: We should get a ComboBox + self.assertIsInstance(combo, QtGui.QComboBox) + self.assertEqual('combo1', combo.objectName()) + self.assertEqual(QtGui.QComboBox.AdjustToMinimumContentsLength, combo.sizeAdjustPolicy()) + def test_create_button(self): """ Test creating a button @@ -114,38 +129,6 @@ class TestUi(TestCase): self.assertEqual('my_btn', btn.objectName()) self.assertTrue(btn.isEnabled()) - def test_create_valign_selection_widgets(self): - """ - Test creating a combo box for valign selection - """ - # GIVEN: A dialog - dialog = QtGui.QDialog() - - # WHEN: We create the widgets - label, combo = create_valign_selection_widgets(dialog) - - # THEN: We should get a label and a combobox. - self.assertEqual(translate('OpenLP.Ui', '&Vertical Align:'), label.text()) - self.assertIsInstance(combo, QtGui.QComboBox) - self.assertEqual(combo, label.buddy()) - for text in [UiStrings().Top, UiStrings().Middle, UiStrings().Bottom]: - self.assertTrue(combo.findText(text) >= 0) - - def test_create_horizontal_adjusting_combo_box(self): - """ - Test creating a horizontal adjusting combo box - """ - # GIVEN: A dialog - dialog = QtGui.QDialog() - - # WHEN: We create the combobox - combo = create_horizontal_adjusting_combo_box(dialog, 'combo1') - - # THEN: We should get a ComboBox - self.assertIsInstance(combo, QtGui.QComboBox) - self.assertEqual('combo1', combo.objectName()) - self.assertEqual(QtGui.QComboBox.AdjustToMinimumContentsLength, combo.sizeAdjustPolicy()) - def test_create_action(self): """ Test creating an action @@ -170,3 +153,20 @@ class TestUi(TestCase): self.assertIsInstance(action.icon(), QtGui.QIcon) self.assertEqual('my tooltip', action.toolTip()) self.assertEqual('my statustip', action.statusTip()) + + def test_create_valign_selection_widgets(self): + """ + Test creating a combo box for valign selection + """ + # GIVEN: A dialog + dialog = QtGui.QDialog() + + # WHEN: We create the widgets + label, combo = create_valign_selection_widgets(dialog) + + # THEN: We should get a label and a combobox. + self.assertEqual(translate('OpenLP.Ui', '&Vertical Align:'), label.text()) + self.assertIsInstance(combo, QtGui.QComboBox) + self.assertEqual(combo, label.buddy()) + for text in [UiStrings().Top, UiStrings().Middle, UiStrings().Bottom]: + self.assertTrue(combo.findText(text) >= 0) From f60379b542a285eb0e4789bfe18e9c2e078c1d54 Mon Sep 17 00:00:00 2001 From: Samuel Mehrbrodt Date: Sat, 3 May 2014 17:22:20 +0200 Subject: [PATCH 27/42] Add new test --- tests/functional/openlp_core_lib/test_ui.py | 27 +++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/tests/functional/openlp_core_lib/test_ui.py b/tests/functional/openlp_core_lib/test_ui.py index 1002550d2..f1b8ee17a 100644 --- a/tests/functional/openlp_core_lib/test_ui.py +++ b/tests/functional/openlp_core_lib/test_ui.py @@ -170,3 +170,30 @@ class TestUi(TestCase): self.assertEqual(combo, label.buddy()) for text in [UiStrings().Top, UiStrings().Middle, UiStrings().Bottom]: self.assertTrue(combo.findText(text) >= 0) + + def test_find_and_set_in_combo_box(self): + """ + Test finding a string in a combo box and setting it as the selected item if present + """ + # GIVEN: A ComboBox + combo = QtGui.QComboBox() + combo.addItems(['One', 'Two', 'Three']) + combo.setCurrentIndex(1) + + # WHEN: We call the method with a non-existing value and set_missing=False + find_and_set_in_combo_box(combo, 'Four', set_missing=False) + + # THEN: The index should not have changed + self.assertEqual(1, combo.currentIndex()) + + # WHEN: We call the method with a non-existing value + find_and_set_in_combo_box(combo, 'Four') + + # THEN: The index should have been reset + self.assertEqual(0, combo.currentIndex()) + + # WHEN: We call the method with the default behavior + find_and_set_in_combo_box(combo, 'Three') + + # THEN: The index should have changed + self.assertEqual(2, combo.currentIndex()) From 7a1741258abc6a0ee44782c5bfd800b43ade8053 Mon Sep 17 00:00:00 2001 From: Samuel Mehrbrodt Date: Sat, 3 May 2014 17:25:45 +0200 Subject: [PATCH 28/42] Typo --- openlp/plugins/songs/forms/authorsdialog.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openlp/plugins/songs/forms/authorsdialog.py b/openlp/plugins/songs/forms/authorsdialog.py index c5a93894b..7bca76ca6 100644 --- a/openlp/plugins/songs/forms/authorsdialog.py +++ b/openlp/plugins/songs/forms/authorsdialog.py @@ -43,7 +43,7 @@ class Ui_AuthorsDialog(object): Set up the UI for the dialog. """ authors_dialog.setObjectName('authors_dialog') - authorsDialog.setWindowIcon(build_icon(u':/icon/openlp-logo.svg')) + authors_dialog.setWindowIcon(build_icon(u':/icon/openlp-logo.svg')) authors_dialog.resize(300, 10) authors_dialog.setModal(True) self.dialog_layout = QtGui.QVBoxLayout(authors_dialog) From 4a75849708df5561610b5a7fe40c70fec8ba8de4 Mon Sep 17 00:00:00 2001 From: Samuel Mehrbrodt Date: Sat, 3 May 2014 17:27:44 +0200 Subject: [PATCH 29/42] Fix readme links --- README.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.txt b/README.txt index b937e1d5f..e3e7cc579 100644 --- a/README.txt +++ b/README.txt @@ -5,7 +5,7 @@ You're probably reading this because you've just downloaded the source code for OpenLP 2.0. If you are looking for the installer file, please go to the download page on the web site:: - http://openlp.org/en/download.html + http://openlp.org/download If you're looking for how to contribute to OpenLP, then please look at the OpenLP wiki:: @@ -13,4 +13,3 @@ OpenLP wiki:: http://wiki.openlp.org/ Thanks for downloading OpenLP 2.0! - From d4edd91d5676a397f2c70f1d0dffb651554f309a Mon Sep 17 00:00:00 2001 From: Samuel Mehrbrodt Date: Sat, 3 May 2014 17:28:31 +0200 Subject: [PATCH 30/42] This is no longer 2.0 --- README.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.txt b/README.txt index e3e7cc579..04294b1b8 100644 --- a/README.txt +++ b/README.txt @@ -1,8 +1,8 @@ -OpenLP 2.0 -========== +OpenLP +====== You're probably reading this because you've just downloaded the source code for -OpenLP 2.0. If you are looking for the installer file, please go to the download +OpenLP. If you are looking for the installer file, please go to the download page on the web site:: http://openlp.org/download @@ -12,4 +12,4 @@ OpenLP wiki:: http://wiki.openlp.org/ -Thanks for downloading OpenLP 2.0! +Thanks for downloading OpenLP! From 37653bfd134398a66ad3e24c57df1c29ae99fddf Mon Sep 17 00:00:00 2001 From: Samuel Mehrbrodt Date: Sat, 3 May 2014 17:34:13 +0200 Subject: [PATCH 31/42] Add missing tag to test --- tests/utils/test_bzr_tags.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/utils/test_bzr_tags.py b/tests/utils/test_bzr_tags.py index 95017e94f..393f4ce25 100644 --- a/tests/utils/test_bzr_tags.py +++ b/tests/utils/test_bzr_tags.py @@ -53,6 +53,7 @@ TAGS = [ ['2.0.1', '?'], ['2.0.2', '?'], ['2.0.3', '?'], + ['2.0.4', '?'], ['2.1.0', '2119'] ] From f21d3cfa838335deccc20355bb9d512038c9cb8e Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Sat, 3 May 2014 20:32:19 +0100 Subject: [PATCH 32/42] fix tests --- tests/functional/openlp_core_lib/test_image_manager.py | 2 +- tests/functional/openlp_core_ui/test_media.py | 2 +- tests/interfaces/openlp_core_common/test_historycombobox.py | 2 +- tests/interfaces/openlp_core_ui/test_shortcutlistform.py | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/functional/openlp_core_lib/test_image_manager.py b/tests/functional/openlp_core_lib/test_image_manager.py index 37b6d6fdd..072978993 100644 --- a/tests/functional/openlp_core_lib/test_image_manager.py +++ b/tests/functional/openlp_core_lib/test_image_manager.py @@ -171,4 +171,4 @@ class TestImageManager(TestCase, TestMixin): self.lock.release() # The sleep time is adjusted in the test case. time.sleep(self.sleep_time) - return '' \ No newline at end of file + return '' diff --git a/tests/functional/openlp_core_ui/test_media.py b/tests/functional/openlp_core_ui/test_media.py index d59690949..4c6fa7f86 100644 --- a/tests/functional/openlp_core_ui/test_media.py +++ b/tests/functional/openlp_core_ui/test_media.py @@ -125,4 +125,4 @@ class TestMedia(TestCase, TestMixin): # THEN: the used_players should be an empty list, and the overridden player should be an empty string self.assertEqual(['vlc', 'webkit', 'phonon'], used_players, 'Used players should be correct') - self.assertEqual('vlc,webkit,phonon', overridden_player, 'Overridden player should be a string of players') \ No newline at end of file + self.assertEqual('vlc,webkit,phonon', overridden_player, 'Overridden player should be a string of players') diff --git a/tests/interfaces/openlp_core_common/test_historycombobox.py b/tests/interfaces/openlp_core_common/test_historycombobox.py index 00a63f15f..c0131e46c 100644 --- a/tests/interfaces/openlp_core_common/test_historycombobox.py +++ b/tests/interfaces/openlp_core_common/test_historycombobox.py @@ -62,4 +62,4 @@ class TestHistoryComboBox(TestCase, TestMixin): self.combo.addItem('test2') # THEN: The list of items should contain both strings. - self.assertEqual(self.combo.getItems(), ['test1', 'test2']) \ No newline at end of file + self.assertEqual(self.combo.getItems(), ['test1', 'test2']) diff --git a/tests/interfaces/openlp_core_ui/test_shortcutlistform.py b/tests/interfaces/openlp_core_ui/test_shortcutlistform.py index 472bce03f..29c365194 100644 --- a/tests/interfaces/openlp_core_ui/test_shortcutlistform.py +++ b/tests/interfaces/openlp_core_ui/test_shortcutlistform.py @@ -75,4 +75,4 @@ class TestShortcutform(TestCase, TestMixin): # THEN: The button should be changed. self.assertEqual(button.text(), text, "The text should match.") mocked_check_method.assert_called_once_with(True) - self.assertEqual(button.isEnabled(), enabled, "The button should be disabled.") \ No newline at end of file + self.assertEqual(button.isEnabled(), enabled, "The button should be disabled.") From d6d3cd1394ca7cce172c0b6ca762fe38fff9de4d Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Sat, 3 May 2014 21:00:17 +0100 Subject: [PATCH 33/42] Fix call path --- openlp/plugins/media/lib/mediaitem.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openlp/plugins/media/lib/mediaitem.py b/openlp/plugins/media/lib/mediaitem.py index 92426334a..0780b175d 100644 --- a/openlp/plugins/media/lib/mediaitem.py +++ b/openlp/plugins/media/lib/mediaitem.py @@ -229,7 +229,7 @@ class MediaMediaItem(MediaManagerItem, RegistryProperties): self.service_path = os.path.join(AppLocation.get_section_data_path(self.settings_section), 'thumbnails') check_directory_exists(self.service_path) self.load_list(Settings().value(self.settings_section + '/media files')) - self.populate_display_types() + self.rebuild_players() def rebuild_players(self): """ From 9b396e7699fb52480ecc99ed5597716eac338466 Mon Sep 17 00:00:00 2001 From: Samuel Mehrbrodt Date: Mon, 5 May 2014 18:20:54 +0200 Subject: [PATCH 34/42] Fix bug 1211913 Fixes: https://launchpad.net/bugs/1211913 --- openlp/plugins/songs/lib/sundayplusimport.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/openlp/plugins/songs/lib/sundayplusimport.py b/openlp/plugins/songs/lib/sundayplusimport.py index f22f8b058..5c5f73047 100644 --- a/openlp/plugins/songs/lib/sundayplusimport.py +++ b/openlp/plugins/songs/lib/sundayplusimport.py @@ -68,7 +68,7 @@ class SundayPlusImport(SongImport): for filename in self.import_source: if self.stop_import_flag: return - song_file = open(filename) + song_file = open(filename, 'rb') self.do_import_file(song_file) song_file.close() @@ -103,7 +103,7 @@ class SundayPlusImport(SongImport): # Now we are looking for the name. if data[i:i + 1] == '#': name_end = data.find(':', i + 1) - name = data[i + 1:name_end] + name = data[i + 1:name_end].upper() i = name_end + 1 while data[i:i + 1] == ' ': i += 1 @@ -129,13 +129,13 @@ class SundayPlusImport(SongImport): value = data[i:end] # If we are in the main group. if not cell: - if name == 'title': + if name == 'TITLE': self.title = self.decode(self.unescape(value)) - elif name == 'Author': + elif name == 'AUTHOR': author = self.decode(self.unescape(value)) if len(author): self.add_author(author) - elif name == 'Copyright': + elif name == 'COPYRIGHT': self.copyright = self.decode(self.unescape(value)) elif name[0:4] == 'CELL': self.parse(value, cell=name[4:]) @@ -147,12 +147,12 @@ class SundayPlusImport(SongImport): verse_type = VerseType.tags[VerseType.from_loose_input(value[0])] if len(value) >= 2 and value[-1] in ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']: verse_type = "%s%s" % (verse_type, value[-1]) - elif name == 'Hotkey': - # Hotkey always appears after MARKER_NAME, so it + elif name == 'HOTKEY': + # HOTKEY always appears after MARKER_NAME, so it # effectively overrides MARKER_NAME, if present. if len(value) and value in list(HOTKEY_TO_VERSE_TYPE.keys()): verse_type = HOTKEY_TO_VERSE_TYPE[value] - if name == 'rtf': + if name == 'RTF': value = self.unescape(value) result = strip_rtf(value, self.encoding) if result is None: From c7ce62bd43a79616e3b2cbd9e26ab0ca439f14ac Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Mon, 5 May 2014 19:29:57 +0200 Subject: [PATCH 35/42] Changed to ignore wrongly formatted songs. --- openlp/plugins/songs/lib/ewimport.py | 29 ++++++++++----- .../openlp_plugins/songs/test_ewimport.py | 37 ++++--------------- 2 files changed, 26 insertions(+), 40 deletions(-) diff --git a/openlp/plugins/songs/lib/ewimport.py b/openlp/plugins/songs/lib/ewimport.py index e12b7e181..b08193672 100644 --- a/openlp/plugins/songs/lib/ewimport.py +++ b/openlp/plugins/songs/lib/ewimport.py @@ -74,6 +74,7 @@ class EasyWorshipSongImport(SongImport): """ def __init__(self, manager, **kwargs): super(EasyWorshipSongImport, self).__init__(manager, **kwargs) + self.entry_error_log = '' def do_import(self): """ @@ -183,7 +184,12 @@ class EasyWorshipSongImport(SongImport): self.set_song_import_object(authors, inflated_content) if self.stop_import_flag: break - if not self.finish(): + if self.entry_error_log: + self.log_error(self.import_source, + translate('SongsPlugin.EasyWorshipSongImport', '"%s" could not be imported. %s') + % (self.title, self.entry_error_log)) + self.entry_error_log = '' + elif not self.finish(): self.log_error(self.import_source) # Set file_pos for next entry file_pos += entry_length @@ -305,7 +311,12 @@ class EasyWorshipSongImport(SongImport): self.set_song_import_object(authors, words) if self.stop_import_flag: break - if not self.finish(): + if self.entry_error_log: + self.log_error(self.import_source, + translate('SongsPlugin.EasyWorshipSongImport', '"%s" could not be imported. %s') + % (self.title, self.entry_error_log)) + self.entry_error_log = '' + elif not self.finish(): self.log_error(self.import_source) db_file.close() self.memo_file.close() @@ -333,16 +344,14 @@ class EasyWorshipSongImport(SongImport): try: decoded_words = words.decode() except UnicodeDecodeError: - # The unicode chars in the rtf was not escaped in the expected manor, doing it manually. - newbytes = bytearray() - for b in words: - if b > 127: - newbytes += bytearray(b'\\\'') + bytearray(str(hex(b))[-2:].encode()) - else: - newbytes.append(b) - decoded_words = newbytes.decode() + # The unicode chars in the rtf was not escaped in the expected manor + self.entry_error_log = translate('SongsPlugin.EasyWorshipSongImport', + 'Unexpected data formatting.') + return result = strip_rtf(decoded_words, self.encoding) if result is None: + self.entry_error_log = translate('SongsPlugin.EasyWorshipSongImport', + 'No song text found.') return words, self.encoding = result verse_type = VerseType.tags[VerseType.Verse] diff --git a/tests/functional/openlp_plugins/songs/test_ewimport.py b/tests/functional/openlp_plugins/songs/test_ewimport.py index e6344e39b..8d9302015 100644 --- a/tests/functional/openlp_plugins/songs/test_ewimport.py +++ b/tests/functional/openlp_plugins/songs/test_ewimport.py @@ -153,15 +153,7 @@ class TestEasyWorshipSongImport(TestCase): """ Test the functions in the :mod:`ewimport` module. """ - """def setUp(self): - self.songimport_patcher = patch('openlp.plugins.songs.lib.ewimport.EasyWorshipSongImport.__init__') - self.mocked_songimport = self.songimport_patcher.start() - self.mocked_songimport.return_value = None - - def tearDown(self): - self.songimport_patcher.stop() - """ - + def create_field_desc_entry_test(self): """ Test creating an instance of the :class`FieldDescEntry` class. @@ -495,32 +487,17 @@ class TestEasyWorshipSongImport(TestCase): """ Test import of rtf without the expected escaping of unicode """ - - # GIVEN: Test files with a mocked out SongImport class, a mocked out "manager", a mocked out "import_wizard", - # and mocked out "author", "add_copyright", "add_verse", "finish" methods. - with patch('openlp.plugins.songs.lib.ewimport.SongImport'), \ - patch('openlp.plugins.songs.lib.ewimport.strip_rtf') as mocked_strip_rtf, \ - patch('openlp.plugins.songs.lib.ewimport.retrieve_windows_encoding') \ - as mocked_retrieve_windows_encoding: - mocked_retrieve_windows_encoding.return_value = 'cp1252' + + # GIVEN: A mocked out SongImport class, a mocked out "manager" and mocked out "author" method. + with patch('openlp.plugins.songs.lib.ewimport.SongImport'): mocked_manager = MagicMock() - mocked_import_wizard = MagicMock() mocked_add_author = MagicMock() - mocked_add_verse = MagicMock() - mocked_finish = MagicMock() - mocked_title = MagicMock() - mocked_finish.return_value = True importer = EasyWorshipSongImportLogger(mocked_manager) - importer.import_wizard = mocked_import_wizard - importer.stop_import_flag = False importer.add_author = mocked_add_author - importer.add_verse = mocked_add_verse - importer.title = mocked_title - importer.finish = mocked_finish - importer.topics = [] + importer.encoding = 'cp1252' # WHEN: running set_song_import_object on a verse string without the needed escaping importer.set_song_import_object('Test Author', b'Det som var fr\x86n begynnelsen') - # THEN: The escaping shoud be added - mocked_strip_rtf.assert_called_with("Det som var fr\'86n begynnelsen", 'cp1252') + # THEN: The import should fail + self.assertEquals(importer.entry_error_log, 'Unexpected data formatting.', 'Import should fail') From 0fd815051f677f92ece5eb3c021ed0a1162af9af Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Mon, 5 May 2014 19:31:45 +0200 Subject: [PATCH 36/42] Fix for packaging --- MANIFEST.in | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MANIFEST.in b/MANIFEST.in index 35e83e30f..be81efb23 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -5,6 +5,8 @@ recursive-include openlp *.html recursive-include openlp *.js recursive-include openlp *.css recursive-include openlp *.png +recursive-include openlp *.ps +recursive-include openlp *.json recursive-include documentation * recursive-include resources * recursive-include scripts * From 1e6f00c2ebd19f92705a7d0dd6435fe20c02bd36 Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Wed, 7 May 2014 17:05:27 +0100 Subject: [PATCH 37/42] Add test --- .../openlp_core_ui/test_slidecontroller.py | 2 +- .../openlp_plugins/remotes/test_router.py | 27 ++++++++++++++++--- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/tests/functional/openlp_core_ui/test_slidecontroller.py b/tests/functional/openlp_core_ui/test_slidecontroller.py index 56d87c511..104c83750 100644 --- a/tests/functional/openlp_core_ui/test_slidecontroller.py +++ b/tests/functional/openlp_core_ui/test_slidecontroller.py @@ -33,7 +33,7 @@ from unittest import TestCase from openlp.core.ui import SlideController -from tests.interfaces import MagicMock, patch +from tests.interfaces import MagicMock class TestSlideController(TestCase): diff --git a/tests/functional/openlp_plugins/remotes/test_router.py b/tests/functional/openlp_plugins/remotes/test_router.py index 9e13a448b..1388e6104 100644 --- a/tests/functional/openlp_plugins/remotes/test_router.py +++ b/tests/functional/openlp_plugins/remotes/test_router.py @@ -32,7 +32,7 @@ This module contains tests for the lib submodule of the Remotes plugin. import os from unittest import TestCase -from openlp.core.common import Settings +from openlp.core.common import Settings, Registry from openlp.plugins.remotes.lib.httpserver import HttpRouter from tests.functional import MagicMock, patch, mock_open from tests.helpers.testmixin import TestMixin @@ -92,15 +92,15 @@ class TestRouter(TestCase, TestMixin): Test the router control functionality """ # GIVEN: A testing set of Routes - router = HttpRouter() + #router = HttpRouter() mocked_function = MagicMock() test_route = [ (r'^/stage/api/poll$', {'function': mocked_function, 'secure': False}), ] - router.routes = test_route + self.router.routes = test_route # WHEN: called with a poll route - function, args = router.process_http_request('/stage/api/poll', None) + function, args = self.router.process_http_request('/stage/api/poll', None) # THEN: the function should have been called only once self.assertEqual(mocked_function, function['function'], 'The mocked function should match defined value.') @@ -126,6 +126,25 @@ class TestRouter(TestCase, TestMixin): # THEN: all types should match self.assertEqual(content_type, header[1], 'Mismatch of content type') + def main_poll_test(self): + """ + Test the main poll logic + """ + # GIVEN: a defined router with two slides + Registry().register('live_controller', MagicMock) + router = HttpRouter() + router.send_response = MagicMock() + router.send_header = MagicMock() + router.end_headers = MagicMock() + router.live_controller.slide_count = 2 + + # WHEN: main poll called + results = router.main_poll() + + # THEN: the correct response should be returned + self.assertEqual(results.decode('utf-8'), '{"results": {"slide_count": 2}}', + 'The resulting json strings should match') + def serve_file_without_params_test(self): """ Test the serve_file method without params From 55c9e3e19678357a28f6c49b1a04f9205271f137 Mon Sep 17 00:00:00 2001 From: Samuel Mehrbrodt Date: Wed, 7 May 2014 21:17:47 +0200 Subject: [PATCH 38/42] Log warning when CCLI no can't be parsed --- openlp/plugins/songs/lib/songshowplusimport.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openlp/plugins/songs/lib/songshowplusimport.py b/openlp/plugins/songs/lib/songshowplusimport.py index fe81b61a2..aebded029 100644 --- a/openlp/plugins/songs/lib/songshowplusimport.py +++ b/openlp/plugins/songs/lib/songshowplusimport.py @@ -151,6 +151,8 @@ class SongShowPlusImport(SongImport): match = re.search(r'\d+', self.decode(data)) if match: self.ccli_number = int(match.group()) + else: + log.warn("Can't parse CCLI Number from string: %s" % self.decode(data)) elif block_key == VERSE: self.add_verse(self.decode(data), "%s%s" % (VerseType.tags[VerseType.Verse], verse_no)) elif block_key == CHORUS: From c6d6be30c6b90388304eb8f1ca0af83ea0442f3c Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Wed, 7 May 2014 21:38:34 +0100 Subject: [PATCH 39/42] fix --- tests/functional/openlp_plugins/remotes/test_router.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/functional/openlp_plugins/remotes/test_router.py b/tests/functional/openlp_plugins/remotes/test_router.py index 1388e6104..037169b88 100644 --- a/tests/functional/openlp_plugins/remotes/test_router.py +++ b/tests/functional/openlp_plugins/remotes/test_router.py @@ -92,7 +92,6 @@ class TestRouter(TestCase, TestMixin): Test the router control functionality """ # GIVEN: A testing set of Routes - #router = HttpRouter() mocked_function = MagicMock() test_route = [ (r'^/stage/api/poll$', {'function': mocked_function, 'secure': False}), From 60fa4c2dcac032db960967c81c3bd32b756c12aa Mon Sep 17 00:00:00 2001 From: Jonathan Springer Date: Wed, 7 May 2014 18:52:06 -0400 Subject: [PATCH 40/42] Make vlcplayer stop call asynchronous to aviod a deadlock with the UI thread --- openlp/core/ui/media/vlcplayer.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/openlp/core/ui/media/vlcplayer.py b/openlp/core/ui/media/vlcplayer.py index c80bb6218..d02526b0e 100644 --- a/openlp/core/ui/media/vlcplayer.py +++ b/openlp/core/ui/media/vlcplayer.py @@ -34,6 +34,7 @@ from distutils.version import LooseVersion import logging import os import sys +import threading from PyQt4 import QtGui @@ -207,7 +208,7 @@ class VlcPlayer(MediaPlayer): start_time = 0 if self.state != MediaState.Paused and controller.media_info.start_time > 0: start_time = controller.media_info.start_time - display.vlc_media_player.play() + threading.Thread(target=display.vlc_media_player.play).start() if not self.media_state_wait(display, vlc.State.Playing): return False self.volume(display, controller.media_info.volume) @@ -233,7 +234,7 @@ class VlcPlayer(MediaPlayer): """ Stop the current item """ - display.vlc_media_player.stop() + threading.Thread(target=display.vlc_media_player.stop).start() self.state = MediaState.Stopped def volume(self, display, vol): From 6de740333b4521d46fc9c518e5260eb1b6424598 Mon Sep 17 00:00:00 2001 From: Jonathan Springer Date: Wed, 7 May 2014 18:54:14 -0400 Subject: [PATCH 41/42] merge trunk From 13b9a7de72b01147199e928a831931668be681eb Mon Sep 17 00:00:00 2001 From: Jonathan Springer Date: Thu, 8 May 2014 10:57:26 -0400 Subject: [PATCH 42/42] Add test for the main window function set_service_modified --- .../openlp_core_ui/test_mainwindow.py | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/tests/functional/openlp_core_ui/test_mainwindow.py b/tests/functional/openlp_core_ui/test_mainwindow.py index 0b17828b9..b348f8f80 100644 --- a/tests/functional/openlp_core_ui/test_mainwindow.py +++ b/tests/functional/openlp_core_ui/test_mainwindow.py @@ -34,6 +34,7 @@ import os from unittest import TestCase from openlp.core.ui.mainwindow import MainWindow +from openlp.core.lib.ui import UiStrings from openlp.core.common.registry import Registry from tests.utils.constants import TEST_RESOURCES_PATH from tests.helpers.testmixin import TestMixin @@ -95,3 +96,41 @@ class TestMainWindow(TestCase, TestMixin): # THEN the file should not be opened assert not mocked_load_path.called, 'load_path should not have been called' + + def main_window_title_test(self): + """ + Test that running a new instance of OpenLP set the window title correctly + """ + # GIVEN a newly opened OpenLP instance + + # WHEN no changes are made to the service + + # THEN the main window's title shoud be the same as the OLPV2x string in the UiStrings class + self.assertEqual(self.main_window.windowTitle(), UiStrings().OLPV2x, + 'The main window\'s title should be the same as the OLPV2x string in UiStrings class') + + def set_service_modifed_test(self): + """ + Test that when setting the service's title the main window's title is set correctly + """ + # GIVEN a newly opened OpenLP instance + + # WHEN set_service_modified is called with with the modified flag set true and a file name + self.main_window.set_service_modified(True, 'test.osz') + + # THEN the main window's title should be set to the + self.assertEqual(self.main_window.windowTitle(), '%s - %s*' % (UiStrings().OLPV2x, 'test.osz'), + 'The main window\'s title should be set to " - test.osz*"') + + def set_service_unmodified_test(self): + """ + Test that when setting the service's title the main window's title is set correctly + """ + # GIVEN a newly opened OpenLP instance + + # WHEN set_service_modified is called with with the modified flag set False and a file name + self.main_window.set_service_modified(False, 'test.osz') + + # THEN the main window's title should be set to the + self.assertEqual(self.main_window.windowTitle(), '%s - %s' % (UiStrings().OLPV2x, 'test.osz'), + 'The main window\'s title should be set to " - test.osz"')