From 7a47e5cb67e50b733cbe70c6e972d64a9b92a14c Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Sun, 15 Jun 2014 22:35:31 +0200 Subject: [PATCH 01/39] fixed bug #719514 ' Themes: and are the same file' Fixes: https://launchpad.net/bugs/719514 --- openlp/core/ui/thememanager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openlp/core/ui/thememanager.py b/openlp/core/ui/thememanager.py index fdd2ea592..6a67605d4 100644 --- a/openlp/core/ui/thememanager.py +++ b/openlp/core/ui/thememanager.py @@ -650,7 +650,7 @@ class ThemeManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ThemeManager, R finally: if out_file: out_file.close() - if image_from and image_from != image_to: + if image_from and os.path.abspath(image_from) != os.path.abspath(image_to): try: encoding = get_filesystem_encoding() shutil.copyfile(str(image_from).encode(encoding), str(image_to).encode(encoding)) From e1743650516a292cb07edbd0995fa2a159512c12 Mon Sep 17 00:00:00 2001 From: Samuel Mehrbrodt Date: Mon, 23 Jun 2014 13:38:17 +0200 Subject: [PATCH 02/39] Fix theme export Fixes: https://launchpad.net/bugs/1332990 --- openlp/core/ui/thememanager.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/openlp/core/ui/thememanager.py b/openlp/core/ui/thememanager.py index fdd2ea592..714964846 100644 --- a/openlp/core/ui/thememanager.py +++ b/openlp/core/ui/thememanager.py @@ -391,9 +391,7 @@ class ThemeManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ThemeManager, R source = os.path.join(self.path, theme) for files in os.walk(source): for name in files[2]: - theme_zip.write( - os.path.join(source, name).encode('utf-8'), os.path.join(theme, name).encode('utf-8') - ) + theme_zip.write(os.path.join(source, name), os.path.join(theme, name)) QtGui.QMessageBox.information(self, translate('OpenLP.ThemeManager', 'Theme Exported'), translate('OpenLP.ThemeManager', From aa0e1ca1070a3347b07762d140b3d6f6e8c6b5b2 Mon Sep 17 00:00:00 2001 From: Samuel Mehrbrodt Date: Mon, 23 Jun 2014 15:51:56 +0200 Subject: [PATCH 03/39] Add test --- openlp/core/ui/thememanager.py | 27 ++++---- .../openlp_core_ui/test_thememanager.py | 62 +++++++++++++++++++ tests/resources/themes/Default/Default.xml | 34 ++++++++++ 3 files changed, 112 insertions(+), 11 deletions(-) create mode 100644 tests/functional/openlp_core_ui/test_thememanager.py create mode 100644 tests/resources/themes/Default/Default.xml diff --git a/openlp/core/ui/thememanager.py b/openlp/core/ui/thememanager.py index 714964846..fb0788b99 100644 --- a/openlp/core/ui/thememanager.py +++ b/openlp/core/ui/thememanager.py @@ -383,15 +383,9 @@ class ThemeManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ThemeManager, R '/last directory export')) self.application.set_busy_cursor() if path: - Settings().setValue(self.settings_section + '/last directory export', path) - theme_path = os.path.join(path, theme + '.otz') - theme_zip = None try: - theme_zip = zipfile.ZipFile(theme_path, 'w') - source = os.path.join(self.path, theme) - for files in os.walk(source): - for name in files[2]: - theme_zip.write(os.path.join(source, name), os.path.join(theme, name)) + Settings().setValue(self.settings_section + '/last directory export', path) + self._export_theme(path, theme) QtGui.QMessageBox.information(self, translate('OpenLP.ThemeManager', 'Theme Exported'), translate('OpenLP.ThemeManager', @@ -401,11 +395,22 @@ class ThemeManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ThemeManager, R critical_error_message_box(translate('OpenLP.ThemeManager', 'Theme Export Failed'), translate('OpenLP.ThemeManager', 'Your theme could not be exported due to an error.')) - finally: - if theme_zip: - theme_zip.close() self.application.set_normal_cursor() + def _export_theme(self, path, theme): + """ + Create the zipfile with the theme contents. + :param path: Location where the zip file will be placed + :param theme: The name of the theme to be exported + """ + theme_path = os.path.join(path, theme + '.otz') + theme_zip = zipfile.ZipFile(theme_path, 'w') + source = os.path.join(self.path, theme) + for files in os.walk(source): + for name in files[2]: + theme_zip.write(os.path.join(source, name), os.path.join(theme, name)) + theme_zip.close() + def on_import_theme(self, field=None): """ Opens a file dialog to select the theme file(s) to import before attempting to extract OpenLP themes from diff --git a/tests/functional/openlp_core_ui/test_thememanager.py b/tests/functional/openlp_core_ui/test_thememanager.py new file mode 100644 index 000000000..3555b8843 --- /dev/null +++ b/tests/functional/openlp_core_ui/test_thememanager.py @@ -0,0 +1,62 @@ +# -*- coding: utf-8 -*- +# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4 + +############################################################################### +# OpenLP - Open Source Lyrics Projection # +# --------------------------------------------------------------------------- # +# Copyright (c) 2008-2014 Raoul Snyman # +# Portions copyright (c) 2008-2014 Tim Bentley, Gerald Britton, Jonathan # +# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub, # +# Meinert Jordan, Armin Köhler, Erik Lundin, Edwin Lunando, Brian T. Meyer. # +# Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias Põldaru, # +# Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # +# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Dave Warnock, # +# Frode Woldsund, Martin Zibricky, Patrick Zimmermann # +# --------------------------------------------------------------------------- # +# This program is free software; you can redistribute it and/or modify it # +# under the terms of the GNU General Public License as published by the Free # +# Software Foundation; version 2 of the License. # +# # +# This program is distributed in the hope that it will be useful, but WITHOUT # +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # +# more details. # +# # +# You should have received a copy of the GNU General Public License along # +# with this program; if not, write to the Free Software Foundation, Inc., 59 # +# Temple Place, Suite 330, Boston, MA 02111-1307 USA # +############################################################################### +""" +Package to test the openlp.core.ui.thememanager package. +""" +import zipfile +import os + +from unittest import TestCase +from tests.interfaces import MagicMock + +from openlp.core.ui import ThemeManager + +RESOURCES_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', 'resources', 'themes')) + + +class TestThemeManager(TestCase): + + def export_theme_test(self): + """ + Test exporting a theme . + """ + # GIVEN: A new ThemeManager instance. + theme_manager = ThemeManager() + theme_manager.path = RESOURCES_PATH + zipfile.ZipFile.__init__ = MagicMock() + zipfile.ZipFile.__init__.return_value = None + zipfile.ZipFile.write = MagicMock() + + # WHEN: The theme is exported + theme_manager._export_theme('/some/path', 'Default') + + # THEN: The zipfile should be created at the given path + zipfile.ZipFile.__init__.assert_called_with('/some/path/Default.otz', 'w') + zipfile.ZipFile.write.assert_called_with(os.path.join(RESOURCES_PATH, 'Default', 'Default.xml'), + 'Default/Default.xml') diff --git a/tests/resources/themes/Default/Default.xml b/tests/resources/themes/Default/Default.xml new file mode 100644 index 000000000..d77731005 --- /dev/null +++ b/tests/resources/themes/Default/Default.xml @@ -0,0 +1,34 @@ + + + Default + + #000000 + + + Arial + #FFFFFF + 40 + False + False + 0 + + True + False + + + Arial + #FFFFFF + 12 + False + False + 0 + + True + False + + + 0 + 0 + False + + From 39fbbf779d930d00bc3edb34229b6951e72d548c Mon Sep 17 00:00:00 2001 From: Samuel Mehrbrodt Date: Mon, 23 Jun 2014 15:54:13 +0200 Subject: [PATCH 04/39] Move this line out of try/catch block --- openlp/core/ui/thememanager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openlp/core/ui/thememanager.py b/openlp/core/ui/thememanager.py index fb0788b99..c42b9b664 100644 --- a/openlp/core/ui/thememanager.py +++ b/openlp/core/ui/thememanager.py @@ -383,8 +383,8 @@ class ThemeManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ThemeManager, R '/last directory export')) self.application.set_busy_cursor() if path: + Settings().setValue(self.settings_section + '/last directory export', path) try: - Settings().setValue(self.settings_section + '/last directory export', path) self._export_theme(path, theme) QtGui.QMessageBox.information(self, translate('OpenLP.ThemeManager', 'Theme Exported'), From 9702870afa6e8cd11fb6cf64b816f230c70f6213 Mon Sep 17 00:00:00 2001 From: Samuel Mehrbrodt Date: Mon, 30 Jun 2014 09:30:19 +0200 Subject: [PATCH 05/39] Close and delete zip in case of exception --- openlp/core/ui/thememanager.py | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/openlp/core/ui/thememanager.py b/openlp/core/ui/thememanager.py index c42b9b664..95df35831 100644 --- a/openlp/core/ui/thememanager.py +++ b/openlp/core/ui/thememanager.py @@ -404,12 +404,17 @@ class ThemeManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ThemeManager, R :param theme: The name of the theme to be exported """ theme_path = os.path.join(path, theme + '.otz') - theme_zip = zipfile.ZipFile(theme_path, 'w') - source = os.path.join(self.path, theme) - for files in os.walk(source): - for name in files[2]: - theme_zip.write(os.path.join(source, name), os.path.join(theme, name)) - theme_zip.close() + try: + theme_zip = zipfile.ZipFile(theme_path, 'w') + source = os.path.join(self.path, theme) + for files in os.walk(source): + for name in files[2]: + theme_zip.write(os.path.join(source, name), os.path.join(theme, name)) + except (IOError, OSError): + if theme_zip: + theme_zip.close() + shutil.rmtree(theme_path, True) + raise def on_import_theme(self, field=None): """ From af6537116c785735c1dd80292cfa0c238f0ea413 Mon Sep 17 00:00:00 2001 From: Samuel Mehrbrodt Date: Mon, 30 Jun 2014 14:36:35 +0200 Subject: [PATCH 06/39] Close file also on success --- openlp/core/ui/thememanager.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openlp/core/ui/thememanager.py b/openlp/core/ui/thememanager.py index 95df35831..c68d1694b 100644 --- a/openlp/core/ui/thememanager.py +++ b/openlp/core/ui/thememanager.py @@ -415,6 +415,8 @@ class ThemeManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ThemeManager, R theme_zip.close() shutil.rmtree(theme_path, True) raise + else: + theme_zip.close() def on_import_theme(self, field=None): """ From 376f8f3dc7d0714a876c6ab184638ffc7f0d2db7 Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Wed, 2 Jul 2014 21:18:18 +0200 Subject: [PATCH 07/39] Added test for thememanager --- .../openlp_core_ui/test_thememanager.py | 94 +++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 tests/functional/openlp_core_ui/test_thememanager.py diff --git a/tests/functional/openlp_core_ui/test_thememanager.py b/tests/functional/openlp_core_ui/test_thememanager.py new file mode 100644 index 000000000..a0bfbd01e --- /dev/null +++ b/tests/functional/openlp_core_ui/test_thememanager.py @@ -0,0 +1,94 @@ +# -*- coding: utf-8 -*- +# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4 + +############################################################################### +# OpenLP - Open Source Lyrics Projection # +# --------------------------------------------------------------------------- # +# Copyright (c) 2008-2014 Raoul Snyman # +# Portions copyright (c) 2008-2014 Tim Bentley, Gerald Britton, Jonathan # +# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub, # +# Meinert Jordan, Armin Köhler, Erik Lundin, Edwin Lunando, Brian T. Meyer. # +# Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias Põldaru, # +# Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # +# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Dave Warnock, # +# Frode Woldsund, Martin Zibricky, Patrick Zimmermann # +# --------------------------------------------------------------------------- # +# This program is free software; you can redistribute it and/or modify it # +# under the terms of the GNU General Public License as published by the Free # +# Software Foundation; version 2 of the License. # +# # +# This program is distributed in the hope that it will be useful, but WITHOUT # +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # +# more details. # +# # +# You should have received a copy of the GNU General Public License along # +# with this program; if not, write to the Free Software Foundation, Inc., 59 # +# Temple Place, Suite 330, Boston, MA 02111-1307 USA # +############################################################################### +""" +Package to test the openlp.core.ui.slidecontroller package. +""" +import os + +from unittest import TestCase + +from openlp.core.common import Registry +from openlp.core.ui import ThemeManager + +from tests.utils.constants import TEST_RESOURCES_PATH +from tests.interfaces import MagicMock, patch + + +class TestThemeManager(TestCase): + + def setUp(self): + """ + Create the UI + """ + Registry.create() + + def tearDown(self): + """ + Delete all the C++ objects at the end so that we don't have a segfault + """ + pass + + def initial_theme_manager_test(self): + """ + Test the initial of theme manager. + """ + # GIVEN: A new service manager instance. + ThemeManager(None) + + # WHEN: the default theme manager is built. + # THEN: The the controller should be registered in the registry. + self.assertNotEqual(Registry().get('theme_manager'), None, 'The base theme manager should be registered') + + def write_theme_test(self): + """ + Test that we don't try to overwrite a theme bacground image with itself + """ + # GIVEN: A new theme manager instance, with mocked builtins.open, shutil.copyfile, + # theme, check_directory_exists and thememanager-attributes. + with patch('builtins.open') as mocked_open, \ + patch('openlp.core.ui.thememanager.shutil.copyfile') as mocked_copyfile, \ + patch('openlp.core.ui.thememanager.check_directory_exists') as mocked_check_directory_exists: + mocked_open.return_value = MagicMock() + theme_manager = ThemeManager(None) + theme_manager.old_background_image = None + theme_manager.generate_and_save_image = MagicMock() + theme_manager.path = '' + mocked_theme = MagicMock() + mocked_theme.theme_name = 'themename' + mocked_theme.extract_formatted_xml = MagicMock() + mocked_theme.extract_formatted_xml.return_value = 'fake_theme_xml'.encode() + + # WHEN: Calling _write_theme with path to the same image, but the path written slightly different + file_name1 = os.path.join(TEST_RESOURCES_PATH, 'church.jpg') + # Do replacement from end of string to avoid problems with path start + file_name2 = file_name1[::-1].replace(os.sep, os.sep + os.sep, 2)[::-1] + theme_manager._write_theme(mocked_theme, file_name1, file_name2) + + # THEN: The mocked_copyfile should not have been called + self.assertFalse(mocked_copyfile.called, 'shutil.copyfile should not be called') From b7a141f75ce6feb1182d0f18f63a28bff7f75efa Mon Sep 17 00:00:00 2001 From: Samuel Mehrbrodt Date: Mon, 7 Jul 2014 15:30:55 +0200 Subject: [PATCH 08/39] Add Presentation Manager import Fixes: https://launchpad.net/bugs/957017 --- .../songs/lib/presentationmanagerimport.py | 93 +++++++++++++++++++ .../songs/test_presentationmanagerimport.py | 53 +++++++++++ .../Great Is Thy Faithfulness.json | 25 +++++ .../Great Is Thy Faithfulness.sng | 51 ++++++++++ 4 files changed, 222 insertions(+) create mode 100644 openlp/plugins/songs/lib/presentationmanagerimport.py create mode 100644 tests/functional/openlp_plugins/songs/test_presentationmanagerimport.py create mode 100644 tests/resources/presentationmanagersongs/Great Is Thy Faithfulness.json create mode 100644 tests/resources/presentationmanagersongs/Great Is Thy Faithfulness.sng diff --git a/openlp/plugins/songs/lib/presentationmanagerimport.py b/openlp/plugins/songs/lib/presentationmanagerimport.py new file mode 100644 index 000000000..11f4be81b --- /dev/null +++ b/openlp/plugins/songs/lib/presentationmanagerimport.py @@ -0,0 +1,93 @@ +# -*- coding: utf-8 -*- +# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4 + +############################################################################### +# OpenLP - Open Source Lyrics Projection # +# --------------------------------------------------------------------------- # +# Copyright (c) 2008-2013 Raoul Snyman # +# Portions copyright (c) 2008-2013 Tim Bentley, Gerald Britton, Jonathan # +# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub, # +# Meinert Jordan, Armin Köhler, Erik Lundin, Edwin Lunando, Brian T. Meyer. # +# Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias Põldaru, # +# Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # +# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Dave Warnock, # +# Frode Woldsund, Martin Zibricky, Patrick Zimmermann # +# --------------------------------------------------------------------------- # +# This program is free software; you can redistribute it and/or modify it # +# under the terms of the GNU General Public License as published by the Free # +# Software Foundation; version 2 of the License. # +# # +# This program is distributed in the hope that it will be useful, but WITHOUT # +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # +# more details. # +# # +# You should have received a copy of the GNU General Public License along # +# with this program; if not, write to the Free Software Foundation, Inc., 59 # +# Temple Place, Suite 330, Boston, MA 02111-1307 USA # +############################################################################### +""" +The :mod:`presentationmanagerimport` module provides the functionality for importing +Presentationmanager song files into the current database. +""" + +import os +from lxml import objectify + +from openlp.core.ui.wizard import WizardStrings +from .songimport import SongImport + + +class PresentationManagerImport(SongImport): + """ + The :class:`PresentationManagerImport` class provides OpenLP with the + ability to import Presentationmanager song files. + """ + def do_import(self): + self.import_wizard.progress_bar.setMaximum(len(self.import_source)) + for file_path in self.import_source: + if self.stop_import_flag: + return + self.import_wizard.increment_progress_bar(WizardStrings.ImportingType % os.path.basename(file_path)) + root = objectify.parse(open(file_path, 'rb')).getroot() + self.process_song(root) + + def process_song(self, root): + self.set_defaults() + self.title = str(root.attributes.title) + self.add_author(str(root.attributes.author)) + self.copyright = str(root.attributes.copyright) + self.ccli_number = str(root.attributes.ccli_number) + self.comments = str(root.attributes.comments) + verse_order_list = [] + verse_count = {} + duplicates = [] + for verse in root.verses.verse: + original_verse_def = verse.get('id') + # Presentation Manager stores duplicate verses instead of a verse order. + # We need to create the verse order from that. + is_duplicate = False + if original_verse_def in duplicates: + is_duplicate = True + else: + duplicates.append(original_verse_def) + if original_verse_def.startswith("Verse"): + verse_def = 'v' + elif original_verse_def.startswith("Chorus") or original_verse_def.startswith("Refrain"): + verse_def = 'c' + elif original_verse_def.startswith("Bridge"): + verse_def = 'b' + elif original_verse_def.startswith("End"): + verse_def = 'e' + else: + verse_def = 'o' + if not is_duplicate: # Only increment verse number if no duplicate + verse_count[verse_def] = verse_count.get(verse_def, 0) + 1 + verse_def = '%s%d' % (verse_def, verse_count[verse_def]) + if not is_duplicate: # Only add verse if no duplicate + self.add_verse(str(verse).strip(), verse_def) + verse_order_list.append(verse_def) + + self.verse_order_list = verse_order_list + if not self.finish(): + self.log_error(self.import_source) \ No newline at end of file diff --git a/tests/functional/openlp_plugins/songs/test_presentationmanagerimport.py b/tests/functional/openlp_plugins/songs/test_presentationmanagerimport.py new file mode 100644 index 000000000..34e49146e --- /dev/null +++ b/tests/functional/openlp_plugins/songs/test_presentationmanagerimport.py @@ -0,0 +1,53 @@ +# -*- coding: utf-8 -*- +# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4 + +############################################################################### +# OpenLP - Open Source Lyrics Projection # +# --------------------------------------------------------------------------- # +# Copyright (c) 2008-2014 Raoul Snyman # +# Portions copyright (c) 2008-2014 Tim Bentley, Gerald Britton, Jonathan # +# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub, # +# Meinert Jordan, Armin Köhler, Erik Lundin, Edwin Lunando, Brian T. Meyer. # +# Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias Põldaru, # +# Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # +# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Dave Warnock, # +# Frode Woldsund, Martin Zibricky, Patrick Zimmermann # +# --------------------------------------------------------------------------- # +# This program is free software; you can redistribute it and/or modify it # +# under the terms of the GNU General Public License as published by the Free # +# Software Foundation; version 2 of the License. # +# # +# This program is distributed in the hope that it will be useful, but WITHOUT # +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # +# more details. # +# # +# You should have received a copy of the GNU General Public License along # +# with this program; if not, write to the Free Software Foundation, Inc., 59 # +# Temple Place, Suite 330, Boston, MA 02111-1307 USA # +############################################################################### +""" +This module contains tests for the PresentationManager song importer. +""" + +import os + +from tests.helpers.songfileimport import SongImportTestHelper + +TEST_PATH = os.path.abspath( + os.path.join(os.path.dirname(__file__), '..', '..', '..', 'resources', 'presentationmanagersongs')) + + +class TestSongShowPlusFileImport(SongImportTestHelper): + + def __init__(self, *args, **kwargs): + self.importer_class_name = 'PresentationManagerImport' + self.importer_module_name = 'presentationmanagerimport' + super(TestSongShowPlusFileImport, self).__init__(*args, **kwargs) + + def test_song_import(self): + """ + Test that loading a PresentationManager file works correctly + """ + self.file_import([os.path.join(TEST_PATH, 'Great Is Thy Faithfulness.sng')], + self.load_external_result_data(os.path.join(TEST_PATH, 'Great Is Thy Faithfulness.json'))) diff --git a/tests/resources/presentationmanagersongs/Great Is Thy Faithfulness.json b/tests/resources/presentationmanagersongs/Great Is Thy Faithfulness.json new file mode 100644 index 000000000..5a5c3ddaf --- /dev/null +++ b/tests/resources/presentationmanagersongs/Great Is Thy Faithfulness.json @@ -0,0 +1,25 @@ +{ + "title": "Great Is Thy Faithfulness", + "authors": [ + "Thomas O. Chisholm (1866-1960)" + ], + "verse_order_list": [], + "verses": [ + [ + "\"Great is Thy faithfulness\", O God my Father.\nThere is no shadow of turning with Thee;\nThou changest not, Thy compassions they fail not,\nAs Thou hast been Thou forever shall be.", + "v1" + ], + [ + "Great is Thy faithfulness!\nGreat is Thy faithfulness!\nMorning by morning new mercies I see!\nAll I have needed Thy hand hath provided -\n\"Great is Thy faithfulness\", Lord, unto me!", + "c1" + ], + [ + "Summer and winter, and springtime and harvest,\nSun, moon, and stars in their courses above,\nJoin with all nature in manifold witness,\nTo Thy great faithfulness, mercy and love.", + "v2" + ], + [ + "Pardon for sin and a peace that endureth,\nThine own dear presence to cheer and to guide,\nStrength for today and bright hope for tomorrow,\nBlessings all mine, with ten thousand beside!", + "v3" + ] + ] +} \ No newline at end of file diff --git a/tests/resources/presentationmanagersongs/Great Is Thy Faithfulness.sng b/tests/resources/presentationmanagersongs/Great Is Thy Faithfulness.sng new file mode 100644 index 000000000..49b29c4c7 --- /dev/null +++ b/tests/resources/presentationmanagersongs/Great Is Thy Faithfulness.sng @@ -0,0 +1,51 @@ + + + +Great Is Thy Faithfulness +Thomas O. Chisholm (1866-1960) + + + + + + +"Great is Thy faithfulness", O God my Father. +There is no shadow of turning with Thee; +Thou changest not, Thy compassions they fail not, +As Thou hast been Thou forever shall be. + + +Great is Thy faithfulness! +Great is Thy faithfulness! +Morning by morning new mercies I see! +All I have needed Thy hand hath provided - +"Great is Thy faithfulness", Lord, unto me! + + +Summer and winter, and springtime and harvest, +Sun, moon, and stars in their courses above, +Join with all nature in manifold witness, +To Thy great faithfulness, mercy and love. + + +Great is Thy faithfulness! +Great is Thy faithfulness! +Morning by morning new mercies I see! +All I have needed Thy hand hath provided - +"Great is Thy faithfulness", Lord, unto me! + + +Pardon for sin and a peace that endureth, +Thine own dear presence to cheer and to guide, +Strength for today and bright hope for tomorrow, +Blessings all mine, with ten thousand beside! + + +Great is Thy faithfulness! +Great is Thy faithfulness! +Morning by morning new mercies I see! +All I have needed Thy hand hath provided - +"Great is Thy faithfulness", Lord, unto me! + + + From 398508f49b019c01cc0828e747ffd6fc0803504b Mon Sep 17 00:00:00 2001 From: Samuel Mehrbrodt Date: Mon, 7 Jul 2014 15:36:07 +0200 Subject: [PATCH 09/39] Gui entry --- openlp/plugins/songs/lib/importer.py | 33 +++++++++++++++++----------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/openlp/plugins/songs/lib/importer.py b/openlp/plugins/songs/lib/importer.py index 6d01da309..19543575b 100644 --- a/openlp/plugins/songs/lib/importer.py +++ b/openlp/plugins/songs/lib/importer.py @@ -51,12 +51,11 @@ from .foilpresenterimport import FoilPresenterImport from .zionworximport import ZionWorxImport from .propresenterimport import ProPresenterImport from .worshipassistantimport import WorshipAssistantImport -# Imports that might fail - +from .presentationmanagerimport import PresentationManagerImport log = logging.getLogger(__name__) - +# Imports that might fail try: from .sofimport import SofImport HAS_SOF = True @@ -161,16 +160,17 @@ class SongFormat(object): MediaShout = 9 OpenSong = 10 PowerSong = 11 - ProPresenter = 12 - SongBeamer = 13 - SongPro = 14 - SongShowPlus = 15 - SongsOfFellowship = 16 - SundayPlus = 17 - WordsOfWorship = 18 - WorshipAssistant = 19 - WorshipCenterPro = 20 - ZionWorx = 21 + PresentationManager = 12 + ProPresenter = 13 + SongBeamer = 14 + SongPro = 15 + SongShowPlus = 16 + SongsOfFellowship = 17 + SundayPlus = 18 + WordsOfWorship = 19 + WorshipAssistant = 20 + WorshipCenterPro = 21 + ZionWorx = 22 # Set optional attribute defaults __defaults__ = { @@ -274,6 +274,12 @@ class SongFormat(object): 'invalidSourceMsg': translate('SongsPlugin.ImportWizardForm', 'You need to specify a valid PowerSong 1.0 ' 'database folder.') }, + PresentationManager: { + 'class': PresentationManagerImport, + 'name': 'PresentationManager', + 'prefix': 'presentationManager', + 'filter': '%s (*.sng)' % translate('SongsPlugin.ImportWizardForm', 'PresentationManager Song Files') + }, ProPresenter: { 'class': ProPresenterImport, 'name': 'ProPresenter', @@ -375,6 +381,7 @@ class SongFormat(object): SongFormat.MediaShout, SongFormat.OpenSong, SongFormat.PowerSong, + SongFormat.PresentationManager, SongFormat.ProPresenter, SongFormat.SongBeamer, SongFormat.SongPro, From df6669220a49aba2c141e2ac1375a33db400be54 Mon Sep 17 00:00:00 2001 From: Samuel Mehrbrodt Date: Mon, 7 Jul 2014 18:17:54 +0200 Subject: [PATCH 10/39] Space --- openlp/plugins/songs/lib/importer.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/openlp/plugins/songs/lib/importer.py b/openlp/plugins/songs/lib/importer.py index 6e4aa1fc7..56e4ace01 100644 --- a/openlp/plugins/songs/lib/importer.py +++ b/openlp/plugins/songs/lib/importer.py @@ -34,7 +34,6 @@ import logging from openlp.core.common import translate, UiStrings from openlp.core.ui.wizard import WizardStrings - from .importers.opensong import OpenSongImport from .importers.easyslides import EasySlidesImport from .importers.openlp import OpenLPSongImport @@ -56,7 +55,6 @@ from .importers.presentationmanager import PresentationManagerImport log = logging.getLogger(__name__) - # Imports that might fail try: from .importers.songsoffellowship import SongsOfFellowshipImport From e6f5136708c99f5883d0395e676f17001475a9f7 Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Mon, 7 Jul 2014 19:22:58 +0200 Subject: [PATCH 11/39] Suggested changes to tests --- .../openlp_core_ui/test_thememanager.py | 43 ++++++++++++++----- 1 file changed, 32 insertions(+), 11 deletions(-) diff --git a/tests/functional/openlp_core_ui/test_thememanager.py b/tests/functional/openlp_core_ui/test_thememanager.py index a0bfbd01e..496e78aa4 100644 --- a/tests/functional/openlp_core_ui/test_thememanager.py +++ b/tests/functional/openlp_core_ui/test_thememanager.py @@ -44,30 +44,24 @@ class TestThemeManager(TestCase): def setUp(self): """ - Create the UI + Set up the tests """ Registry.create() - def tearDown(self): - """ - Delete all the C++ objects at the end so that we don't have a segfault - """ - pass - def initial_theme_manager_test(self): """ - Test the initial of theme manager. + Test the instantiation of theme manager. """ # GIVEN: A new service manager instance. ThemeManager(None) # WHEN: the default theme manager is built. # THEN: The the controller should be registered in the registry. - self.assertNotEqual(Registry().get('theme_manager'), None, 'The base theme manager should be registered') + self.assertIsNotNone(Registry().get('theme_manager'), 'The base theme manager should be registered') - def write_theme_test(self): + def write_theme_same_image_test(self): """ - Test that we don't try to overwrite a theme bacground image with itself + Test that we don't try to overwrite a theme background image with itself """ # GIVEN: A new theme manager instance, with mocked builtins.open, shutil.copyfile, # theme, check_directory_exists and thememanager-attributes. @@ -92,3 +86,30 @@ class TestThemeManager(TestCase): # THEN: The mocked_copyfile should not have been called self.assertFalse(mocked_copyfile.called, 'shutil.copyfile should not be called') + + def write_theme_diff_images_test(self): + """ + Test that we do overwrite a theme background image when a new is submitted + """ + # GIVEN: A new theme manager instance, with mocked builtins.open, shutil.copyfile, + # theme, check_directory_exists and thememanager-attributes. + with patch('builtins.open') as mocked_open, \ + patch('openlp.core.ui.thememanager.shutil.copyfile') as mocked_copyfile, \ + patch('openlp.core.ui.thememanager.check_directory_exists') as mocked_check_directory_exists: + mocked_open.return_value = MagicMock() + theme_manager = ThemeManager(None) + theme_manager.old_background_image = None + theme_manager.generate_and_save_image = MagicMock() + theme_manager.path = '' + mocked_theme = MagicMock() + mocked_theme.theme_name = 'themename' + mocked_theme.extract_formatted_xml = MagicMock() + mocked_theme.extract_formatted_xml.return_value = 'fake_theme_xml'.encode() + + # WHEN: Calling _write_theme with path to different images + file_name1 = os.path.join(TEST_RESOURCES_PATH, 'church.jpg') + file_name2 = os.path.join(TEST_RESOURCES_PATH, 'church2.jpg') + theme_manager._write_theme(mocked_theme, file_name1, file_name2) + + # THEN: The mocked_copyfile should not have been called + self.assertTrue(mocked_copyfile.called, 'shutil.copyfile should be called') From fdded5adc22d14f2b04df73d5047679b0597e953 Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Mon, 7 Jul 2014 19:28:27 +0200 Subject: [PATCH 12/39] Fix tag tests --- tests/utils/test_bzr_tags.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/utils/test_bzr_tags.py b/tests/utils/test_bzr_tags.py index acadbd8c4..393f4ce25 100644 --- a/tests/utils/test_bzr_tags.py +++ b/tests/utils/test_bzr_tags.py @@ -50,6 +50,10 @@ TAGS = [ ['1.9.11', '2039'], ['1.9.12', '2063'], ['2.0', '2118'], + ['2.0.1', '?'], + ['2.0.2', '?'], + ['2.0.3', '?'], + ['2.0.4', '?'], ['2.1.0', '2119'] ] From 53cb11e03e5f3dacbffb3aaf8facacfa594d2af9 Mon Sep 17 00:00:00 2001 From: Samuel Mehrbrodt Date: Fri, 11 Jul 2014 16:19:53 +0200 Subject: [PATCH 13/39] EOF; verse order fixed --- openlp/plugins/songs/lib/importers/presentationmanager.py | 2 +- .../presentationmanagersongs/Great Is Thy Faithfulness.json | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/openlp/plugins/songs/lib/importers/presentationmanager.py b/openlp/plugins/songs/lib/importers/presentationmanager.py index 4ea08076e..52a047a30 100644 --- a/openlp/plugins/songs/lib/importers/presentationmanager.py +++ b/openlp/plugins/songs/lib/importers/presentationmanager.py @@ -90,4 +90,4 @@ class PresentationManagerImport(SongImport): self.verse_order_list = verse_order_list if not self.finish(): - self.log_error(self.import_source) \ No newline at end of file + self.log_error(self.import_source) diff --git a/tests/resources/presentationmanagersongs/Great Is Thy Faithfulness.json b/tests/resources/presentationmanagersongs/Great Is Thy Faithfulness.json index 5a5c3ddaf..1e484b11b 100644 --- a/tests/resources/presentationmanagersongs/Great Is Thy Faithfulness.json +++ b/tests/resources/presentationmanagersongs/Great Is Thy Faithfulness.json @@ -3,7 +3,7 @@ "authors": [ "Thomas O. Chisholm (1866-1960)" ], - "verse_order_list": [], + "verse_order_list": ["v1", "c1", "v2", "c1", "v3", "c1"], "verses": [ [ "\"Great is Thy faithfulness\", O God my Father.\nThere is no shadow of turning with Thee;\nThou changest not, Thy compassions they fail not,\nAs Thou hast been Thou forever shall be.", @@ -22,4 +22,4 @@ "v3" ] ] -} \ No newline at end of file +} From 15ca94554b9309b8d57fa98be3e101bf01821805 Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Mon, 14 Jul 2014 09:21:36 +0200 Subject: [PATCH 14/39] Updated jenkins script to match tests --- scripts/jenkins_script.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/scripts/jenkins_script.py b/scripts/jenkins_script.py index eeafbfe23..cd6a0c9cf 100755 --- a/scripts/jenkins_script.py +++ b/scripts/jenkins_script.py @@ -62,11 +62,12 @@ class OpenLPJobs(object): Branch_Pull = 'Branch-01-Pull' Branch_Functional = 'Branch-02-Functional-Tests' Branch_Interface = 'Branch-03-Interface-Tests' - Branch_Windows = 'Branch-04-Windows_Tests' + Branch_Windows_Functional = 'Branch-04a-Windows_Functional_Tests' + Branch_Windows_Interface = 'Branch-04b-Windows_Interface_Tests' Branch_PEP = 'Branch-05a-Code_Analysis' Branch_Coverage = 'Branch-05b-Test_Coverage' - Jobs = [Branch_Pull, Branch_Functional, Branch_Interface, Branch_Windows, Branch_PEP, Branch_Coverage] + Jobs = [Branch_Pull, Branch_Functional, Branch_Interface, Branch_Windows_Functional, Branch_Windows_Interface, Branch_PEP, Branch_Coverage] class Colour(object): From dc4c9f389b0b1a6bb5e14cfe76e6bdb2b1936fe4 Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Mon, 14 Jul 2014 09:27:38 +0200 Subject: [PATCH 15/39] pep8 fix --- scripts/jenkins_script.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/jenkins_script.py b/scripts/jenkins_script.py index cd6a0c9cf..4ee0b3aa2 100755 --- a/scripts/jenkins_script.py +++ b/scripts/jenkins_script.py @@ -67,7 +67,8 @@ class OpenLPJobs(object): Branch_PEP = 'Branch-05a-Code_Analysis' Branch_Coverage = 'Branch-05b-Test_Coverage' - Jobs = [Branch_Pull, Branch_Functional, Branch_Interface, Branch_Windows_Functional, Branch_Windows_Interface, Branch_PEP, Branch_Coverage] + Jobs = [Branch_Pull, Branch_Functional, Branch_Interface, Branch_Windows_Functional, Branch_Windows_Interface, + Branch_PEP, Branch_Coverage] class Colour(object): From 0ce859c2cd6b7b99bc068b759fe35e7cbddb71a3 Mon Sep 17 00:00:00 2001 From: Samuel Mehrbrodt Date: Mon, 14 Jul 2014 13:36:33 +0200 Subject: [PATCH 16/39] Fix import --- openlp/plugins/songs/lib/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openlp/plugins/songs/lib/__init__.py b/openlp/plugins/songs/lib/__init__.py index d03bdefd6..999f51fad 100644 --- a/openlp/plugins/songs/lib/__init__.py +++ b/openlp/plugins/songs/lib/__init__.py @@ -374,7 +374,7 @@ def clean_song(manager, song): :param manager: The song database manager object. :param song: The song object. """ - from .xml import SongXML + from .openlyricsxml import SongXML if song.title: song.title = clean_title(song.title) From 5e349c6c24e5a6278a56fae17f71d4403097493b Mon Sep 17 00:00:00 2001 From: Samuel Mehrbrodt Date: Mon, 14 Jul 2014 18:50:50 +0200 Subject: [PATCH 17/39] Merge conflict --- openlp/plugins/songs/lib/importer.py | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/openlp/plugins/songs/lib/importer.py b/openlp/plugins/songs/lib/importer.py index eb8c8b4d6..0084a74de 100644 --- a/openlp/plugins/songs/lib/importer.py +++ b/openlp/plugins/songs/lib/importer.py @@ -160,23 +160,19 @@ class SongFormat(object): FoilPresenter = 8 MediaShout = 9 OpenSong = 10 -<<<<<<< TREE - PowerSong = 11 - PresentationManager = 12 -======= PowerPraise = 11 PowerSong = 12 ->>>>>>> MERGE-SOURCE - ProPresenter = 13 - SongBeamer = 14 - SongPro = 15 - SongShowPlus = 16 - SongsOfFellowship = 17 - SundayPlus = 18 - WordsOfWorship = 19 - WorshipAssistant = 20 - WorshipCenterPro = 21 - ZionWorx = 22 + PresentationManager = 13 + ProPresenter = 14 + SongBeamer = 15 + SongPro = 16 + SongShowPlus = 17 + SongsOfFellowship = 18 + SundayPlus = 19 + WordsOfWorship = 20 + WorshipAssistant = 21 + WorshipCenterPro = 22 + ZionWorx = 23 # Set optional attribute defaults __defaults__ = { From 2613ad30766800c7547d4aa6e5bb466a44a51f4b Mon Sep 17 00:00:00 2001 From: Samuel Mehrbrodt Date: Thu, 17 Jul 2014 23:04:58 +0200 Subject: [PATCH 18/39] Don't run upgrades on an up to date database --- openlp/core/lib/db.py | 5 +- openlp/plugins/songs/lib/upgrade.py | 65 ++++++++++--------------- openlp/plugins/songusage/lib/upgrade.py | 10 ++-- 3 files changed, 32 insertions(+), 48 deletions(-) diff --git a/openlp/core/lib/db.py b/openlp/core/lib/db.py index d67c05c42..8e9380241 100644 --- a/openlp/core/lib/db.py +++ b/openlp/core/lib/db.py @@ -96,9 +96,10 @@ def upgrade_db(url, upgrade): mapper(Metadata, metadata_table) version_meta = session.query(Metadata).get('version') if version_meta is None: - version_meta = Metadata.populate(key='version', value='0') + # Tables have just been created - fill the version field with the most recent version + version = upgrade.__version__ + version_meta = Metadata.populate(key='version', value=version) session.add(version_meta) - version = 0 else: version = int(version_meta.value) if version > upgrade.__version__: diff --git a/openlp/plugins/songs/lib/upgrade.py b/openlp/plugins/songs/lib/upgrade.py index 580ae767d..5b7255266 100644 --- a/openlp/plugins/songs/lib/upgrade.py +++ b/openlp/plugins/songs/lib/upgrade.py @@ -33,7 +33,6 @@ backend for the Songs plugin import logging from sqlalchemy import Column, ForeignKey, types -from sqlalchemy.exc import OperationalError from sqlalchemy.sql.expression import func, false, null, text from openlp.core.lib.db import get_upgrade_op @@ -57,16 +56,13 @@ def upgrade_1(session, metadata): :param session: :param metadata: """ - try: - op = get_upgrade_op(session) - op.drop_table('media_files_songs') - op.add_column('media_files', Column('song_id', types.Integer(), server_default=null())) - op.add_column('media_files', Column('weight', types.Integer(), server_default=text('0'))) - if metadata.bind.url.get_dialect().name != 'sqlite': - # SQLite doesn't support ALTER TABLE ADD CONSTRAINT - op.create_foreign_key('fk_media_files_song_id', 'media_files', 'songs', ['song_id', 'id']) - except OperationalError: - log.info('Upgrade 1 has already been run') + op = get_upgrade_op(session) + op.drop_table('media_files_songs') + op.add_column('media_files', Column('song_id', types.Integer(), server_default=null())) + op.add_column('media_files', Column('weight', types.Integer(), server_default=text('0'))) + if metadata.bind.url.get_dialect().name != 'sqlite': + # SQLite doesn't support ALTER TABLE ADD CONSTRAINT + op.create_foreign_key('fk_media_files_song_id', 'media_files', 'songs', ['song_id', 'id']) def upgrade_2(session, metadata): @@ -75,12 +71,9 @@ def upgrade_2(session, metadata): This upgrade adds a create_date and last_modified date to the songs table """ - try: - op = get_upgrade_op(session) - op.add_column('songs', Column('create_date', types.DateTime(), default=func.now())) - op.add_column('songs', Column('last_modified', types.DateTime(), default=func.now())) - except OperationalError: - log.info('Upgrade 2 has already been run') + op = get_upgrade_op(session) + op.add_column('songs', Column('create_date', types.DateTime(), default=func.now())) + op.add_column('songs', Column('last_modified', types.DateTime(), default=func.now())) def upgrade_3(session, metadata): @@ -89,14 +82,11 @@ def upgrade_3(session, metadata): This upgrade adds a temporary song flag to the songs table """ - try: - op = get_upgrade_op(session) - if metadata.bind.url.get_dialect().name == 'sqlite': - op.add_column('songs', Column('temporary', types.Boolean(create_constraint=False), server_default=false())) - else: - op.add_column('songs', Column('temporary', types.Boolean(), server_default=false())) - except OperationalError: - log.info('Upgrade 3 has already been run') + op = get_upgrade_op(session) + if metadata.bind.url.get_dialect().name == 'sqlite': + op.add_column('songs', Column('temporary', types.Boolean(create_constraint=False), server_default=false())) + else: + op.add_column('songs', Column('temporary', types.Boolean(), server_default=false())) def upgrade_4(session, metadata): @@ -105,17 +95,14 @@ def upgrade_4(session, metadata): This upgrade adds a column for author type to the authors_songs table """ - try: - # Since SQLite doesn't support changing the primary key of a table, we need to recreate the table - # and copy the old values - op = get_upgrade_op(session) - op.create_table('authors_songs_tmp', - Column('author_id', types.Integer(), ForeignKey('authors.id'), primary_key=True), - Column('song_id', types.Integer(), ForeignKey('songs.id'), primary_key=True), - Column('author_type', types.String(), primary_key=True, - nullable=False, server_default=text('""'))) - op.execute('INSERT INTO authors_songs_tmp SELECT author_id, song_id, "" FROM authors_songs') - op.drop_table('authors_songs') - op.rename_table('authors_songs_tmp', 'authors_songs') - except OperationalError: - log.info('Upgrade 4 has already been run') + # Since SQLite doesn't support changing the primary key of a table, we need to recreate the table + # and copy the old values + op = get_upgrade_op(session) + op.create_table('authors_songs_tmp', + Column('author_id', types.Integer(), ForeignKey('authors.id'), primary_key=True), + Column('song_id', types.Integer(), ForeignKey('songs.id'), primary_key=True), + Column('author_type', types.String(), primary_key=True, + nullable=False, server_default=text('""'))) + op.execute('INSERT INTO authors_songs_tmp SELECT author_id, song_id, "" FROM authors_songs') + op.drop_table('authors_songs') + op.rename_table('authors_songs_tmp', 'authors_songs') diff --git a/openlp/plugins/songusage/lib/upgrade.py b/openlp/plugins/songusage/lib/upgrade.py index 24f264824..b0f0f52f0 100644 --- a/openlp/plugins/songusage/lib/upgrade.py +++ b/openlp/plugins/songusage/lib/upgrade.py @@ -32,7 +32,6 @@ backend for the SongsUsage plugin """ import logging -from sqlalchemy.exc import OperationalError from sqlalchemy import Column, types from openlp.core.lib.db import get_upgrade_op @@ -50,9 +49,6 @@ def upgrade_1(session, metadata): :param session: SQLAlchemy Session object :param metadata: SQLAlchemy MetaData object """ - try: - op = get_upgrade_op(session) - op.add_column('songusage_data', Column('plugin_name', types.Unicode(20), server_default='')) - op.add_column('songusage_data', Column('source', types.Unicode(10), server_default='')) - except OperationalError: - log.info('Upgrade 1 has already taken place') + op = get_upgrade_op(session) + op.add_column('songusage_data', Column('plugin_name', types.Unicode(20), server_default='')) + op.add_column('songusage_data', Column('source', types.Unicode(10), server_default='')) From fa5787e5d86dede1bcb1a7e379746c77f5834cad Mon Sep 17 00:00:00 2001 From: Samuel Mehrbrodt Date: Thu, 17 Jul 2014 23:16:00 +0200 Subject: [PATCH 19/39] Add test --- .../openlp_plugins/songs/test_db.py | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/tests/functional/openlp_plugins/songs/test_db.py b/tests/functional/openlp_plugins/songs/test_db.py index 53b98c045..e696ea94b 100644 --- a/tests/functional/openlp_plugins/songs/test_db.py +++ b/tests/functional/openlp_plugins/songs/test_db.py @@ -125,3 +125,31 @@ class TestDB(TestCase): # THEN: The type should be correct self.assertEqual(author_type, AuthorType.Words) + + def test_author_get_display_name(self): + """ + Test that the display name of an author is correct + """ + # GIVEN: An author + author = Author() + author.display_name = "John Doe" + + # WHEN: We call the get_display_name() function + display_name = author.get_display_name() + + # THEN: It should return only the name + self.assertEqual("John Doe", display_name) + + def test_author_get_display_name_with_type(self): + """ + Test that the display name of an author with a type is correct + """ + # GIVEN: An author + author = Author() + author.display_name = "John Doe" + + # WHEN: We call the get_display_name() function + display_name = author.get_display_name(AuthorType.Words) + + # THEN: It should return the name with the type in brackets + self.assertEqual("John Doe (Words)", display_name) From d4a94d0cd592caac8bc1673acdc3de3d33b776f5 Mon Sep 17 00:00:00 2001 From: Raoul Snyman Date: Thu, 17 Jul 2014 23:46:48 +0200 Subject: [PATCH 20/39] Fix the Windows tests --- scripts/jenkins_script.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/scripts/jenkins_script.py b/scripts/jenkins_script.py index eeafbfe23..cd6a0c9cf 100755 --- a/scripts/jenkins_script.py +++ b/scripts/jenkins_script.py @@ -62,11 +62,12 @@ class OpenLPJobs(object): Branch_Pull = 'Branch-01-Pull' Branch_Functional = 'Branch-02-Functional-Tests' Branch_Interface = 'Branch-03-Interface-Tests' - Branch_Windows = 'Branch-04-Windows_Tests' + Branch_Windows_Functional = 'Branch-04a-Windows_Functional_Tests' + Branch_Windows_Interface = 'Branch-04b-Windows_Interface_Tests' Branch_PEP = 'Branch-05a-Code_Analysis' Branch_Coverage = 'Branch-05b-Test_Coverage' - Jobs = [Branch_Pull, Branch_Functional, Branch_Interface, Branch_Windows, Branch_PEP, Branch_Coverage] + Jobs = [Branch_Pull, Branch_Functional, Branch_Interface, Branch_Windows_Functional, Branch_Windows_Interface, Branch_PEP, Branch_Coverage] class Colour(object): From 2b1b8ac68615f2595266f0c7da202495e823dab2 Mon Sep 17 00:00:00 2001 From: Raoul Snyman Date: Thu, 17 Jul 2014 23:55:54 +0200 Subject: [PATCH 21/39] Make the script stop after a failure. --- scripts/jenkins_script.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/scripts/jenkins_script.py b/scripts/jenkins_script.py index cd6a0c9cf..6c6fdac80 100755 --- a/scripts/jenkins_script.py +++ b/scripts/jenkins_script.py @@ -115,7 +115,9 @@ class JenkinsTrigger(object): print('%s (revision %s)' % (get_repo_name(), revno)) for job in OpenLPJobs.Jobs: - self.__print_build_info(job) + if not self.__print_build_info(job): + print('Stopping after failure') + break def open_browser(self): """ @@ -132,6 +134,7 @@ class JenkinsTrigger(object): :param job_name: The name of the job we want the information from. For example *Branch-01-Pull*. Use the class variables from the :class:`OpenLPJobs` class. """ + is_success = False job = self.jenkins_instance.job(job_name) while job.info['inQueue']: time.sleep(1) @@ -140,11 +143,13 @@ class JenkinsTrigger(object): if build.info['result'] == 'SUCCESS': # Make 'SUCCESS' green. result_string = '%s%s%s' % (Colour.GREEN_START, build.info['result'], Colour.GREEN_END) + is_success = True else: # Make 'FAILURE' red. result_string = '%s%s%s' % (Colour.RED_START, build.info['result'], Colour.RED_END) url = build.info['url'] print('[%s] %s' % (result_string, url)) + return is_success def get_repo_name(): From cad82e637d3a9f5743ddde113d34e50d7c49bd60 Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Fri, 18 Jul 2014 22:09:25 +0100 Subject: [PATCH 22/39] Update script --- scripts/jenkins_script.py | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/scripts/jenkins_script.py b/scripts/jenkins_script.py index eeafbfe23..64d76bef9 100755 --- a/scripts/jenkins_script.py +++ b/scripts/jenkins_script.py @@ -87,7 +87,7 @@ class JenkinsTrigger(object): :param token: The token we need to trigger the build. If you do not have this token, ask in IRC. """ self.token = token - self.repo_name = get_repo_name() + self.base_name, self.repo_name = get_repo_name('b') self.jenkins_instance = Jenkins(JENKINS_URL) def trigger_build(self): @@ -111,7 +111,8 @@ class JenkinsTrigger(object): bzr = Popen(('bzr', 'revno'), stdout=PIPE, stderr=PIPE) raw_output, error = bzr.communicate() revno = raw_output.decode().strip() - print('%s (revision %s)' % (get_repo_name(), revno)) + print('Remote repository: %s ' % self.repo_name) + print(' Local repository: %s (revision %s)' % (self.repo_name, revno)) for job in OpenLPJobs.Jobs: self.__print_build_info(job) @@ -146,7 +147,7 @@ class JenkinsTrigger(object): print('[%s] %s' % (result_string, url)) -def get_repo_name(): +def get_repo_name(branch_type='l'): """ This returns the name of branch of the working directory. For example it returns *lp:~googol/openlp/render*. """ @@ -162,6 +163,7 @@ def get_repo_name(): output_list = list(map(str.strip, raw_output.split('\n'))) # Determine the branch's name repo_name = '' + base_name = '' for line in output_list: # Check if it is remote branch. if 'push branch' in line: @@ -174,7 +176,15 @@ def get_repo_name(): if match: repo_name = 'lp:%s' % match.group(2) break - return repo_name.strip('/') + elif 'repository branch' in line: + base_name = line.split(':')[1] + break + if branch_type == 'b': + return base_name.strip('/'), repo_name.strip('/') + elif branch_type == 'r': + return base_name.strip('/') + else: + return repo_name.strip('/') def main(): @@ -188,9 +198,12 @@ def main(): options, args = parser.parse_args(sys.argv) if len(args) == 2: - if not get_repo_name(): + if not get_repo_name('l'): print('Not a branch. Have you pushed it to launchpad? Did you cd to the branch?') return + if not get_repo_name('r'): + print('No remote branch. Have you pushed it to launchpad? Did you cd to the branch?') + return token = args[-1] if token in OLD_TOKENS: print('Your token is not valid anymore. Get the most recent one.') From 73ec92ae13632028196eeef547228f7527593519 Mon Sep 17 00:00:00 2001 From: Stewart Becker Date: Mon, 21 Jul 2014 07:37:41 +0100 Subject: [PATCH 23/39] Added option to wrap footer text --- openlp/core/common/settings.py | 1 + openlp/core/lib/htmlbuilder.py | 6 ++++-- openlp/core/ui/themestab.py | 14 ++++++++++++++ openlp/plugins/songs/lib/__init__.py | 2 +- 4 files changed, 20 insertions(+), 3 deletions(-) diff --git a/openlp/core/common/settings.py b/openlp/core/common/settings.py index 3b7b31ca1..634bc5ced 100644 --- a/openlp/core/common/settings.py +++ b/openlp/core/common/settings.py @@ -286,6 +286,7 @@ class Settings(QtCore.QSettings): 'themes/last directory export': '', 'themes/last directory import': '', 'themes/theme level': ThemeLevel.Song, + 'themes/wrap footer': False, 'user interface/live panel': True, 'user interface/live splitter geometry': QtCore.QByteArray(), 'user interface/lock panel': False, diff --git a/openlp/core/lib/htmlbuilder.py b/openlp/core/lib/htmlbuilder.py index 473aa9d7d..058e5a2a1 100644 --- a/openlp/core/lib/htmlbuilder.py +++ b/openlp/core/lib/htmlbuilder.py @@ -398,6 +398,7 @@ import logging from PyQt4 import QtWebKit +from openlp.core.common import Settings from openlp.core.lib.theme import BackgroundType, BackgroundGradientType, VerticalType, HorizontalType log = logging.getLogger(__name__) @@ -750,12 +751,13 @@ def build_footer_css(item, height): font-size: %spt; color: %s; text-align: left; - white-space: nowrap; + white-space: %s; """ theme = item.theme_data if not theme or not item.footer: return '' bottom = height - int(item.footer.y()) - int(item.footer.height()) + whitespace = 'normal' if Settings().value('themes/wrap footer') else 'nowrap' lyrics_html = style % (item.footer.x(), bottom, item.footer.width(), - theme.font_footer_name, theme.font_footer_size, theme.font_footer_color) + theme.font_footer_name, theme.font_footer_size, theme.font_footer_color, whitespace) return lyrics_html diff --git a/openlp/core/ui/themestab.py b/openlp/core/ui/themestab.py index 0478f0ed0..230439566 100644 --- a/openlp/core/ui/themestab.py +++ b/openlp/core/ui/themestab.py @@ -69,6 +69,14 @@ class ThemesTab(SettingsTab): self.default_list_view.setObjectName('default_list_view') self.global_group_box_layout.addWidget(self.default_list_view) self.left_layout.addWidget(self.global_group_box) + self.universal_group_box = QtGui.QGroupBox(self.left_column) + self.universal_group_box.setObjectName('universal_group_box') + self.universal_group_box_layout = QtGui.QVBoxLayout(self.universal_group_box) + self.universal_group_box_layout.setObjectName('universal_group_box_layout') + self.wrap_footer_check_box = QtGui.QCheckBox(self.universal_group_box) + self.wrap_footer_check_box.setObjectName('wrap_footer_check_box') + self.universal_group_box_layout.addWidget(self.wrap_footer_check_box) + self.left_layout.addWidget(self.universal_group_box) self.left_layout.addStretch() self.level_group_box = QtGui.QGroupBox(self.right_column) self.level_group_box.setObjectName('level_group_box') @@ -112,6 +120,8 @@ class ThemesTab(SettingsTab): """ self.tab_title_visible = UiStrings().Themes self.global_group_box.setTitle(translate('OpenLP.ThemesTab', 'Global Theme')) + self.universal_group_box.setTitle(translate('OpenLP.ThemesTab', 'Universal Settings')) + self.wrap_footer_check_box.setText(translate('OpenLP.ThemesTab', '&Wrap footer text')) self.level_group_box.setTitle(translate('OpenLP.ThemesTab', 'Theme Level')) self.song_level_radio_button.setText(translate('OpenLP.ThemesTab', 'S&ong Level')) self.song_level_label.setText( @@ -136,6 +146,7 @@ class ThemesTab(SettingsTab): settings.beginGroup(self.settings_section) self.theme_level = settings.value('theme level') self.global_theme = settings.value('global theme') + wrap_footer = settings.value('wrap footer') settings.endGroup() if self.theme_level == ThemeLevel.Global: self.global_level_radio_button.setChecked(True) @@ -143,15 +154,18 @@ class ThemesTab(SettingsTab): self.service_level_radio_button.setChecked(True) else: self.song_level_radio_button.setChecked(True) + self.wrap_footer_check_box.setChecked(wrap_footer) def save(self): """ Save the settings """ + wrap_footer = self.wrap_footer_check_box.isChecked() settings = Settings() settings.beginGroup(self.settings_section) settings.setValue('theme level', self.theme_level) settings.setValue('global theme', self.global_theme) + settings.setValue('wrap footer', wrap_footer) settings.endGroup() self.renderer.set_theme_level(self.theme_level) if self.tab_visited: diff --git a/openlp/plugins/songs/lib/__init__.py b/openlp/plugins/songs/lib/__init__.py index d03bdefd6..999f51fad 100644 --- a/openlp/plugins/songs/lib/__init__.py +++ b/openlp/plugins/songs/lib/__init__.py @@ -374,7 +374,7 @@ def clean_song(manager, song): :param manager: The song database manager object. :param song: The song object. """ - from .xml import SongXML + from .openlyricsxml import SongXML if song.title: song.title = clean_title(song.title) From 2555bc50d4ed202b13a5d0c60ead773b8a4e3b21 Mon Sep 17 00:00:00 2001 From: Stewart Becker Date: Mon, 21 Jul 2014 18:13:20 +0100 Subject: [PATCH 24/39] Add test for wrap footer setting --- .../openlp_core_lib/test_htmlbuilder.py | 35 ++++++++++++++++--- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/tests/functional/openlp_core_lib/test_htmlbuilder.py b/tests/functional/openlp_core_lib/test_htmlbuilder.py index ef5ffdf43..a68e14061 100644 --- a/tests/functional/openlp_core_lib/test_htmlbuilder.py +++ b/tests/functional/openlp_core_lib/test_htmlbuilder.py @@ -6,10 +6,12 @@ from unittest import TestCase from PyQt4 import QtCore +from openlp.core.common import Settings from openlp.core.lib.htmlbuilder import build_html, build_background_css, build_lyrics_css, build_lyrics_outline_css, \ build_lyrics_format_css, build_footer_css from openlp.core.lib.theme import HorizontalType, VerticalType from tests.functional import MagicMock, patch +from tests.helpers.testmixin import TestMixin HTML = """ @@ -184,7 +186,7 @@ LYRICS_OUTLINE_CSS = ' -webkit-text-stroke: 0.125em #000000; -webkit-text-fill-c LYRICS_FORMAT_CSS = ' word-wrap: break-word; text-align: justify; vertical-align: bottom; ' + \ 'font-family: Arial; font-size: 40pt; color: #FFFFFF; line-height: 108%; margin: 0;padding: 0; ' + \ 'padding-bottom: 0.5em; padding-left: 2px; width: 1580px; height: 810px; font-style:italic; font-weight:bold; ' -FOOTER_CSS = """ +FOOTER_CSS_BASE = """ left: 10px; bottom: 0px; width: 1260px; @@ -192,11 +194,29 @@ FOOTER_CSS = """ font-size: 12pt; color: #FFFFFF; text-align: left; - white-space: nowrap; + white-space: %s; """ +FOOTER_CSS = FOOTER_CSS_BASE % ('nowrap') +FOOTER_CSS_WRAP = FOOTER_CSS_BASE % ('normal') + + +class Htmbuilder(TestCase, TestMixin): + """ + Test the functions in the Htmlbuilder module + """ + def setUp(self): + """ + Create the UI + """ + self.build_settings() + + def tearDown(self): + """ + Delete all the C++ objects at the end so that we don't have a segfault + """ + self.destroy_settings() -class Htmbuilder(TestCase): def build_html_test(self): """ Test the build_html() function @@ -316,8 +336,15 @@ class Htmbuilder(TestCase): item.theme_data.font_footer_color = '#FFFFFF' height = 1024 - # WHEN: create the css. + # WHEN: create the css with default settings. css = build_footer_css(item, height) # THEN: THE css should be the same. assert FOOTER_CSS == css, 'The footer strings should be equal.' + + # WHEN: Settings say that footer should wrap + Settings().setValue('themes/wrap footer', True) + css = build_footer_css(item, height) + + # THEN: Footer should wrap + assert FOOTER_CSS_WRAP == css, 'The footer strings should be equal.' From 9a1ce000b7bfa79216d6aa6eb5ba767c9a7f6194 Mon Sep 17 00:00:00 2001 From: Stewart Becker Date: Mon, 21 Jul 2014 22:45:27 +0100 Subject: [PATCH 25/39] Patch Registry.execute so that it is undoen at end of test --- .../openlp_core_ui/test_slidecontroller.py | 46 ++++++++++--------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/tests/functional/openlp_core_ui/test_slidecontroller.py b/tests/functional/openlp_core_ui/test_slidecontroller.py index ed237d424..ea68b8ae9 100644 --- a/tests/functional/openlp_core_ui/test_slidecontroller.py +++ b/tests/functional/openlp_core_ui/test_slidecontroller.py @@ -508,18 +508,18 @@ class TestSlideController(TestCase): mocked_update_preview = MagicMock() mocked_preview_widget = MagicMock() mocked_slide_selected = MagicMock() - Registry.execute = mocked_execute - Registry.create() - slide_controller = SlideController(None) - slide_controller.service_item = mocked_item - slide_controller.update_preview = mocked_update_preview - slide_controller.preview_widget = mocked_preview_widget - slide_controller.slide_selected = mocked_slide_selected - slide_controller.is_live = True - - # WHEN: The method is called - slide_controller.on_slide_selected_index([9]) - + with patch.object(Registry, 'execute') as mocked_execute: + Registry.create() + slide_controller = SlideController(None) + slide_controller.service_item = mocked_item + slide_controller.update_preview = mocked_update_preview + slide_controller.preview_widget = mocked_preview_widget + slide_controller.slide_selected = mocked_slide_selected + slide_controller.is_live = True + + # WHEN: The method is called + slide_controller.on_slide_selected_index([9]) + # THEN: It should have sent a notification mocked_item.is_command.assert_called_once_with() mocked_execute.assert_called_once_with('mocked item_slide', [mocked_item, True, 9]) @@ -539,16 +539,16 @@ class TestSlideController(TestCase): mocked_update_preview = MagicMock() mocked_preview_widget = MagicMock() mocked_slide_selected = MagicMock() - Registry.execute = mocked_execute - Registry.create() - slide_controller = SlideController(None) - slide_controller.service_item = mocked_item - slide_controller.update_preview = mocked_update_preview - slide_controller.preview_widget = mocked_preview_widget - slide_controller.slide_selected = mocked_slide_selected - - # WHEN: The method is called - slide_controller.on_slide_selected_index([7]) + with patch.object(Registry, 'execute') as mocked_execute: + Registry.create() + slide_controller = SlideController(None) + slide_controller.service_item = mocked_item + slide_controller.update_preview = mocked_update_preview + slide_controller.preview_widget = mocked_preview_widget + slide_controller.slide_selected = mocked_slide_selected + + # WHEN: The method is called + slide_controller.on_slide_selected_index([7]) # THEN: It should have sent a notification mocked_item.is_command.assert_called_once_with() @@ -556,3 +556,5 @@ class TestSlideController(TestCase): self.assertEqual(0, mocked_update_preview.call_count, 'Update preview should not have been called') mocked_preview_widget.change_slide.assert_called_once_with(7) mocked_slide_selected.assert_called_once_with() + + From 668864c38d474ca3e56c7e984f0553f9a44d8027 Mon Sep 17 00:00:00 2001 From: Stewart Becker Date: Tue, 22 Jul 2014 21:06:48 +0100 Subject: [PATCH 26/39] Tidy up tests and formatting --- .../functional/openlp_core_lib/test_htmlbuilder.py | 14 ++++++++++++-- .../openlp_core_ui/test_slidecontroller.py | 10 +++------- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/tests/functional/openlp_core_lib/test_htmlbuilder.py b/tests/functional/openlp_core_lib/test_htmlbuilder.py index a68e14061..e98dfc687 100644 --- a/tests/functional/openlp_core_lib/test_htmlbuilder.py +++ b/tests/functional/openlp_core_lib/test_htmlbuilder.py @@ -13,7 +13,6 @@ from openlp.core.lib.theme import HorizontalType, VerticalType from tests.functional import MagicMock, patch from tests.helpers.testmixin import TestMixin - HTML = """ @@ -216,7 +215,6 @@ class Htmbuilder(TestCase, TestMixin): """ self.destroy_settings() - def build_html_test(self): """ Test the build_html() function @@ -342,6 +340,18 @@ class Htmbuilder(TestCase, TestMixin): # THEN: THE css should be the same. assert FOOTER_CSS == css, 'The footer strings should be equal.' + def build_footer_css_wrap_test(self): + """ + Test the build_footer_css() function + """ + # GIVEN: Create a theme. + item = MagicMock() + item.footer = QtCore.QRect(10, 921, 1260, 103) + item.theme_data.font_footer_name = 'Arial' + item.theme_data.font_footer_size = 12 + item.theme_data.font_footer_color = '#FFFFFF' + height = 1024 + # WHEN: Settings say that footer should wrap Settings().setValue('themes/wrap footer', True) css = build_footer_css(item, height) diff --git a/tests/functional/openlp_core_ui/test_slidecontroller.py b/tests/functional/openlp_core_ui/test_slidecontroller.py index ea68b8ae9..1d241a317 100644 --- a/tests/functional/openlp_core_ui/test_slidecontroller.py +++ b/tests/functional/openlp_core_ui/test_slidecontroller.py @@ -504,7 +504,6 @@ class TestSlideController(TestCase): mocked_item = MagicMock() mocked_item.is_command.return_value = True mocked_item.name = 'Mocked Item' - mocked_execute = MagicMock() mocked_update_preview = MagicMock() mocked_preview_widget = MagicMock() mocked_slide_selected = MagicMock() @@ -516,10 +515,10 @@ class TestSlideController(TestCase): slide_controller.preview_widget = mocked_preview_widget slide_controller.slide_selected = mocked_slide_selected slide_controller.is_live = True - + # WHEN: The method is called slide_controller.on_slide_selected_index([9]) - + # THEN: It should have sent a notification mocked_item.is_command.assert_called_once_with() mocked_execute.assert_called_once_with('mocked item_slide', [mocked_item, True, 9]) @@ -535,7 +534,6 @@ class TestSlideController(TestCase): mocked_item = MagicMock() mocked_item.is_command.return_value = False mocked_item.name = 'Mocked Item' - mocked_execute = MagicMock() mocked_update_preview = MagicMock() mocked_preview_widget = MagicMock() mocked_slide_selected = MagicMock() @@ -546,7 +544,7 @@ class TestSlideController(TestCase): slide_controller.update_preview = mocked_update_preview slide_controller.preview_widget = mocked_preview_widget slide_controller.slide_selected = mocked_slide_selected - + # WHEN: The method is called slide_controller.on_slide_selected_index([7]) @@ -556,5 +554,3 @@ class TestSlideController(TestCase): self.assertEqual(0, mocked_update_preview.call_count, 'Update preview should not have been called') mocked_preview_widget.change_slide.assert_called_once_with(7) mocked_slide_selected.assert_called_once_with() - - From d90fcface2853d0d6d0f4abc18168e20eb317f97 Mon Sep 17 00:00:00 2001 From: Stewart Becker Date: Thu, 24 Jul 2014 20:28:57 +0100 Subject: [PATCH 27/39] Style fixes for Tim --- openlp/core/ui/themestab.py | 6 ++---- tests/functional/openlp_core_lib/test_htmlbuilder.py | 4 ++-- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/openlp/core/ui/themestab.py b/openlp/core/ui/themestab.py index 230439566..4b3f8b6eb 100644 --- a/openlp/core/ui/themestab.py +++ b/openlp/core/ui/themestab.py @@ -146,7 +146,7 @@ class ThemesTab(SettingsTab): settings.beginGroup(self.settings_section) self.theme_level = settings.value('theme level') self.global_theme = settings.value('global theme') - wrap_footer = settings.value('wrap footer') + self.wrap_footer_check_box.setChecked(settings.value('wrap footer')) settings.endGroup() if self.theme_level == ThemeLevel.Global: self.global_level_radio_button.setChecked(True) @@ -154,18 +154,16 @@ class ThemesTab(SettingsTab): self.service_level_radio_button.setChecked(True) else: self.song_level_radio_button.setChecked(True) - self.wrap_footer_check_box.setChecked(wrap_footer) def save(self): """ Save the settings """ - wrap_footer = self.wrap_footer_check_box.isChecked() settings = Settings() settings.beginGroup(self.settings_section) settings.setValue('theme level', self.theme_level) settings.setValue('global theme', self.global_theme) - settings.setValue('wrap footer', wrap_footer) + settings.setValue('wrap footer', self.wrap_footer_check_box.isChecked()) settings.endGroup() self.renderer.set_theme_level(self.theme_level) if self.tab_visited: diff --git a/tests/functional/openlp_core_lib/test_htmlbuilder.py b/tests/functional/openlp_core_lib/test_htmlbuilder.py index e98dfc687..4563c98b4 100644 --- a/tests/functional/openlp_core_lib/test_htmlbuilder.py +++ b/tests/functional/openlp_core_lib/test_htmlbuilder.py @@ -320,7 +320,7 @@ class Htmbuilder(TestCase, TestMixin): css = build_lyrics_format_css(theme_data, width, height) # THEN: They should be equal. - assert LYRICS_FORMAT_CSS == css, 'The lyrics format css should be equal.' + self.assertEqual(LYRICS_FORMAT_CSS, css, 'The lyrics format css should be equal.') def build_footer_css_test(self): """ @@ -357,4 +357,4 @@ class Htmbuilder(TestCase, TestMixin): css = build_footer_css(item, height) # THEN: Footer should wrap - assert FOOTER_CSS_WRAP == css, 'The footer strings should be equal.' + self.assertEqual(FOOTER_CSS_WRAP, css, 'The footer strings should be equal.') From 2f984c45c48f7857ec57758dc6b32ee09a19ff51 Mon Sep 17 00:00:00 2001 From: Stewart Becker Date: Thu, 24 Jul 2014 22:57:16 +0100 Subject: [PATCH 28/39] Style fixes for Tim --- tests/functional/openlp_core_lib/test_htmlbuilder.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/functional/openlp_core_lib/test_htmlbuilder.py b/tests/functional/openlp_core_lib/test_htmlbuilder.py index 4563c98b4..7ba63a792 100644 --- a/tests/functional/openlp_core_lib/test_htmlbuilder.py +++ b/tests/functional/openlp_core_lib/test_htmlbuilder.py @@ -243,7 +243,7 @@ class Htmbuilder(TestCase, TestMixin): html = build_html(item, screen, is_live, background, plugins=plugins) # THEN: The returned html should match. - assert html == HTML + self.assertEqual(html, HTML, 'The returned html should match') def build_background_css_radial_test(self): """ @@ -259,7 +259,7 @@ class Htmbuilder(TestCase, TestMixin): css = build_background_css(item, width) # THEN: The returned css should match. - assert BACKGROUND_CSS_RADIAL == css, 'The background css should be equal.' + self.assertEqual(BACKGROUND_CSS_RADIAL, css, 'The background css should be equal.') def build_lyrics_css_test(self): """ @@ -280,7 +280,7 @@ class Htmbuilder(TestCase, TestMixin): css = build_lyrics_css(item) # THEN: The css should be equal. - assert LYRICS_CSS == css, 'The lyrics css should be equal.' + self.assertEqual(LYRICS_CSS, css, 'The lyrics css should be equal.') def build_lyrics_outline_css_test(self): """ @@ -297,7 +297,7 @@ class Htmbuilder(TestCase, TestMixin): css = build_lyrics_outline_css(theme_data) # THEN: The css should be equal. - assert LYRICS_OUTLINE_CSS == css, 'The outline css should be equal.' + self.assertEqual(LYRICS_OUTLINE_CSS, css, 'The outline css should be equal.') def build_lyrics_format_css_test(self): """ @@ -338,7 +338,7 @@ class Htmbuilder(TestCase, TestMixin): css = build_footer_css(item, height) # THEN: THE css should be the same. - assert FOOTER_CSS == css, 'The footer strings should be equal.' + self.assertEqual(FOOTER_CSS, css, 'The footer strings should be equal.') def build_footer_css_wrap_test(self): """ From 63f08f0c4aba91196866aaeb5a78da99e075ad54 Mon Sep 17 00:00:00 2001 From: Samuel Mehrbrodt Date: Mon, 18 Aug 2014 20:45:15 +0200 Subject: [PATCH 29/39] Fix ProPresenter import Fixes: https://launchpad.net/bugs/1358418 --- openlp/plugins/songs/lib/importer.py | 2 +- openlp/plugins/songs/lib/importers/__init__.py | 2 +- openlp/plugins/songs/lib/importers/propresenter.py | 11 ++++++++++- openlp/plugins/songs/lib/importers/songimport.py | 9 +++++++++ 4 files changed, 21 insertions(+), 3 deletions(-) diff --git a/openlp/plugins/songs/lib/importer.py b/openlp/plugins/songs/lib/importer.py index 0084a74de..9c17e1f67 100644 --- a/openlp/plugins/songs/lib/importer.py +++ b/openlp/plugins/songs/lib/importer.py @@ -292,7 +292,7 @@ class SongFormat(object): 'class': ProPresenterImport, 'name': 'ProPresenter', 'prefix': 'proPresenter', - 'filter': '%s (*.pro4)' % translate('SongsPlugin.ImportWizardForm', 'ProPresenter Song Files') + 'filter': '%s (*.pro4)' % translate('SongsPlugin.ImportWizardForm', 'ProPresenter 4 Song Files') }, SongBeamer: { 'class': SongBeamerImport, diff --git a/openlp/plugins/songs/lib/importers/__init__.py b/openlp/plugins/songs/lib/importers/__init__.py index da302572e..f86a3e95e 100644 --- a/openlp/plugins/songs/lib/importers/__init__.py +++ b/openlp/plugins/songs/lib/importers/__init__.py @@ -27,5 +27,5 @@ # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### """ -The :mod:`~openlp.plugins.songs.lib.import` module contains importers for the Songs plugin. +The :mod:`~openlp.plugins.songs.lib.importers` module contains importers for the Songs plugin. """ diff --git a/openlp/plugins/songs/lib/importers/propresenter.py b/openlp/plugins/songs/lib/importers/propresenter.py index 3bf7f9cd8..ca9a2e9c8 100644 --- a/openlp/plugins/songs/lib/importers/propresenter.py +++ b/openlp/plugins/songs/lib/importers/propresenter.py @@ -33,17 +33,20 @@ ProPresenter song files into the current installation database. import os import base64 +import logging from lxml import objectify from openlp.core.ui.wizard import WizardStrings from openlp.plugins.songs.lib import strip_rtf from .songimport import SongImport +log = logging.getLogger(__name__) + class ProPresenterImport(SongImport): """ The :class:`ProPresenterImport` class provides OpenLP with the - ability to import ProPresenter song files. + ability to import ProPresenter 4 song files. """ def do_import(self): self.import_wizard.progress_bar.setMaximum(len(self.import_source)) @@ -67,9 +70,15 @@ class ProPresenterImport(SongImport): count = 0 for slide in root.slides.RVDisplaySlide: count += 1 + if not hasattr(slide.displayElements, 'RVTextElement'): + log.debug('No text found, may be an image slide') + continue RTFData = slide.displayElements.RVTextElement.get('RTFData') rtf = base64.standard_b64decode(RTFData) words, encoding = strip_rtf(rtf.decode()) self.add_verse(words, "v%d" % count) + # Some songs don't have a title - use the first line as title + if not self.title: + self.title = self.guess_title() if not self.finish(): self.log_error(self.import_source) diff --git a/openlp/plugins/songs/lib/importers/songimport.py b/openlp/plugins/songs/lib/importers/songimport.py index 5382efbe5..14622e978 100644 --- a/openlp/plugins/songs/lib/importers/songimport.py +++ b/openlp/plugins/songs/lib/importers/songimport.py @@ -316,6 +316,15 @@ class SongImport(QtCore.QObject): self.verse_order_list_generated.append(self.verse_order_list_generated[-1]) self.verse_order_list_generated_useful = True + def guess_title(self): + """ + Guess the title from the first verse (to be used when the song has no title information) + :return: The guessed title + """ + if not self.verses: + return '' + return self.verses[0][1].split('\n')[0].strip() + def check_complete(self): """ Check the mandatory fields are entered (i.e. title and a verse) From 0bf256070a898317a88d0cfca8af6ca9aa16c3dd Mon Sep 17 00:00:00 2001 From: Samuel Mehrbrodt Date: Mon, 18 Aug 2014 21:04:46 +0200 Subject: [PATCH 30/39] Add test --- .../songs/lib/importers/propresenter.py | 9 ++--- .../plugins/songs/lib/importers/songimport.py | 9 ----- .../songs/test_propresenterimport.py | 2 ++ .../propresentersongs/Vaste Grond.json | 34 +++++++++++++++++++ .../propresentersongs/Vaste Grond.pro4 | 1 + 5 files changed, 40 insertions(+), 15 deletions(-) create mode 100644 tests/resources/propresentersongs/Vaste Grond.json create mode 100644 tests/resources/propresentersongs/Vaste Grond.pro4 diff --git a/openlp/plugins/songs/lib/importers/propresenter.py b/openlp/plugins/songs/lib/importers/propresenter.py index ca9a2e9c8..b0509393b 100644 --- a/openlp/plugins/songs/lib/importers/propresenter.py +++ b/openlp/plugins/songs/lib/importers/propresenter.py @@ -55,11 +55,11 @@ class ProPresenterImport(SongImport): return self.import_wizard.increment_progress_bar(WizardStrings.ImportingType % os.path.basename(file_path)) root = objectify.parse(open(file_path, 'rb')).getroot() - self.process_song(root) + self.process_song(root, file_path) - def process_song(self, root): + def process_song(self, root, filename): self.set_defaults() - self.title = root.get('CCLISongTitle') + self.title = os.path.basename(filename).rstrip('.pro4') self.copyright = root.get('CCLICopyrightInfo') self.comments = root.get('notes') self.ccli_number = root.get('CCLILicenseNumber') @@ -77,8 +77,5 @@ class ProPresenterImport(SongImport): rtf = base64.standard_b64decode(RTFData) words, encoding = strip_rtf(rtf.decode()) self.add_verse(words, "v%d" % count) - # Some songs don't have a title - use the first line as title - if not self.title: - self.title = self.guess_title() if not self.finish(): self.log_error(self.import_source) diff --git a/openlp/plugins/songs/lib/importers/songimport.py b/openlp/plugins/songs/lib/importers/songimport.py index 14622e978..5382efbe5 100644 --- a/openlp/plugins/songs/lib/importers/songimport.py +++ b/openlp/plugins/songs/lib/importers/songimport.py @@ -316,15 +316,6 @@ class SongImport(QtCore.QObject): self.verse_order_list_generated.append(self.verse_order_list_generated[-1]) self.verse_order_list_generated_useful = True - def guess_title(self): - """ - Guess the title from the first verse (to be used when the song has no title information) - :return: The guessed title - """ - if not self.verses: - return '' - return self.verses[0][1].split('\n')[0].strip() - def check_complete(self): """ Check the mandatory fields are entered (i.e. title and a verse) diff --git a/tests/functional/openlp_plugins/songs/test_propresenterimport.py b/tests/functional/openlp_plugins/songs/test_propresenterimport.py index 3b79961f9..f3bdcb959 100644 --- a/tests/functional/openlp_plugins/songs/test_propresenterimport.py +++ b/tests/functional/openlp_plugins/songs/test_propresenterimport.py @@ -52,3 +52,5 @@ class TestProPresenterFileImport(SongImportTestHelper): """ self.file_import([os.path.join(TEST_PATH, 'Amazing Grace.pro4')], self.load_external_result_data(os.path.join(TEST_PATH, 'Amazing Grace.json'))) + self.file_import([os.path.join(TEST_PATH, 'Vaste Grond.pro4')], + self.load_external_result_data(os.path.join(TEST_PATH, 'Vaste Grond.json'))) diff --git a/tests/resources/propresentersongs/Vaste Grond.json b/tests/resources/propresentersongs/Vaste Grond.json new file mode 100644 index 000000000..f55abd83e --- /dev/null +++ b/tests/resources/propresentersongs/Vaste Grond.json @@ -0,0 +1,34 @@ +{ + "title": "Vaste Grond", + "verse_order_list": [], + "verses": [ + [ + "God voor U is niets onmogelijk\nHoe ongelofelijk\nU heeft alles in de hand", + "v1" + ], + [ + "U bent God en trekt Uw eigen plan\nU bent voor niemand bang\nVoor niets en niemand bang", + "v2" + ], + [ + "U houd me vast en geeft me moed\nOm door te gaan als ik niet durf\nIk wil van U zijn", + "v3" + ], + [ + "U geeft me kracht, en bent de vaste grond\nwaarop ik stevig sta\nik wil van U zijn, voor altijd van U zijn\nO God.", + "v4" + ], + [ + "Grote God, U bent uitzonderlijk\nen ondoorgrondelijk\nU biedt Uw liefde aan", + "v5" + ], + [ + "Wie ben ik, dat U mij ziet staan\nen met mij om wilt gaan?\nIk kan U niet weerstaan", + "v6" + ], + [ + "Onweerstaanbaar,\nonweerstaanbare God", + "v7" + ] + ] +} \ No newline at end of file diff --git a/tests/resources/propresentersongs/Vaste Grond.pro4 b/tests/resources/propresentersongs/Vaste Grond.pro4 new file mode 100644 index 000000000..7abfb593d --- /dev/null +++ b/tests/resources/propresentersongs/Vaste Grond.pro4 @@ -0,0 +1 @@ +<_-RVRect3D-_position x="32.37209" y="29" z="0" width="1074.349" height="818.7442"><_-D-_serializedShadow containerClass="NSMutableDictionary"><_-RVRect3D-_position x="32.37209" y="29" z="0" width="1074.349" height="818.7442"><_-D-_serializedShadow containerClass="NSMutableDictionary"><_-RVRect3D-_position x="32.37209" y="29" z="0" width="1074.349" height="818.7442"><_-D-_serializedShadow containerClass="NSMutableDictionary"><_-RVRect3D-_position x="32.37209" y="29" z="0" width="1074.349" height="818.7442"><_-D-_serializedShadow containerClass="NSMutableDictionary"><_-RVRect3D-_position x="32.37209" y="29" z="0" width="1074.349" height="818.7442"><_-D-_serializedShadow containerClass="NSMutableDictionary"><_-RVRect3D-_position x="32.37209" y="29" z="0" width="1074.349" height="818.7442"><_-D-_serializedShadow containerClass="NSMutableDictionary"><_-RVRect3D-_position x="32.37209" y="29" z="0" width="1074.349" height="818.7442"><_-D-_serializedShadow containerClass="NSMutableDictionary"> \ No newline at end of file From eeeb2b558ee7080fe378bdb496d5f146970a846f Mon Sep 17 00:00:00 2001 From: Samuel Mehrbrodt Date: Mon, 18 Aug 2014 21:05:39 +0200 Subject: [PATCH 31/39] PEP8 --- scripts/jenkins_script.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/jenkins_script.py b/scripts/jenkins_script.py index 6c6fdac80..d7c8a3427 100755 --- a/scripts/jenkins_script.py +++ b/scripts/jenkins_script.py @@ -67,7 +67,8 @@ class OpenLPJobs(object): Branch_PEP = 'Branch-05a-Code_Analysis' Branch_Coverage = 'Branch-05b-Test_Coverage' - Jobs = [Branch_Pull, Branch_Functional, Branch_Interface, Branch_Windows_Functional, Branch_Windows_Interface, Branch_PEP, Branch_Coverage] + Jobs = [Branch_Pull, Branch_Functional, Branch_Interface, Branch_Windows_Functional, + Branch_Windows_Interface, Branch_PEP, Branch_Coverage] class Colour(object): From bde55c79f87d911a675f4556379a85ac51aa78b1 Mon Sep 17 00:00:00 2001 From: Samuel Mehrbrodt Date: Mon, 18 Aug 2014 21:15:23 +0200 Subject: [PATCH 32/39] No newline at end of file... --- tests/resources/propresentersongs/Vaste Grond.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/resources/propresentersongs/Vaste Grond.json b/tests/resources/propresentersongs/Vaste Grond.json index f55abd83e..75ffac7a2 100644 --- a/tests/resources/propresentersongs/Vaste Grond.json +++ b/tests/resources/propresentersongs/Vaste Grond.json @@ -31,4 +31,4 @@ "v7" ] ] -} \ No newline at end of file +} From ce26493dac45976aa2b54aa75d370dcc3e670f3c Mon Sep 17 00:00:00 2001 From: Samuel Mehrbrodt Date: Tue, 19 Aug 2014 07:57:54 +0200 Subject: [PATCH 33/39] We only support v4 files --- openlp/plugins/songs/lib/importer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openlp/plugins/songs/lib/importer.py b/openlp/plugins/songs/lib/importer.py index 9c17e1f67..e9ee2c2f3 100644 --- a/openlp/plugins/songs/lib/importer.py +++ b/openlp/plugins/songs/lib/importer.py @@ -290,7 +290,7 @@ class SongFormat(object): }, ProPresenter: { 'class': ProPresenterImport, - 'name': 'ProPresenter', + 'name': 'ProPresenter 4', 'prefix': 'proPresenter', 'filter': '%s (*.pro4)' % translate('SongsPlugin.ImportWizardForm', 'ProPresenter 4 Song Files') }, From 49fca807f4d476fd00b0bf872f24e89932719938 Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Thu, 21 Aug 2014 14:41:46 +0200 Subject: [PATCH 34/39] deleted file leftover from merge --- .../openlp_core_ui/test_thememanager.py.moved | 115 ------------------ 1 file changed, 115 deletions(-) delete mode 100644 tests/functional/openlp_core_ui/test_thememanager.py.moved diff --git a/tests/functional/openlp_core_ui/test_thememanager.py.moved b/tests/functional/openlp_core_ui/test_thememanager.py.moved deleted file mode 100644 index 496e78aa4..000000000 --- a/tests/functional/openlp_core_ui/test_thememanager.py.moved +++ /dev/null @@ -1,115 +0,0 @@ -# -*- coding: utf-8 -*- -# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4 - -############################################################################### -# OpenLP - Open Source Lyrics Projection # -# --------------------------------------------------------------------------- # -# Copyright (c) 2008-2014 Raoul Snyman # -# Portions copyright (c) 2008-2014 Tim Bentley, Gerald Britton, Jonathan # -# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub, # -# Meinert Jordan, Armin Köhler, Erik Lundin, Edwin Lunando, Brian T. Meyer. # -# Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias Põldaru, # -# Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # -# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Dave Warnock, # -# Frode Woldsund, Martin Zibricky, Patrick Zimmermann # -# --------------------------------------------------------------------------- # -# This program is free software; you can redistribute it and/or modify it # -# under the terms of the GNU General Public License as published by the Free # -# Software Foundation; version 2 of the License. # -# # -# This program is distributed in the hope that it will be useful, but WITHOUT # -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # -# more details. # -# # -# You should have received a copy of the GNU General Public License along # -# with this program; if not, write to the Free Software Foundation, Inc., 59 # -# Temple Place, Suite 330, Boston, MA 02111-1307 USA # -############################################################################### -""" -Package to test the openlp.core.ui.slidecontroller package. -""" -import os - -from unittest import TestCase - -from openlp.core.common import Registry -from openlp.core.ui import ThemeManager - -from tests.utils.constants import TEST_RESOURCES_PATH -from tests.interfaces import MagicMock, patch - - -class TestThemeManager(TestCase): - - def setUp(self): - """ - Set up the tests - """ - Registry.create() - - def initial_theme_manager_test(self): - """ - Test the instantiation of theme manager. - """ - # GIVEN: A new service manager instance. - ThemeManager(None) - - # WHEN: the default theme manager is built. - # THEN: The the controller should be registered in the registry. - self.assertIsNotNone(Registry().get('theme_manager'), 'The base theme manager should be registered') - - def write_theme_same_image_test(self): - """ - Test that we don't try to overwrite a theme background image with itself - """ - # GIVEN: A new theme manager instance, with mocked builtins.open, shutil.copyfile, - # theme, check_directory_exists and thememanager-attributes. - with patch('builtins.open') as mocked_open, \ - patch('openlp.core.ui.thememanager.shutil.copyfile') as mocked_copyfile, \ - patch('openlp.core.ui.thememanager.check_directory_exists') as mocked_check_directory_exists: - mocked_open.return_value = MagicMock() - theme_manager = ThemeManager(None) - theme_manager.old_background_image = None - theme_manager.generate_and_save_image = MagicMock() - theme_manager.path = '' - mocked_theme = MagicMock() - mocked_theme.theme_name = 'themename' - mocked_theme.extract_formatted_xml = MagicMock() - mocked_theme.extract_formatted_xml.return_value = 'fake_theme_xml'.encode() - - # WHEN: Calling _write_theme with path to the same image, but the path written slightly different - file_name1 = os.path.join(TEST_RESOURCES_PATH, 'church.jpg') - # Do replacement from end of string to avoid problems with path start - file_name2 = file_name1[::-1].replace(os.sep, os.sep + os.sep, 2)[::-1] - theme_manager._write_theme(mocked_theme, file_name1, file_name2) - - # THEN: The mocked_copyfile should not have been called - self.assertFalse(mocked_copyfile.called, 'shutil.copyfile should not be called') - - def write_theme_diff_images_test(self): - """ - Test that we do overwrite a theme background image when a new is submitted - """ - # GIVEN: A new theme manager instance, with mocked builtins.open, shutil.copyfile, - # theme, check_directory_exists and thememanager-attributes. - with patch('builtins.open') as mocked_open, \ - patch('openlp.core.ui.thememanager.shutil.copyfile') as mocked_copyfile, \ - patch('openlp.core.ui.thememanager.check_directory_exists') as mocked_check_directory_exists: - mocked_open.return_value = MagicMock() - theme_manager = ThemeManager(None) - theme_manager.old_background_image = None - theme_manager.generate_and_save_image = MagicMock() - theme_manager.path = '' - mocked_theme = MagicMock() - mocked_theme.theme_name = 'themename' - mocked_theme.extract_formatted_xml = MagicMock() - mocked_theme.extract_formatted_xml.return_value = 'fake_theme_xml'.encode() - - # WHEN: Calling _write_theme with path to different images - file_name1 = os.path.join(TEST_RESOURCES_PATH, 'church.jpg') - file_name2 = os.path.join(TEST_RESOURCES_PATH, 'church2.jpg') - theme_manager._write_theme(mocked_theme, file_name1, file_name2) - - # THEN: The mocked_copyfile should not have been called - self.assertTrue(mocked_copyfile.called, 'shutil.copyfile should be called') From 3a1fda85d5ba63a0a5489c3344e3a78277e9271e Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Thu, 21 Aug 2014 14:51:34 +0200 Subject: [PATCH 35/39] Fixed windows test failure by removing special char from filenames --- .../functional/openlp_plugins/songs/test_powerpraiseimport.py | 4 ++-- ...her, mein Gott zu Dir.json => Naher, mein Gott zu Dir.json} | 0 ...äher, mein Gott zu Dir.ppl => Naher, mein Gott zu Dir.ppl} | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename tests/resources/powerpraisesongs/{Näher, mein Gott zu Dir.json => Naher, mein Gott zu Dir.json} (100%) rename tests/resources/powerpraisesongs/{Näher, mein Gott zu Dir.ppl => Naher, mein Gott zu Dir.ppl} (100%) diff --git a/tests/functional/openlp_plugins/songs/test_powerpraiseimport.py b/tests/functional/openlp_plugins/songs/test_powerpraiseimport.py index dbe834e1c..e6a2a5194 100644 --- a/tests/functional/openlp_plugins/songs/test_powerpraiseimport.py +++ b/tests/functional/openlp_plugins/songs/test_powerpraiseimport.py @@ -50,7 +50,7 @@ class TestPowerPraiseFileImport(SongImportTestHelper): """ Test that loading a PowerPraise file works correctly """ - self.file_import([os.path.join(TEST_PATH, 'Näher, mein Gott zu Dir.ppl')], - self.load_external_result_data(os.path.join(TEST_PATH, 'Näher, mein Gott zu Dir.json'))) + self.file_import([os.path.join(TEST_PATH, 'Naher, mein Gott zu Dir.ppl')], + self.load_external_result_data(os.path.join(TEST_PATH, 'Naher, mein Gott zu Dir.json'))) self.file_import([os.path.join(TEST_PATH, 'You are so faithful.ppl')], self.load_external_result_data(os.path.join(TEST_PATH, 'You are so faithful.json'))) diff --git a/tests/resources/powerpraisesongs/Näher, mein Gott zu Dir.json b/tests/resources/powerpraisesongs/Naher, mein Gott zu Dir.json similarity index 100% rename from tests/resources/powerpraisesongs/Näher, mein Gott zu Dir.json rename to tests/resources/powerpraisesongs/Naher, mein Gott zu Dir.json diff --git a/tests/resources/powerpraisesongs/Näher, mein Gott zu Dir.ppl b/tests/resources/powerpraisesongs/Naher, mein Gott zu Dir.ppl similarity index 100% rename from tests/resources/powerpraisesongs/Näher, mein Gott zu Dir.ppl rename to tests/resources/powerpraisesongs/Naher, mein Gott zu Dir.ppl From fd4dc4caf7eeec3206f7ab58ac00d19c9592f100 Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Thu, 21 Aug 2014 15:07:02 +0200 Subject: [PATCH 36/39] Fixed another windows test by properly constructing paths. --- tests/functional/openlp_core_ui/test_thememanager.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/functional/openlp_core_ui/test_thememanager.py b/tests/functional/openlp_core_ui/test_thememanager.py index 3fd15baac..0f3fa8ac4 100644 --- a/tests/functional/openlp_core_ui/test_thememanager.py +++ b/tests/functional/openlp_core_ui/test_thememanager.py @@ -62,12 +62,12 @@ class TestThemeManager(TestCase): zipfile.ZipFile.write = MagicMock() # WHEN: The theme is exported - theme_manager._export_theme('/some/path', 'Default') + theme_manager._export_theme(os.path.join('some', 'path'), 'Default') # THEN: The zipfile should be created at the given path - zipfile.ZipFile.__init__.assert_called_with('/some/path/Default.otz', 'w') + zipfile.ZipFile.__init__.assert_called_with(os.path.join('some', 'path', 'Default.otz'), 'w') zipfile.ZipFile.write.assert_called_with(os.path.join(TEST_RESOURCES_PATH, 'themes', 'Default', 'Default.xml'), - 'Default/Default.xml') + os.path.join('Default', 'Default.xml')) def initial_theme_manager_test(self): """ From 516fd30bc7fe6e7205a22d737d932d8d66e59593 Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Sat, 23 Aug 2014 21:42:10 +0100 Subject: [PATCH 37/39] fix conversion bug --- openlp/core/ui/servicemanager.py | 2 +- .../openlp_core_ui/test_servicemanager.py | 243 +++++++++++++++++- 2 files changed, 243 insertions(+), 2 deletions(-) diff --git a/openlp/core/ui/servicemanager.py b/openlp/core/ui/servicemanager.py index 592b01524..369137694 100644 --- a/openlp/core/ui/servicemanager.py +++ b/openlp/core/ui/servicemanager.py @@ -993,7 +993,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage service_item.auto_play_slides_once = False self.set_modified() - def on_auto_start(self): + def on_auto_start(self, field=None): """ Toggles to Auto Start Setting. """ diff --git a/tests/functional/openlp_core_ui/test_servicemanager.py b/tests/functional/openlp_core_ui/test_servicemanager.py index 2c76ed965..bb9dff91e 100644 --- a/tests/functional/openlp_core_ui/test_servicemanager.py +++ b/tests/functional/openlp_core_ui/test_servicemanager.py @@ -31,7 +31,8 @@ Package to test the openlp.core.ui.slidecontroller package. """ from unittest import TestCase -from openlp.core.common import Registry +from openlp.core.common import Registry, ThemeLevel +from openlp.core.lib import ServiceItem, ServiceItemType, ItemCapabilities from openlp.core.ui import ServiceManager from tests.interfaces import MagicMock, patch @@ -89,3 +90,243 @@ class TestServiceManager(TestCase): self.assertEqual('txt' in service_manager.suffixes, True, 'The suffix txt should be in the list') self.assertEqual('ppt' in service_manager.suffixes, True, 'The suffix ppt should be in the list') self.assertEqual('pptx' in service_manager.suffixes, True, 'The suffix pptx should be in the list') + + def build_context_menu_test(self): + """ + Test the creation of a context menu from a null service item. + """ + # GIVEN: A new service manager instance and a default service item. + service_manager = ServiceManager(None) + item = MagicMock() + item.parent.return_value = False + item.data.return_value = 0 + service_manager.service_manager_list = MagicMock() + service_manager.service_manager_list.itemAt.return_value = item + service_item = ServiceItem(None) + service_manager.service_items.insert(1, {'service_item': service_item}) + service_manager.edit_action = MagicMock() + service_manager.rename_action = MagicMock() + service_manager.create_custom_action = MagicMock() + service_manager.maintain_action = MagicMock() + service_manager.notes_action = MagicMock() + service_manager.time_action = MagicMock() + service_manager.auto_start_action = MagicMock() + service_manager.auto_play_slides_menu = MagicMock() + service_manager.auto_play_slides_once = MagicMock() + service_manager.auto_play_slides_loop = MagicMock() + service_manager.timed_slide_interval = MagicMock() + service_manager.theme_menu = MagicMock() + service_manager.menu = MagicMock() + # WHEN I define a context menu + service_manager.context_menu(1) + # THEN the following calls should have occurred. + self.assertEquals(service_manager.edit_action.setVisible.call_count, 1, 'Should have been called once') + self.assertEquals(service_manager.rename_action.setVisible.call_count, 1, 'Should have been called once') + self.assertEquals(service_manager.create_custom_action.setVisible.call_count, 1, 'Should have been called once') + self.assertEquals(service_manager.maintain_action.setVisible.call_count, 1, 'Should have been called once') + self.assertEquals(service_manager.notes_action.setVisible.call_count, 1, 'Should have been called once') + self.assertEquals(service_manager.time_action.setVisible.call_count, 1, 'Should have been called once') + self.assertEquals(service_manager.auto_start_action.setVisible.call_count, 1, 'Should have been called once') + self.assertEquals(service_manager.auto_play_slides_menu.menuAction().setVisible.call_count, 1, + 'Should have been called once') + self.assertEquals(service_manager.auto_play_slides_once.setChecked.call_count, 0, 'Should not be called') + self.assertEquals(service_manager.auto_play_slides_loop.setChecked.call_count, 0, 'Should not be called') + self.assertEquals(service_manager.timed_slide_interval.setChecked.call_count, 0, 'Should not be called') + self.assertEquals(service_manager.theme_menu.menuAction().setVisible.call_count, 1, + 'Should have been called once') + + def build_song_context_menu_test(self): + """ + Test the creation of a context menu from service item of type text from Songs. + """ + # GIVEN: A new service manager instance and a default service item. + mocked_renderer = MagicMock() + mocked_renderer.theme_level = ThemeLevel.Song + Registry().register('plugin_manager', MagicMock()) + Registry().register('renderer', mocked_renderer) + service_manager = ServiceManager(None) + item = MagicMock() + item.parent.return_value = False + item.data.return_value = 0 + service_manager.service_manager_list = MagicMock() + service_manager.service_manager_list.itemAt.return_value = item + service_item = ServiceItem(None) + service_item.add_capability(ItemCapabilities.CanEdit) + service_item.add_capability(ItemCapabilities.CanPreview) + service_item.add_capability(ItemCapabilities.CanLoop) + service_item.add_capability(ItemCapabilities.OnLoadUpdate) + service_item.add_capability(ItemCapabilities.AddIfNewItem) + service_item.add_capability(ItemCapabilities.CanSoftBreak) + service_item.service_item_type = ServiceItemType.Text + service_item.edit_id = 1 + service_item._display_frames.append(MagicMock()) + service_manager.service_items.insert(1, {'service_item': service_item}) + service_manager.edit_action = MagicMock() + service_manager.rename_action = MagicMock() + service_manager.create_custom_action = MagicMock() + service_manager.maintain_action = MagicMock() + service_manager.notes_action = MagicMock() + service_manager.time_action = MagicMock() + service_manager.auto_start_action = MagicMock() + service_manager.auto_play_slides_menu = MagicMock() + service_manager.auto_play_slides_once = MagicMock() + service_manager.auto_play_slides_loop = MagicMock() + service_manager.timed_slide_interval = MagicMock() + service_manager.theme_menu = MagicMock() + service_manager.menu = MagicMock() + # WHEN I define a context menu + service_manager.context_menu(1) + # THEN the following calls should have occurred. + self.assertEquals(service_manager.edit_action.setVisible.call_count, 2, 'Should have be called twice') + self.assertEquals(service_manager.rename_action.setVisible.call_count, 1, 'Should have be called once') + self.assertEquals(service_manager.create_custom_action.setVisible.call_count, 1, 'Should have be called once') + self.assertEquals(service_manager.maintain_action.setVisible.call_count, 1, 'Should have be called once') + self.assertEquals(service_manager.notes_action.setVisible.call_count, 1, 'Should have be called once') + self.assertEquals(service_manager.time_action.setVisible.call_count, 1, 'Should have be called once') + self.assertEquals(service_manager.auto_start_action.setVisible.call_count, 1, 'Should have be called once') + self.assertEquals(service_manager.auto_play_slides_menu.menuAction().setVisible.call_count, 1, + 'Should have be called once') + self.assertEquals(service_manager.auto_play_slides_once.setChecked.call_count, 0, 'Should not be called') + self.assertEquals(service_manager.auto_play_slides_loop.setChecked.call_count, 0, 'Should not be called') + self.assertEquals(service_manager.timed_slide_interval.setChecked.call_count, 0, 'Should not be called') + self.assertEquals(service_manager.theme_menu.menuAction().setVisible.call_count, 2, + 'Should have be called twice') + # THEN we add a 2nd display frame + service_item._display_frames.append(MagicMock()) + service_manager.context_menu(1) + # THEN the following additional calls should have occurred. + self.assertEquals(service_manager.auto_play_slides_menu.menuAction().setVisible.call_count, 2, + 'Should have be called twice') + self.assertEquals(service_manager.auto_play_slides_once.setChecked.call_count, 1, 'Should have be called once') + self.assertEquals(service_manager.auto_play_slides_loop.setChecked.call_count, 1, 'Should have be called once') + self.assertEquals(service_manager.timed_slide_interval.setChecked.call_count, 1, 'Should have be called once') + + def build_bible_context_menu_test(self): + """ + Test the creation of a context menu from service item of type text from Bibles. + """ + # GIVEN: A new service manager instance and a default service item. + mocked_renderer = MagicMock() + mocked_renderer.theme_level = ThemeLevel.Song + Registry().register('plugin_manager', MagicMock()) + Registry().register('renderer', mocked_renderer) + service_manager = ServiceManager(None) + item = MagicMock() + item.parent.return_value = False + item.data.return_value = 0 + service_manager.service_manager_list = MagicMock() + service_manager.service_manager_list.itemAt.return_value = item + service_item = ServiceItem(None) + service_item.add_capability(ItemCapabilities.NoLineBreaks) + service_item.add_capability(ItemCapabilities.CanPreview) + service_item.add_capability(ItemCapabilities.CanLoop) + service_item.add_capability(ItemCapabilities.CanWordSplit) + service_item.add_capability(ItemCapabilities.CanEditTitle) + service_item.service_item_type = ServiceItemType.Text + service_item.edit_id = 1 + service_item._display_frames.append(MagicMock()) + service_manager.service_items.insert(1, {'service_item': service_item}) + service_manager.edit_action = MagicMock() + service_manager.rename_action = MagicMock() + service_manager.create_custom_action = MagicMock() + service_manager.maintain_action = MagicMock() + service_manager.notes_action = MagicMock() + service_manager.time_action = MagicMock() + service_manager.auto_start_action = MagicMock() + service_manager.auto_play_slides_menu = MagicMock() + service_manager.auto_play_slides_once = MagicMock() + service_manager.auto_play_slides_loop = MagicMock() + service_manager.timed_slide_interval = MagicMock() + service_manager.theme_menu = MagicMock() + service_manager.menu = MagicMock() + # WHEN I define a context menu + service_manager.context_menu(1) + # THEN the following calls should have occurred. + self.assertEquals(service_manager.edit_action.setVisible.call_count, 1, 'Should have be called once') + self.assertEquals(service_manager.rename_action.setVisible.call_count, 2, 'Should have be called twice') + self.assertEquals(service_manager.create_custom_action.setVisible.call_count, 1, 'Should have be called once') + self.assertEquals(service_manager.maintain_action.setVisible.call_count, 1, 'Should have be called once') + self.assertEquals(service_manager.notes_action.setVisible.call_count, 1, 'Should have be called once') + self.assertEquals(service_manager.time_action.setVisible.call_count, 1, 'Should have be called once') + self.assertEquals(service_manager.auto_start_action.setVisible.call_count, 1, 'Should have be called once') + self.assertEquals(service_manager.auto_play_slides_menu.menuAction().setVisible.call_count, 1, + 'Should have be called once') + self.assertEquals(service_manager.auto_play_slides_once.setChecked.call_count, 0, 'Should not be called') + self.assertEquals(service_manager.auto_play_slides_loop.setChecked.call_count, 0, 'Should not be called') + self.assertEquals(service_manager.timed_slide_interval.setChecked.call_count, 0, 'Should not be called') + self.assertEquals(service_manager.theme_menu.menuAction().setVisible.call_count, 2, + 'Should have be called twice') + # THEN we add a 2nd display frame + service_item._display_frames.append(MagicMock()) + service_manager.context_menu(1) + # THEN the following additional calls should have occurred. + self.assertEquals(service_manager.auto_play_slides_menu.menuAction().setVisible.call_count, 2, + 'Should have be called twice') + self.assertEquals(service_manager.auto_play_slides_once.setChecked.call_count, 1, 'Should have be called once') + self.assertEquals(service_manager.auto_play_slides_loop.setChecked.call_count, 1, 'Should have be called once') + self.assertEquals(service_manager.timed_slide_interval.setChecked.call_count, 1, 'Should have be called once') + + def build_custom_context_menu_test(self): + """ + Test the creation of a context menu from service item of type text from Custom. + """ + # GIVEN: A new service manager instance and a default service item. + mocked_renderer = MagicMock() + mocked_renderer.theme_level = ThemeLevel.Song + Registry().register('plugin_manager', MagicMock()) + Registry().register('renderer', mocked_renderer) + service_manager = ServiceManager(None) + item = MagicMock() + item.parent.return_value = False + item.data.return_value = 0 + service_manager.service_manager_list = MagicMock() + service_manager.service_manager_list.itemAt.return_value = item + service_item = ServiceItem(None) + service_item.add_capability(ItemCapabilities.CanEdit) + service_item.add_capability(ItemCapabilities.CanPreview) + service_item.add_capability(ItemCapabilities.CanLoop) + service_item.add_capability(ItemCapabilities.CanSoftBreak) + service_item.add_capability(ItemCapabilities.OnLoadUpdate) + service_item.service_item_type = ServiceItemType.Text + service_item.edit_id = 1 + service_item._display_frames.append(MagicMock()) + service_manager.service_items.insert(1, {'service_item': service_item}) + service_manager.edit_action = MagicMock() + service_manager.rename_action = MagicMock() + service_manager.create_custom_action = MagicMock() + service_manager.maintain_action = MagicMock() + service_manager.notes_action = MagicMock() + service_manager.time_action = MagicMock() + service_manager.auto_start_action = MagicMock() + service_manager.auto_play_slides_menu = MagicMock() + service_manager.auto_play_slides_once = MagicMock() + service_manager.auto_play_slides_loop = MagicMock() + service_manager.timed_slide_interval = MagicMock() + service_manager.theme_menu = MagicMock() + service_manager.menu = MagicMock() + # WHEN I define a context menu + service_manager.context_menu(1) + # THEN the following calls should have occurred. + self.assertEquals(service_manager.edit_action.setVisible.call_count, 2, 'Should have be called twice') + self.assertEquals(service_manager.rename_action.setVisible.call_count, 1, 'Should have be called once') + self.assertEquals(service_manager.create_custom_action.setVisible.call_count, 1, 'Should have be called once') + self.assertEquals(service_manager.maintain_action.setVisible.call_count, 1, 'Should have be called once') + self.assertEquals(service_manager.notes_action.setVisible.call_count, 1, 'Should have be called once') + self.assertEquals(service_manager.time_action.setVisible.call_count, 1, 'Should have be called once') + self.assertEquals(service_manager.auto_start_action.setVisible.call_count, 1, 'Should have be called once') + self.assertEquals(service_manager.auto_play_slides_menu.menuAction().setVisible.call_count, 1, + 'Should have be called once') + self.assertEquals(service_manager.auto_play_slides_once.setChecked.call_count, 0, 'Should not be called') + self.assertEquals(service_manager.auto_play_slides_loop.setChecked.call_count, 0, 'Should not be called') + self.assertEquals(service_manager.timed_slide_interval.setChecked.call_count, 0, 'Should not be called') + self.assertEquals(service_manager.theme_menu.menuAction().setVisible.call_count, 2, + 'Should have be called twice') + # THEN we add a 2nd display frame + service_item._display_frames.append(MagicMock()) + service_manager.context_menu(1) + # THEN the following additional calls should have occurred. + self.assertEquals(service_manager.auto_play_slides_menu.menuAction().setVisible.call_count, 2, + 'Should have be called twice') + self.assertEquals(service_manager.auto_play_slides_once.setChecked.call_count, 1, 'Should have be called once') + self.assertEquals(service_manager.auto_play_slides_loop.setChecked.call_count, 1, 'Should have be called once') + self.assertEquals(service_manager.timed_slide_interval.setChecked.call_count, 1, 'Should have be called once') \ No newline at end of file From 09bb622af89af633b7d9b368c8e596d79db9d4c6 Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Sun, 24 Aug 2014 10:32:26 +0100 Subject: [PATCH 38/39] Final tests --- .../openlp_core_ui/test_servicemanager.py | 225 +++++++++++++++++- 1 file changed, 224 insertions(+), 1 deletion(-) diff --git a/tests/functional/openlp_core_ui/test_servicemanager.py b/tests/functional/openlp_core_ui/test_servicemanager.py index bb9dff91e..d8d2be50e 100644 --- a/tests/functional/openlp_core_ui/test_servicemanager.py +++ b/tests/functional/openlp_core_ui/test_servicemanager.py @@ -329,4 +329,227 @@ class TestServiceManager(TestCase): 'Should have be called twice') self.assertEquals(service_manager.auto_play_slides_once.setChecked.call_count, 1, 'Should have be called once') self.assertEquals(service_manager.auto_play_slides_loop.setChecked.call_count, 1, 'Should have be called once') - self.assertEquals(service_manager.timed_slide_interval.setChecked.call_count, 1, 'Should have be called once') \ No newline at end of file + self.assertEquals(service_manager.timed_slide_interval.setChecked.call_count, 1, 'Should have be called once') + + def build_image_context_menu_test(self): + """ + Test the creation of a context menu from service item of type Image from Image. + """ + # GIVEN: A new service manager instance and a default service item. + Registry().register('plugin_manager', MagicMock()) + Registry().register('renderer', MagicMock()) + service_manager = ServiceManager(None) + item = MagicMock() + item.parent.return_value = False + item.data.return_value = 0 + service_manager.service_manager_list = MagicMock() + service_manager.service_manager_list.itemAt.return_value = item + service_item = ServiceItem(None) + service_item.add_capability(ItemCapabilities.CanMaintain) + service_item.add_capability(ItemCapabilities.CanPreview) + service_item.add_capability(ItemCapabilities.CanLoop) + service_item.add_capability(ItemCapabilities.CanAppend) + service_item.add_capability(ItemCapabilities.CanEditTitle) + service_item.service_item_type = ServiceItemType.Image + service_item.edit_id = 1 + service_item._raw_frames.append(MagicMock()) + service_manager.service_items.insert(1, {'service_item': service_item}) + service_manager.edit_action = MagicMock() + service_manager.rename_action = MagicMock() + service_manager.create_custom_action = MagicMock() + service_manager.maintain_action = MagicMock() + service_manager.notes_action = MagicMock() + service_manager.time_action = MagicMock() + service_manager.auto_start_action = MagicMock() + service_manager.auto_play_slides_menu = MagicMock() + service_manager.auto_play_slides_once = MagicMock() + service_manager.auto_play_slides_loop = MagicMock() + service_manager.timed_slide_interval = MagicMock() + service_manager.theme_menu = MagicMock() + service_manager.menu = MagicMock() + # WHEN I define a context menu + service_manager.context_menu(1) + # THEN the following calls should have occurred. + self.assertEquals(service_manager.edit_action.setVisible.call_count, 1, 'Should have be called once') + self.assertEquals(service_manager.rename_action.setVisible.call_count, 2, 'Should have be called twice') + self.assertEquals(service_manager.create_custom_action.setVisible.call_count, 1, 'Should have be called once') + self.assertEquals(service_manager.maintain_action.setVisible.call_count, 2, 'Should have be called twice') + self.assertEquals(service_manager.notes_action.setVisible.call_count, 1, 'Should have be called once') + self.assertEquals(service_manager.time_action.setVisible.call_count, 1, 'Should have be called once') + self.assertEquals(service_manager.auto_start_action.setVisible.call_count, 1, 'Should have be called once') + self.assertEquals(service_manager.auto_play_slides_menu.menuAction().setVisible.call_count, 1, + 'Should have be called once') + self.assertEquals(service_manager.auto_play_slides_once.setChecked.call_count, 0, 'Should not be called') + self.assertEquals(service_manager.auto_play_slides_loop.setChecked.call_count, 0, 'Should not be called') + self.assertEquals(service_manager.timed_slide_interval.setChecked.call_count, 0, 'Should not be called') + self.assertEquals(service_manager.theme_menu.menuAction().setVisible.call_count, 1, + 'Should have be called once') + # THEN we add a 2nd display frame and regenerate the menu. + service_item._raw_frames.append(MagicMock()) + service_manager.context_menu(1) + # THEN the following additional calls should have occurred. + self.assertEquals(service_manager.auto_play_slides_menu.menuAction().setVisible.call_count, 2, + 'Should have be called twice') + self.assertEquals(service_manager.auto_play_slides_once.setChecked.call_count, 1, 'Should have be called once') + self.assertEquals(service_manager.auto_play_slides_loop.setChecked.call_count, 1, 'Should have be called once') + self.assertEquals(service_manager.timed_slide_interval.setChecked.call_count, 1, 'Should have be called once') + + def build_media_context_menu_test(self): + """ + Test the creation of a context menu from service item of type Command from Media. + """ + # GIVEN: A new service manager instance and a default service item. + Registry().register('plugin_manager', MagicMock()) + Registry().register('renderer', MagicMock()) + service_manager = ServiceManager(None) + item = MagicMock() + item.parent.return_value = False + item.data.return_value = 0 + service_manager.service_manager_list = MagicMock() + service_manager.service_manager_list.itemAt.return_value = item + service_item = ServiceItem(None) + service_item.add_capability(ItemCapabilities.CanAutoStartForLive) + service_item.add_capability(ItemCapabilities.CanEditTitle) + service_item.add_capability(ItemCapabilities.RequiresMedia) + service_item.service_item_type = ServiceItemType.Command + service_item.edit_id = 1 + service_item._raw_frames.append(MagicMock()) + service_manager.service_items.insert(1, {'service_item': service_item}) + service_manager.edit_action = MagicMock() + service_manager.rename_action = MagicMock() + service_manager.create_custom_action = MagicMock() + service_manager.maintain_action = MagicMock() + service_manager.notes_action = MagicMock() + service_manager.time_action = MagicMock() + service_manager.auto_start_action = MagicMock() + service_manager.auto_play_slides_menu = MagicMock() + service_manager.auto_play_slides_once = MagicMock() + service_manager.auto_play_slides_loop = MagicMock() + service_manager.timed_slide_interval = MagicMock() + service_manager.theme_menu = MagicMock() + service_manager.menu = MagicMock() + # WHEN I define a context menu + service_manager.context_menu(1) + # THEN the following calls should have occurred. + self.assertEquals(service_manager.edit_action.setVisible.call_count, 1, 'Should have be called once') + self.assertEquals(service_manager.rename_action.setVisible.call_count, 2, 'Should have be called twice') + self.assertEquals(service_manager.create_custom_action.setVisible.call_count, 1, 'Should have be called once') + self.assertEquals(service_manager.maintain_action.setVisible.call_count, 1, 'Should have be called once') + self.assertEquals(service_manager.notes_action.setVisible.call_count, 1, 'Should have be called once') + self.assertEquals(service_manager.time_action.setVisible.call_count, 1, 'Should have be called once') + self.assertEquals(service_manager.auto_start_action.setVisible.call_count, 2, 'Should have be called twice') + self.assertEquals(service_manager.auto_play_slides_menu.menuAction().setVisible.call_count, 1, + 'Should have be called once') + self.assertEquals(service_manager.auto_play_slides_once.setChecked.call_count, 0, 'Should not be called') + self.assertEquals(service_manager.auto_play_slides_loop.setChecked.call_count, 0, 'Should not be called') + self.assertEquals(service_manager.timed_slide_interval.setChecked.call_count, 0, 'Should not be called') + self.assertEquals(service_manager.theme_menu.menuAction().setVisible.call_count, 1, + 'Should have be called once') + # THEN I change the length of the media and regenerate the menu. + service_item.set_media_length(5) + service_manager.context_menu(1) + # THEN the following additional calls should have occurred. + self.assertEquals(service_manager.time_action.setVisible.call_count, 3, 'Should have be called three times') + + def build_presentation_pdf_context_menu_test(self): + """ + Test the creation of a context menu from service item of type Command with PDF from Presentation. + """ + # GIVEN: A new service manager instance and a default service item. + Registry().register('plugin_manager', MagicMock()) + Registry().register('renderer', MagicMock()) + service_manager = ServiceManager(None) + item = MagicMock() + item.parent.return_value = False + item.data.return_value = 0 + service_manager.service_manager_list = MagicMock() + service_manager.service_manager_list.itemAt.return_value = item + service_item = ServiceItem(None) + service_item.add_capability(ItemCapabilities.CanMaintain) + service_item.add_capability(ItemCapabilities.CanPreview) + service_item.add_capability(ItemCapabilities.CanLoop) + service_item.add_capability(ItemCapabilities.CanAppend) + service_item.service_item_type = ServiceItemType.Command + service_item.edit_id = 1 + service_item._raw_frames.append(MagicMock()) + service_manager.service_items.insert(1, {'service_item': service_item}) + service_manager.edit_action = MagicMock() + service_manager.rename_action = MagicMock() + service_manager.create_custom_action = MagicMock() + service_manager.maintain_action = MagicMock() + service_manager.notes_action = MagicMock() + service_manager.time_action = MagicMock() + service_manager.auto_start_action = MagicMock() + service_manager.auto_play_slides_menu = MagicMock() + service_manager.auto_play_slides_once = MagicMock() + service_manager.auto_play_slides_loop = MagicMock() + service_manager.timed_slide_interval = MagicMock() + service_manager.theme_menu = MagicMock() + service_manager.menu = MagicMock() + # WHEN I define a context menu + service_manager.context_menu(1) + # THEN the following calls should have occurred. + self.assertEquals(service_manager.edit_action.setVisible.call_count, 1, 'Should have be called once') + self.assertEquals(service_manager.rename_action.setVisible.call_count, 1, 'Should have be called once') + self.assertEquals(service_manager.create_custom_action.setVisible.call_count, 1, 'Should have be called once') + self.assertEquals(service_manager.maintain_action.setVisible.call_count, 2, 'Should have be called twice') + self.assertEquals(service_manager.notes_action.setVisible.call_count, 1, 'Should have be called once') + self.assertEquals(service_manager.time_action.setVisible.call_count, 1, 'Should have be called once') + self.assertEquals(service_manager.auto_start_action.setVisible.call_count, 1, 'Should have be called once') + self.assertEquals(service_manager.auto_play_slides_menu.menuAction().setVisible.call_count, 1, + 'Should have be called once') + self.assertEquals(service_manager.auto_play_slides_once.setChecked.call_count, 0, 'Should not be called') + self.assertEquals(service_manager.auto_play_slides_loop.setChecked.call_count, 0, 'Should not be called') + self.assertEquals(service_manager.timed_slide_interval.setChecked.call_count, 0, 'Should not be called') + self.assertEquals(service_manager.theme_menu.menuAction().setVisible.call_count, 1, + 'Should have be called once') + + def build_presentation_non_pdf_context_menu_test(self): + """ + Test the creation of a context menu from service item of type Command with Impress from Presentation. + """ + # GIVEN: A new service manager instance and a default service item. + Registry().register('plugin_manager', MagicMock()) + Registry().register('renderer', MagicMock()) + service_manager = ServiceManager(None) + item = MagicMock() + item.parent.return_value = False + item.data.return_value = 0 + service_manager.service_manager_list = MagicMock() + service_manager.service_manager_list.itemAt.return_value = item + service_item = ServiceItem(None) + service_item.add_capability(ItemCapabilities.ProvidesOwnDisplay) + service_item.service_item_type = ServiceItemType.Command + service_item.edit_id = 1 + service_item._raw_frames.append(MagicMock()) + service_manager.service_items.insert(1, {'service_item': service_item}) + service_manager.edit_action = MagicMock() + service_manager.rename_action = MagicMock() + service_manager.create_custom_action = MagicMock() + service_manager.maintain_action = MagicMock() + service_manager.notes_action = MagicMock() + service_manager.time_action = MagicMock() + service_manager.auto_start_action = MagicMock() + service_manager.auto_play_slides_menu = MagicMock() + service_manager.auto_play_slides_once = MagicMock() + service_manager.auto_play_slides_loop = MagicMock() + service_manager.timed_slide_interval = MagicMock() + service_manager.theme_menu = MagicMock() + service_manager.menu = MagicMock() + # WHEN I define a context menu + service_manager.context_menu(1) + # THEN the following calls should have occurred. + self.assertEquals(service_manager.edit_action.setVisible.call_count, 1, 'Should have be called once') + self.assertEquals(service_manager.rename_action.setVisible.call_count, 1, 'Should have be called once') + self.assertEquals(service_manager.create_custom_action.setVisible.call_count, 1, 'Should have be called once') + self.assertEquals(service_manager.maintain_action.setVisible.call_count, 1, 'Should have be called once') + self.assertEquals(service_manager.notes_action.setVisible.call_count, 1, 'Should have be called once') + self.assertEquals(service_manager.time_action.setVisible.call_count, 1, 'Should have be called once') + self.assertEquals(service_manager.auto_start_action.setVisible.call_count, 1, 'Should have be called once') + self.assertEquals(service_manager.auto_play_slides_menu.menuAction().setVisible.call_count, 1, + 'Should have be called once') + self.assertEquals(service_manager.auto_play_slides_once.setChecked.call_count, 0, 'Should not be called') + self.assertEquals(service_manager.auto_play_slides_loop.setChecked.call_count, 0, 'Should not be called') + self.assertEquals(service_manager.timed_slide_interval.setChecked.call_count, 0, 'Should not be called') + self.assertEquals(service_manager.theme_menu.menuAction().setVisible.call_count, 1, + 'Should have be called once') From 3026e7bd47fd40271c1171f96ae2f5b8c7908609 Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Sun, 24 Aug 2014 11:24:23 +0100 Subject: [PATCH 39/39] remove script change --- scripts/jenkins_script.py | 23 +++++------------------ 1 file changed, 5 insertions(+), 18 deletions(-) diff --git a/scripts/jenkins_script.py b/scripts/jenkins_script.py index 430e842ce..7abdbccd0 100755 --- a/scripts/jenkins_script.py +++ b/scripts/jenkins_script.py @@ -89,7 +89,7 @@ class JenkinsTrigger(object): :param token: The token we need to trigger the build. If you do not have this token, ask in IRC. """ self.token = token - self.base_name, self.repo_name = get_repo_name('b') + self.repo_name = get_repo_name() self.jenkins_instance = Jenkins(JENKINS_URL) def trigger_build(self): @@ -113,8 +113,7 @@ class JenkinsTrigger(object): bzr = Popen(('bzr', 'revno'), stdout=PIPE, stderr=PIPE) raw_output, error = bzr.communicate() revno = raw_output.decode().strip() - print('Remote repository: %s ' % self.repo_name) - print(' Local repository: %s (revision %s)' % (self.repo_name, revno)) + print('%s (revision %s)' % (get_repo_name(), revno)) for job in OpenLPJobs.Jobs: if not self.__print_build_info(job): @@ -154,7 +153,7 @@ class JenkinsTrigger(object): return is_success -def get_repo_name(branch_type='l'): +def get_repo_name(): """ This returns the name of branch of the working directory. For example it returns *lp:~googol/openlp/render*. """ @@ -170,7 +169,6 @@ def get_repo_name(branch_type='l'): output_list = list(map(str.strip, raw_output.split('\n'))) # Determine the branch's name repo_name = '' - base_name = '' for line in output_list: # Check if it is remote branch. if 'push branch' in line: @@ -183,15 +181,7 @@ def get_repo_name(branch_type='l'): if match: repo_name = 'lp:%s' % match.group(2) break - elif 'repository branch' in line: - base_name = line.split(':')[1] - break - if branch_type == 'b': - return base_name.strip('/'), repo_name.strip('/') - elif branch_type == 'r': - return base_name.strip('/') - else: - return repo_name.strip('/') + return repo_name.strip('/') def main(): @@ -205,12 +195,9 @@ def main(): options, args = parser.parse_args(sys.argv) if len(args) == 2: - if not get_repo_name('l'): + if not get_repo_name(): print('Not a branch. Have you pushed it to launchpad? Did you cd to the branch?') return - if not get_repo_name('r'): - print('No remote branch. Have you pushed it to launchpad? Did you cd to the branch?') - return token = args[-1] if token in OLD_TOKENS: print('Your token is not valid anymore. Get the most recent one.')