From 71324fc932d3ae69b86276e23d15b35018b0b48f Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Thu, 25 Sep 2014 11:07:31 +0200 Subject: [PATCH 01/11] Forward ported fix for bug1265368 Fixes: https://launchpad.net/bugs/1265368 --- openlp/core/ui/slidecontroller.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openlp/core/ui/slidecontroller.py b/openlp/core/ui/slidecontroller.py index 44c28deb6..31c826a14 100644 --- a/openlp/core/ui/slidecontroller.py +++ b/openlp/core/ui/slidecontroller.py @@ -374,7 +374,8 @@ class SlideController(DisplayController, RegistryProperties): triggers=self._slide_shortcut_activated) for s in shortcuts]) self.shortcut_timer.timeout.connect(self._slide_shortcut_activated) # Signals - self.preview_widget.itemSelectionChanged.connect(self.on_slide_selected) + self.preview_widget.clicked.connect(self.on_slide_selected) + self.preview_widget.verticalHeader().sectionClicked.connect(self.on_slide_selected) if self.is_live: # Need to use event as called across threads and UI is updated QtCore.QObject.connect(self, QtCore.SIGNAL('slidecontroller_toggle_display'), self.toggle_display) From 977fd1d18761537bec2e5b9a58519d972bccba95 Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Thu, 25 Sep 2014 16:59:56 +0200 Subject: [PATCH 02/11] Fix tests so they can run individually. --- tests/functional/openlp_plugins/remotes/test_router.py | 1 + tests/functional/openlp_plugins/songs/test_ewimport.py | 6 ++++++ .../functional/openlp_plugins/songs/test_opensongimport.py | 7 +++++++ .../openlp_plugins/songs/test_powerpraiseimport.py | 1 + .../openlp_plugins/songs/test_songbeamerimport.py | 7 +++++++ .../functional/openlp_plugins/songs/test_zionworximport.py | 7 +++++++ 6 files changed, 29 insertions(+) diff --git a/tests/functional/openlp_plugins/remotes/test_router.py b/tests/functional/openlp_plugins/remotes/test_router.py index 037169b88..e7b209349 100644 --- a/tests/functional/openlp_plugins/remotes/test_router.py +++ b/tests/functional/openlp_plugins/remotes/test_router.py @@ -130,6 +130,7 @@ class TestRouter(TestCase, TestMixin): Test the main poll logic """ # GIVEN: a defined router with two slides + Registry.create() Registry().register('live_controller', MagicMock) router = HttpRouter() router.send_response = MagicMock() diff --git a/tests/functional/openlp_plugins/songs/test_ewimport.py b/tests/functional/openlp_plugins/songs/test_ewimport.py index f441084e7..3cb2c3bbd 100644 --- a/tests/functional/openlp_plugins/songs/test_ewimport.py +++ b/tests/functional/openlp_plugins/songs/test_ewimport.py @@ -35,6 +35,7 @@ from unittest import TestCase from tests.functional import MagicMock, patch +from openlp.core.common import Registry from openlp.plugins.songs.lib.importers.easyworship import EasyWorshipSongImport, FieldDescEntry, FieldType TEST_PATH = os.path.abspath( @@ -153,6 +154,11 @@ class TestEasyWorshipSongImport(TestCase): """ Test the functions in the :mod:`ewimport` module. """ + def setUp(self): + """ + Create the registry + """ + Registry.create() def create_field_desc_entry_test(self): """ diff --git a/tests/functional/openlp_plugins/songs/test_opensongimport.py b/tests/functional/openlp_plugins/songs/test_opensongimport.py index 07b275f98..09d9eb61f 100644 --- a/tests/functional/openlp_plugins/songs/test_opensongimport.py +++ b/tests/functional/openlp_plugins/songs/test_opensongimport.py @@ -35,6 +35,7 @@ from unittest import TestCase from tests.helpers.songfileimport import SongImportTestHelper from openlp.plugins.songs.lib.importers.opensong import OpenSongImport +from openlp.core.common import Registry from tests.functional import patch, MagicMock TEST_PATH = os.path.abspath( @@ -64,6 +65,12 @@ class TestOpenSongImport(TestCase): """ Test the functions in the :mod:`opensongimport` module. """ + def setUp(self): + """ + Create the registry + """ + Registry.create() + def create_importer_test(self): """ Test creating an instance of the OpenSong file importer diff --git a/tests/functional/openlp_plugins/songs/test_powerpraiseimport.py b/tests/functional/openlp_plugins/songs/test_powerpraiseimport.py index e6a2a5194..eac51f6da 100644 --- a/tests/functional/openlp_plugins/songs/test_powerpraiseimport.py +++ b/tests/functional/openlp_plugins/songs/test_powerpraiseimport.py @@ -34,6 +34,7 @@ ProPresenter song files into the current installation database. import os from tests.helpers.songfileimport import SongImportTestHelper +from openlp.core.common import Registry TEST_PATH = os.path.abspath( os.path.join(os.path.dirname(__file__), '..', '..', '..', 'resources', 'powerpraisesongs')) diff --git a/tests/functional/openlp_plugins/songs/test_songbeamerimport.py b/tests/functional/openlp_plugins/songs/test_songbeamerimport.py index 3d872ae65..493d8fd2a 100644 --- a/tests/functional/openlp_plugins/songs/test_songbeamerimport.py +++ b/tests/functional/openlp_plugins/songs/test_songbeamerimport.py @@ -36,6 +36,7 @@ from unittest import TestCase from tests.functional import MagicMock, patch from openlp.plugins.songs.lib.importers.songbeamer import SongBeamerImport from openlp.plugins.songs.lib import VerseType +from openlp.core.common import Registry TEST_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..', 'resources', 'songbeamersongs')) @@ -59,6 +60,12 @@ class TestSongBeamerImport(TestCase): """ Test the functions in the :mod:`songbeamerimport` module. """ + def setUp(self): + """ + Create the registry + """ + Registry.create() + def create_importer_test(self): """ Test creating an instance of the SongBeamer file importer diff --git a/tests/functional/openlp_plugins/songs/test_zionworximport.py b/tests/functional/openlp_plugins/songs/test_zionworximport.py index faedc7005..2d2bae4d0 100644 --- a/tests/functional/openlp_plugins/songs/test_zionworximport.py +++ b/tests/functional/openlp_plugins/songs/test_zionworximport.py @@ -35,12 +35,19 @@ from unittest import TestCase from tests.functional import MagicMock, patch from openlp.plugins.songs.lib.importers.zionworx import ZionWorxImport from openlp.plugins.songs.lib.importers.songimport import SongImport +from openlp.core.common import Registry class TestZionWorxImport(TestCase): """ Test the functions in the :mod:`zionworximport` module. """ + def setUp(self): + """ + Create the registry + """ + Registry.create() + def create_importer_test(self): """ Test creating an instance of the ZionWorx file importer From 3e66b4aa98cb9bb45977d37fe4c54f3c53d4f665 Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Thu, 25 Sep 2014 17:01:11 +0200 Subject: [PATCH 03/11] Fix for importing custom tags from openlyricsxml + test in progress --- openlp/plugins/songs/lib/openlyricsxml.py | 12 +++-- .../songs/test_openlyricsimport.py | 47 ++++++++++++++++++- 2 files changed, 53 insertions(+), 6 deletions(-) diff --git a/openlp/plugins/songs/lib/openlyricsxml.py b/openlp/plugins/songs/lib/openlyricsxml.py index 9458d6180..01c6cf50e 100644 --- a/openlp/plugins/songs/lib/openlyricsxml.py +++ b/openlp/plugins/songs/lib/openlyricsxml.py @@ -239,6 +239,7 @@ class OpenLyrics(object): def __init__(self, manager): self.manager = manager + FormattingTags.load_tags() def song_to_xml(self, song): """ @@ -582,18 +583,19 @@ class OpenLyrics(object): # Some tags have only start html e.g. {br} 'end html': tag.close.text if hasattr(tag, 'close') else '', 'protected': False, + # Add 'temporary' key in case the formatting tag should not be saved otherwise it is supposed that + # formatting tag is permanent. + 'temporary': temporary } - # Add 'temporary' key in case the formatting tag should not be saved otherwise it is supposed that - # formatting tag is permanent. - if temporary: - openlp_tag['temporary'] = temporary found_tags.append(openlp_tag) existing_tag_ids = [tag['start tag'] for tag in FormattingTags.get_html_tags()] new_tags = [tag for tag in found_tags if tag['start tag'] not in existing_tag_ids] # Do not save an empty list. if new_tags: FormattingTags.add_html_tags(new_tags) - FormattingTags.save_html_tags() + if not temporary: + custom_tags = [tag for tag in FormattingTags.get_html_tags() if not tag['protected'] and not tag['temporary']] + FormattingTags.save_html_tags(custom_tags) def _process_lines_mixed_content(self, element, newlines=True): """ diff --git a/tests/functional/openlp_plugins/songs/test_openlyricsimport.py b/tests/functional/openlp_plugins/songs/test_openlyricsimport.py index 25db3e9e4..7e1fba1fa 100644 --- a/tests/functional/openlp_plugins/songs/test_openlyricsimport.py +++ b/tests/functional/openlp_plugins/songs/test_openlyricsimport.py @@ -31,11 +31,18 @@ This module contains tests for the OpenLyrics song importer. """ import os +import json from unittest import TestCase +from lxml import etree, objectify from tests.functional import MagicMock, patch +from tests.helpers.testmixin import TestMixin from openlp.plugins.songs.lib.importers.openlyrics import OpenLyricsImport from openlp.plugins.songs.lib.importers.songimport import SongImport +from openlp.plugins.songs.lib.openlyricsxml import OpenLyrics +from openlp.core.common import Registry, Settings +from openlp.core.lib import FormattingTags + TEST_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..', 'resources', 'openlyricssongs')) @@ -59,11 +66,28 @@ SONG_TEST_DATA = { } } +tags_str ='[{"protected": false, "desc": "z", "start tag": "{z}", "end html": "", "temporary": false, "end tag": "{/z}", "start html": "strong>"}]' -class TestOpenLyricsImport(TestCase): + +class TestOpenLyricsImport(TestCase, TestMixin): """ Test the functions in the :mod:`openlyricsimport` module. """ + def setUp(self): + """ + Create the registry + """ + self.get_application() + Registry.create() + self.build_settings() + #Settings().extend_default_settings(__default_settings__) + + def tearDown(self): + """ + Cleanup + """ + self.destroy_settings() + def create_importer_test(self): """ Test creating an instance of the OpenLyrics file importer @@ -97,3 +121,24 @@ class TestOpenLyricsImport(TestCase): # THEN: The xml_to_song() method should have been called self.assertTrue(importer.open_lyrics.xml_to_song.called) + + def process_formatting_tags_test(self): + """ + Test that _process_formatting_tags works + """ + # GIVEN: A OpenLyric XML with formatting and a mocked out formattingtag-setting + mocked_manager = MagicMock() + Settings().setValue('formattingTags/html_tags', json.loads(tags_str)) + ol = OpenLyrics(mocked_manager) + parser = etree.XMLParser(remove_blank_text=True) + parsed_file = etree.parse(open(os.path.join(TEST_PATH, 'duchu-tags.xml'), 'rb'), parser) + xml = etree.tostring(parsed_file).decode() + song_xml = objectify.fromstring(xml) + + # WHEN: processing the formatting tags + print(Settings().value('formattingTags/html_tags')) + ol._process_formatting_tags(song_xml, False) + + # THEN: New tags should have been saved + print(str(Settings().value('formattingTags/html_tags'))) + self.assertTrue(False) From 839df08eb76a1b66ebe7bfe365e77b8699402384 Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Thu, 25 Sep 2014 17:02:10 +0200 Subject: [PATCH 04/11] Another test fix --- tests/helpers/songfileimport.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/helpers/songfileimport.py b/tests/helpers/songfileimport.py index 01bfafdd8..7a911dea8 100644 --- a/tests/helpers/songfileimport.py +++ b/tests/helpers/songfileimport.py @@ -34,6 +34,8 @@ import json import logging from unittest import TestCase +from openlp.plugins.songs.lib.importers.opensong import OpenSongImport +from openlp.core.common import Registry from tests.functional import patch, MagicMock, call log = logging.getLogger(__name__) @@ -53,6 +55,7 @@ class SongImportTestHelper(TestCase): """ Patch and set up the mocks required. """ + Registry.create() self.add_copyright_patcher = patch('openlp.plugins.songs.lib.importers.%s.%s.add_copyright' % (self.importer_module_name, self.importer_class_name)) self.add_verse_patcher = patch('openlp.plugins.songs.lib.importers.%s.%s.add_verse' % From 9b8b114a59835e659e08871bb468da7454d9b898 Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Thu, 25 Sep 2014 21:31:31 +0100 Subject: [PATCH 05/11] Fixed the new test. --- .../songs/test_openlyricsimport.py | 18 ++++++++----- .../resources/openlyricssongs/duchu-tags.xml | 27 +++++++++++++++++++ 2 files changed, 39 insertions(+), 6 deletions(-) create mode 100644 tests/resources/openlyricssongs/duchu-tags.xml diff --git a/tests/functional/openlp_plugins/songs/test_openlyricsimport.py b/tests/functional/openlp_plugins/songs/test_openlyricsimport.py index 7e1fba1fa..b782a14ba 100644 --- a/tests/functional/openlp_plugins/songs/test_openlyricsimport.py +++ b/tests/functional/openlp_plugins/songs/test_openlyricsimport.py @@ -66,7 +66,13 @@ SONG_TEST_DATA = { } } -tags_str ='[{"protected": false, "desc": "z", "start tag": "{z}", "end html": "", "temporary": false, "end tag": "{/z}", "start html": "strong>"}]' +start_tags = [{"protected": False, "desc": "z", "start tag": "{z}", "end html": "", "temporary": False, + "end tag": "{/z}", "start html": "strong>"}] +result_tags = [{"temporary": False, "protected": False, "desc": "z", "start tag": "{z}", "start html": "strong>", + "end html": "", "end tag": "{/z}"}, + {"temporary": False, "end tag": "{/c}", "desc": "c", "start tag": "{c}", + "start html": "", "end html": "", + "protected": False}] class TestOpenLyricsImport(TestCase, TestMixin): @@ -126,9 +132,9 @@ class TestOpenLyricsImport(TestCase, TestMixin): """ Test that _process_formatting_tags works """ - # GIVEN: A OpenLyric XML with formatting and a mocked out formattingtag-setting + # GIVEN: A OpenLyric XML with formatting tags and a mocked out manager mocked_manager = MagicMock() - Settings().setValue('formattingTags/html_tags', json.loads(tags_str)) + Settings().setValue('formattingTags/html_tags', json.dumps(start_tags)) ol = OpenLyrics(mocked_manager) parser = etree.XMLParser(remove_blank_text=True) parsed_file = etree.parse(open(os.path.join(TEST_PATH, 'duchu-tags.xml'), 'rb'), parser) @@ -136,9 +142,9 @@ class TestOpenLyricsImport(TestCase, TestMixin): song_xml = objectify.fromstring(xml) # WHEN: processing the formatting tags - print(Settings().value('formattingTags/html_tags')) ol._process_formatting_tags(song_xml, False) # THEN: New tags should have been saved - print(str(Settings().value('formattingTags/html_tags'))) - self.assertTrue(False) + self.assertListEqual(json.loads(json.dumps(result_tags)), + json.loads(str(Settings().value('formattingTags/html_tags'))), + 'The formatting tags should contain both the old and the new') diff --git a/tests/resources/openlyricssongs/duchu-tags.xml b/tests/resources/openlyricssongs/duchu-tags.xml new file mode 100644 index 000000000..e082ce5fc --- /dev/null +++ b/tests/resources/openlyricssongs/duchu-tags.xml @@ -0,0 +1,27 @@ + + + + + Duchu svätý volám príď <akordy> + + + Author Unknown + + + + + + <span class="chord" style="display:none"><strong> + </strong></span> + + + + + + [D]Duchu svätý volám príď, [Ami]oheň mojej duši daj,
[G]Oheň môjmu telu daj, [D]rozpáľ ma.
+
+ + Všemoh[Ami]úci [G]Boh tu s nami [D]je,
neko[Ami]nečne [G]milostivý [D]je,
Uka[Ami]zuje [G]dobrotivú [D]tvár voči [Ami]t[G]ým,
ktorí milovať ho [D]chcú.
+
+
+
\ No newline at end of file From 60dc075e3b6786d6b5cdf10d91be974bdecc89d8 Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Thu, 25 Sep 2014 21:46:09 +0100 Subject: [PATCH 06/11] pep8 fix --- openlp/plugins/songs/lib/openlyricsxml.py | 3 ++- tests/functional/openlp_plugins/songs/test_openlyricsimport.py | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/openlp/plugins/songs/lib/openlyricsxml.py b/openlp/plugins/songs/lib/openlyricsxml.py index 01c6cf50e..cab51093c 100644 --- a/openlp/plugins/songs/lib/openlyricsxml.py +++ b/openlp/plugins/songs/lib/openlyricsxml.py @@ -594,7 +594,8 @@ class OpenLyrics(object): if new_tags: FormattingTags.add_html_tags(new_tags) if not temporary: - custom_tags = [tag for tag in FormattingTags.get_html_tags() if not tag['protected'] and not tag['temporary']] + custom_tags = [tag for tag in FormattingTags.get_html_tags() + if not tag['protected'] and not tag['temporary']] FormattingTags.save_html_tags(custom_tags) def _process_lines_mixed_content(self, element, newlines=True): diff --git a/tests/functional/openlp_plugins/songs/test_openlyricsimport.py b/tests/functional/openlp_plugins/songs/test_openlyricsimport.py index b782a14ba..d7ba07beb 100644 --- a/tests/functional/openlp_plugins/songs/test_openlyricsimport.py +++ b/tests/functional/openlp_plugins/songs/test_openlyricsimport.py @@ -86,7 +86,6 @@ class TestOpenLyricsImport(TestCase, TestMixin): self.get_application() Registry.create() self.build_settings() - #Settings().extend_default_settings(__default_settings__) def tearDown(self): """ From a8a7068de85effb69250582a093a7ff43c2c6f92 Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Sat, 27 Sep 2014 20:57:28 +0100 Subject: [PATCH 07/11] Added slidecontroller ui test --- .../openlp_core_ui/test_slidecontroller.py | 90 +++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 tests/interfaces/openlp_core_ui/test_slidecontroller.py diff --git a/tests/interfaces/openlp_core_ui/test_slidecontroller.py b/tests/interfaces/openlp_core_ui/test_slidecontroller.py new file mode 100644 index 000000000..efbc9368b --- /dev/null +++ b/tests/interfaces/openlp_core_ui/test_slidecontroller.py @@ -0,0 +1,90 @@ +# -*- 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. +""" +from PyQt4 import QtCore, QtTest + +from unittest import TestCase +from openlp.core import Registry +from openlp.core.lib import ServiceItemAction +from openlp.core.lib import ScreenList + +from openlp.core.ui import SlideController +from openlp.core.ui.slidecontroller import WIDE_MENU, NON_TEXT_MENU + +from tests.interfaces import MagicMock, patch +from tests.helpers.testmixin import TestMixin + + +class TestSlideController(TestCase,TestMixin): + + def setUp(self): + """ + Create the UI + """ + self.build_settings() + self.get_application() + Registry.create() + ScreenList.create(self.app.desktop()) + self.mocked_main_window = MagicMock() + self.mocked_main_window.control_splitter = None + Registry().register('media_controller', MagicMock()) + Registry().register('service_list', MagicMock()) + Registry().register('main_window', self.mocked_main_window) + self.slide_controller = SlideController(None) + self.slide_controller.update_slide_limits = MagicMock() + self.slide_controller.type_prefix = MagicMock() + self.slide_controller.category = MagicMock() + + def tearDown(self): + """ + Clean up + """ + self.destroy_settings() + + + def click_preview_widget_test(self): + """ + Test that when the preview_widget is clicked then on_slide_selected is called + """ + # GIVEN: An initialized SlideController with some mocking + with patch('openlp.core.ui.slidecontroller.create_action') as mocked_create_action: + mocked_create_action.return_value = None + self.slide_controller.on_slide_selected = MagicMock() + self.slide_controller.initialise() + + # WHEN: The preview_widget is clicked + QtTest.QTest.mouseClick(self.slide_controller.preview_widget, QtCore.Qt.LeftButton) + QtTest.QTest.mouseClick(self.slide_controller.preview_widget.verticalHeader(), QtCore.Qt.LeftButton) + + + # THEN slide_selected should have been called twice + self.assertEqual(self.slide_controller.on_slide_selected.call_count, 2, + 'on_slide_selected should have been called 2 times') \ No newline at end of file From 2b9d36702ba2c08f2d9aebfe2ebacfd8f0219197 Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Mon, 29 Sep 2014 21:11:07 +0100 Subject: [PATCH 08/11] Added oxps as supported presentation filetype (by mudraw) --- openlp/plugins/presentations/lib/mediaitem.py | 2 +- openlp/plugins/presentations/lib/messagelistener.py | 6 +++--- openlp/plugins/presentations/lib/pdfcontroller.py | 2 +- .../openlp_plugins/presentations/test_mediaitem.py | 3 ++- tests/interfaces/openlp_core_ui/test_slidecontroller.py | 4 +--- 5 files changed, 8 insertions(+), 9 deletions(-) diff --git a/openlp/plugins/presentations/lib/mediaitem.py b/openlp/plugins/presentations/lib/mediaitem.py index 5b503d50f..d85f71512 100644 --- a/openlp/plugins/presentations/lib/mediaitem.py +++ b/openlp/plugins/presentations/lib/mediaitem.py @@ -264,7 +264,7 @@ class PresentationMediaItem(MediaManagerItem): if not self.display_type_combo_box.currentText(): return False service_item.add_capability(ItemCapabilities.CanEditTitle) - if (file_type == 'pdf' or file_type == 'xps') and context != ServiceItemContext.Service: + if (file_type == 'pdf' or file_type == 'xps' or filetype == 'oxps') and context != ServiceItemContext.Service: service_item.add_capability(ItemCapabilities.CanMaintain) service_item.add_capability(ItemCapabilities.CanPreview) service_item.add_capability(ItemCapabilities.CanLoop) diff --git a/openlp/plugins/presentations/lib/messagelistener.py b/openlp/plugins/presentations/lib/messagelistener.py index ac115228a..d4275a189 100644 --- a/openlp/plugins/presentations/lib/messagelistener.py +++ b/openlp/plugins/presentations/lib/messagelistener.py @@ -320,10 +320,10 @@ class MessageListener(object): file = item.get_frame_path() self.handler = item.processor # When starting presentation from the servicemanager we convert - # PDF/XPS-serviceitems into image-serviceitems. When started from the mediamanager + # PDF/XPS/OXPS-serviceitems into image-serviceitems. When started from the mediamanager # the conversion has already been done at this point. - if file.endswith('.pdf') or file.endswith('.xps'): - log.debug('Converting from pdf/xps to images for serviceitem with file %s', file) + if file.endswith('.pdf') or file.endswith('xps'): + log.debug('Converting from pdf/xps/oxps to images for serviceitem with file %s', file) # Create a copy of the original item, and then clear the original item so it can be filled with images item_cpy = copy.copy(item) item.__init__(None) diff --git a/openlp/plugins/presentations/lib/pdfcontroller.py b/openlp/plugins/presentations/lib/pdfcontroller.py index 0283fefd4..7545aac1f 100644 --- a/openlp/plugins/presentations/lib/pdfcontroller.py +++ b/openlp/plugins/presentations/lib/pdfcontroller.py @@ -148,7 +148,7 @@ class PdfController(PresentationController): if os.path.isfile(os.path.join(application_path, 'mudraw')): self.mudrawbin = os.path.join(application_path, 'mudraw') if self.mudrawbin: - self.also_supports = ['xps'] + self.also_supports = ['xps', 'oxps'] return True elif self.gsbin: return True diff --git a/tests/functional/openlp_plugins/presentations/test_mediaitem.py b/tests/functional/openlp_plugins/presentations/test_mediaitem.py index 2210c7d1f..b826a4cae 100644 --- a/tests/functional/openlp_plugins/presentations/test_mediaitem.py +++ b/tests/functional/openlp_plugins/presentations/test_mediaitem.py @@ -71,7 +71,7 @@ class TestMediaItem(TestCase, TestMixin): pdf_controller = MagicMock() pdf_controller.enabled.return_value = True pdf_controller.supports = ['pdf'] - pdf_controller.also_supports = ['xps'] + pdf_controller.also_supports = ['xps', 'oxps'] # Mock the controllers. self.media_item.controllers = { 'Impress': impress_controller, @@ -90,3 +90,4 @@ class TestMediaItem(TestCase, TestMixin): self.assertIn('*.ppt', self.media_item.on_new_file_masks, 'The file mask should contain the ppt extension') self.assertIn('*.pdf', self.media_item.on_new_file_masks, 'The file mask should contain the pdf extension') self.assertIn('*.xps', self.media_item.on_new_file_masks, 'The file mask should contain the xps extension') + self.assertIn('*.oxps', self.media_item.on_new_file_masks, 'The file mask should contain the oxps extension') diff --git a/tests/interfaces/openlp_core_ui/test_slidecontroller.py b/tests/interfaces/openlp_core_ui/test_slidecontroller.py index efbc9368b..b797548a5 100644 --- a/tests/interfaces/openlp_core_ui/test_slidecontroller.py +++ b/tests/interfaces/openlp_core_ui/test_slidecontroller.py @@ -32,12 +32,10 @@ Package to test the openlp.core.ui.slidecontroller package. from PyQt4 import QtCore, QtTest from unittest import TestCase -from openlp.core import Registry -from openlp.core.lib import ServiceItemAction +from openlp.core.common import Registry from openlp.core.lib import ScreenList from openlp.core.ui import SlideController -from openlp.core.ui.slidecontroller import WIDE_MENU, NON_TEXT_MENU from tests.interfaces import MagicMock, patch from tests.helpers.testmixin import TestMixin From 9dbbe9d5bee41c812e4c46d4061b19c4af9c944b Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Fri, 3 Oct 2014 11:57:35 +0200 Subject: [PATCH 09/11] Fixed console popping up on windows when running mudraw.exe --- .../presentations/lib/pdfcontroller.py | 29 +++++++++++++++---- .../openlp_core_ui/test_slidecontroller.py | 6 ++-- 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/openlp/plugins/presentations/lib/pdfcontroller.py b/openlp/plugins/presentations/lib/pdfcontroller.py index 7545aac1f..8fb00d917 100644 --- a/openlp/plugins/presentations/lib/pdfcontroller.py +++ b/openlp/plugins/presentations/lib/pdfcontroller.py @@ -34,10 +34,13 @@ import re from subprocess import check_output, CalledProcessError, STDOUT from openlp.core.utils import AppLocation -from openlp.core.common import Settings, is_win +from openlp.core.common import Settings, is_win, trace_error_handler from openlp.core.lib import ScreenList from .presentationcontroller import PresentationController, PresentationDocument +if is_win(): + from subprocess import STARTUPINFO, STARTF_USESHOWWINDOW + log = logging.getLogger(__name__) @@ -74,11 +77,19 @@ class PdfController(PresentationController): runlog = '' log.debug('testing program_path: %s', program_path) try: - runlog = check_output([program_path, '--help'], stderr=STDOUT) + # Setup startupinfo options for check_output to avoid console popping up on windows + if is_win(): + startupinfo = STARTUPINFO() + startupinfo.dwFlags |= STARTF_USESHOWWINDOW + else: + startupinfo = None + runlog = check_output([program_path, '--help'], stderr=STDOUT, startupinfo=startupinfo) except CalledProcessError as e: runlog = e.output except Exception: + trace_error_handler(log) runlog = '' + log.debug('check_output returned: %s' % runlog) # Analyse the output to see it the program is mudraw, ghostscript or neither for line in runlog.splitlines(): decoded_line = line.decode() @@ -182,6 +193,12 @@ class PdfDocument(PresentationDocument): self.hidden = False self.image_files = [] self.num_pages = -1 + # Setup startupinfo options for check_output to avoid console popping up on windows + if is_win(): + self.startupinfo = STARTUPINFO() + self.startupinfo.dwFlags |= STARTF_USESHOWWINDOW + else: + self.startupinfo = None def gs_get_resolution(self, size): """ @@ -199,7 +216,8 @@ class PdfDocument(PresentationDocument): runlog = [] try: runlog = check_output([self.controller.gsbin, '-dNOPAUSE', '-dNODISPLAY', '-dBATCH', - '-sFile=' + self.file_path, gs_resolution_script]) + '-sFile=' + self.file_path, gs_resolution_script], + startupinfo=self.startupinfo) except CalledProcessError as e: log.debug(' '.join(e.cmd)) log.debug(e.output) @@ -248,13 +266,14 @@ class PdfDocument(PresentationDocument): os.makedirs(self.get_temp_folder()) if self.controller.mudrawbin: runlog = check_output([self.controller.mudrawbin, '-w', str(size.right()), '-h', str(size.bottom()), - '-o', os.path.join(self.get_temp_folder(), 'mainslide%03d.png'), self.file_path]) + '-o', os.path.join(self.get_temp_folder(), 'mainslide%03d.png'), self.file_path], + startupinfo=self.startupinfo) elif self.controller.gsbin: resolution = self.gs_get_resolution(size) runlog = check_output([self.controller.gsbin, '-dSAFER', '-dNOPAUSE', '-dBATCH', '-sDEVICE=png16m', '-r' + str(resolution), '-dTextAlphaBits=4', '-dGraphicsAlphaBits=4', '-sOutputFile=' + os.path.join(self.get_temp_folder(), 'mainslide%03d.png'), - self.file_path]) + self.file_path], startupinfo=self.startupinfo) created_files = sorted(os.listdir(self.get_temp_folder())) for fn in created_files: if os.path.isfile(os.path.join(self.get_temp_folder(), fn)): diff --git a/tests/interfaces/openlp_core_ui/test_slidecontroller.py b/tests/interfaces/openlp_core_ui/test_slidecontroller.py index b797548a5..f83fb28ba 100644 --- a/tests/interfaces/openlp_core_ui/test_slidecontroller.py +++ b/tests/interfaces/openlp_core_ui/test_slidecontroller.py @@ -41,7 +41,7 @@ from tests.interfaces import MagicMock, patch from tests.helpers.testmixin import TestMixin -class TestSlideController(TestCase,TestMixin): +class TestSlideController(TestCase, TestMixin): def setUp(self): """ @@ -67,7 +67,6 @@ class TestSlideController(TestCase,TestMixin): """ self.destroy_settings() - def click_preview_widget_test(self): """ Test that when the preview_widget is clicked then on_slide_selected is called @@ -82,7 +81,6 @@ class TestSlideController(TestCase,TestMixin): QtTest.QTest.mouseClick(self.slide_controller.preview_widget, QtCore.Qt.LeftButton) QtTest.QTest.mouseClick(self.slide_controller.preview_widget.verticalHeader(), QtCore.Qt.LeftButton) - # THEN slide_selected should have been called twice self.assertEqual(self.slide_controller.on_slide_selected.call_count, 2, - 'on_slide_selected should have been called 2 times') \ No newline at end of file + 'on_slide_selected should have been called 2 times') From 773a1cef39733a574fa5fa12d974c925eb81ae1b Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Mon, 6 Oct 2014 21:05:06 +0100 Subject: [PATCH 10/11] Remove non-working test --- .../openlp_core_ui/test_slidecontroller.py | 86 ------------------- 1 file changed, 86 deletions(-) delete mode 100644 tests/interfaces/openlp_core_ui/test_slidecontroller.py diff --git a/tests/interfaces/openlp_core_ui/test_slidecontroller.py b/tests/interfaces/openlp_core_ui/test_slidecontroller.py deleted file mode 100644 index f83fb28ba..000000000 --- a/tests/interfaces/openlp_core_ui/test_slidecontroller.py +++ /dev/null @@ -1,86 +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. -""" -from PyQt4 import QtCore, QtTest - -from unittest import TestCase -from openlp.core.common import Registry -from openlp.core.lib import ScreenList - -from openlp.core.ui import SlideController - -from tests.interfaces import MagicMock, patch -from tests.helpers.testmixin import TestMixin - - -class TestSlideController(TestCase, TestMixin): - - def setUp(self): - """ - Create the UI - """ - self.build_settings() - self.get_application() - Registry.create() - ScreenList.create(self.app.desktop()) - self.mocked_main_window = MagicMock() - self.mocked_main_window.control_splitter = None - Registry().register('media_controller', MagicMock()) - Registry().register('service_list', MagicMock()) - Registry().register('main_window', self.mocked_main_window) - self.slide_controller = SlideController(None) - self.slide_controller.update_slide_limits = MagicMock() - self.slide_controller.type_prefix = MagicMock() - self.slide_controller.category = MagicMock() - - def tearDown(self): - """ - Clean up - """ - self.destroy_settings() - - def click_preview_widget_test(self): - """ - Test that when the preview_widget is clicked then on_slide_selected is called - """ - # GIVEN: An initialized SlideController with some mocking - with patch('openlp.core.ui.slidecontroller.create_action') as mocked_create_action: - mocked_create_action.return_value = None - self.slide_controller.on_slide_selected = MagicMock() - self.slide_controller.initialise() - - # WHEN: The preview_widget is clicked - QtTest.QTest.mouseClick(self.slide_controller.preview_widget, QtCore.Qt.LeftButton) - QtTest.QTest.mouseClick(self.slide_controller.preview_widget.verticalHeader(), QtCore.Qt.LeftButton) - - # THEN slide_selected should have been called twice - self.assertEqual(self.slide_controller.on_slide_selected.call_count, 2, - 'on_slide_selected should have been called 2 times') From c02ef96fff543fecd22ce783a537d64cd1f0cfe9 Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Tue, 14 Oct 2014 11:05:35 +0200 Subject: [PATCH 11/11] Made the code a bit more readable by introducing PDF_CONTROLLER_FILETYPES --- openlp/plugins/presentations/lib/mediaitem.py | 6 +++--- openlp/plugins/presentations/lib/messagelistener.py | 9 ++++++--- openlp/plugins/presentations/lib/pdfcontroller.py | 2 ++ 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/openlp/plugins/presentations/lib/mediaitem.py b/openlp/plugins/presentations/lib/mediaitem.py index d85f71512..6502d3220 100644 --- a/openlp/plugins/presentations/lib/mediaitem.py +++ b/openlp/plugins/presentations/lib/mediaitem.py @@ -38,7 +38,7 @@ from openlp.core.lib import MediaManagerItem, ItemCapabilities, ServiceItemConte from openlp.core.lib.ui import critical_error_message_box, create_horizontal_adjusting_combo_box from openlp.core.utils import get_locale_key from openlp.plugins.presentations.lib import MessageListener - +from openlp.plugins.presentations.lib.pdfcontroller import PDF_CONTROLLER_FILETYPES log = logging.getLogger(__name__) @@ -260,11 +260,11 @@ class PresentationMediaItem(MediaManagerItem): filename = presentation_file if filename is None: filename = items[0].data(QtCore.Qt.UserRole) - file_type = os.path.splitext(filename)[1][1:] + file_type = os.path.splitext(filename.lower())[1][1:] if not self.display_type_combo_box.currentText(): return False service_item.add_capability(ItemCapabilities.CanEditTitle) - if (file_type == 'pdf' or file_type == 'xps' or filetype == 'oxps') and context != ServiceItemContext.Service: + if file_type in PDF_CONTROLLER_FILETYPES and context != ServiceItemContext.Service: service_item.add_capability(ItemCapabilities.CanMaintain) service_item.add_capability(ItemCapabilities.CanPreview) service_item.add_capability(ItemCapabilities.CanLoop) diff --git a/openlp/plugins/presentations/lib/messagelistener.py b/openlp/plugins/presentations/lib/messagelistener.py index d4275a189..fb37ef403 100644 --- a/openlp/plugins/presentations/lib/messagelistener.py +++ b/openlp/plugins/presentations/lib/messagelistener.py @@ -29,12 +29,14 @@ import logging import copy +import os from PyQt4 import QtCore from openlp.core.common import Registry from openlp.core.ui import HideMode from openlp.core.lib import ServiceItemContext, ServiceItem +from openlp.plugins.presentations.lib.pdfcontroller import PDF_CONTROLLER_FILETYPES log = logging.getLogger(__name__) @@ -322,7 +324,8 @@ class MessageListener(object): # When starting presentation from the servicemanager we convert # PDF/XPS/OXPS-serviceitems into image-serviceitems. When started from the mediamanager # the conversion has already been done at this point. - if file.endswith('.pdf') or file.endswith('xps'): + file_type = os.path.splitext(file.lower())[1][1:] + if file_type in PDF_CONTROLLER_FILETYPES: log.debug('Converting from pdf/xps/oxps to images for serviceitem with file %s', file) # Create a copy of the original item, and then clear the original item so it can be filled with images item_cpy = copy.copy(item) @@ -338,7 +341,7 @@ class MessageListener(object): item.image_border = item_cpy.image_border item.main = item_cpy.main item.theme_data = item_cpy.theme_data - # When presenting PDF or XPS, we are using the image presentation code, + # When presenting PDF/XPS/OXPS, we are using the image presentation code, # so handler & processor is set to None, and we skip adding the handler. self.handler = None if self.handler == self.media_item.automatic: @@ -349,7 +352,7 @@ class MessageListener(object): controller = self.live_handler else: controller = self.preview_handler - # When presenting PDF or XPS, we are using the image presentation code, + # When presenting PDF/XPS/OXPS, we are using the image presentation code, # so handler & processor is set to None, and we skip adding the handler. if self.handler is None: self.controller = controller diff --git a/openlp/plugins/presentations/lib/pdfcontroller.py b/openlp/plugins/presentations/lib/pdfcontroller.py index 8fb00d917..e1d0dc8f0 100644 --- a/openlp/plugins/presentations/lib/pdfcontroller.py +++ b/openlp/plugins/presentations/lib/pdfcontroller.py @@ -43,6 +43,8 @@ if is_win(): log = logging.getLogger(__name__) +PDF_CONTROLLER_FILETYPES = ['pdf', 'xps', 'oxps'] + class PdfController(PresentationController): """