← Back to team overview

openlp-core team mailing list archive

[Merge] lp:~tomasgroth/openlp/bugfixes1 into lp:openlp

 

Tomas Groth has proposed merging lp:~tomasgroth/openlp/bugfixes1 into lp:openlp.

Requested reviews:
  Raoul Snyman (raoul-snyman)
  Tim Bentley (trb143)

For more details, see:
https://code.launchpad.net/~tomasgroth/openlp/bugfixes1/+merge/238262

Fix tests so they can run individually.
Fix for importing custom tags from openlyricsxml.
Fixed console popping up on windows when running mudraw.exe.
Added oxps as supported presentation filetype (by mudraw).
-- 
https://code.launchpad.net/~tomasgroth/openlp/bugfixes1/+merge/238262
Your team OpenLP Core is subscribed to branch lp:openlp.
=== modified file 'openlp/core/ui/slidecontroller.py'
--- openlp/core/ui/slidecontroller.py	2014-07-15 18:52:59 +0000
+++ openlp/core/ui/slidecontroller.py	2014-10-14 09:12:37 +0000
@@ -374,7 +374,8 @@
                                                       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)

=== modified file 'openlp/plugins/presentations/lib/mediaitem.py'
--- openlp/plugins/presentations/lib/mediaitem.py	2014-08-25 20:04:33 +0000
+++ openlp/plugins/presentations/lib/mediaitem.py	2014-10-14 09:12:37 +0000
@@ -38,7 +38,7 @@
 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 @@
         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') 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)

=== modified file 'openlp/plugins/presentations/lib/messagelistener.py'
--- openlp/plugins/presentations/lib/messagelistener.py	2014-09-08 21:08:49 +0000
+++ openlp/plugins/presentations/lib/messagelistener.py	2014-10-14 09:12:37 +0000
@@ -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__)
 
@@ -320,10 +322,11 @@
         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)
+        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)
             item.__init__(None)
@@ -338,7 +341,7 @@
             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 @@
             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

=== modified file 'openlp/plugins/presentations/lib/pdfcontroller.py'
--- openlp/plugins/presentations/lib/pdfcontroller.py	2014-08-27 23:18:06 +0000
+++ openlp/plugins/presentations/lib/pdfcontroller.py	2014-10-14 09:12:37 +0000
@@ -34,12 +34,17 @@
 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__)
 
+PDF_CONTROLLER_FILETYPES = ['pdf', 'xps', 'oxps']
+
 
 class PdfController(PresentationController):
     """
@@ -74,11 +79,19 @@
         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()
@@ -148,7 +161,7 @@
                     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
@@ -182,6 +195,12 @@
         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 +218,8 @@
         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 +268,14 @@
                 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)):

=== modified file 'openlp/plugins/songs/lib/openlyricsxml.py'
--- openlp/plugins/songs/lib/openlyricsxml.py	2014-07-03 16:54:51 +0000
+++ openlp/plugins/songs/lib/openlyricsxml.py	2014-10-14 09:12:37 +0000
@@ -239,6 +239,7 @@
 
     def __init__(self, manager):
         self.manager = manager
+        FormattingTags.load_tags()
 
     def song_to_xml(self, song):
         """
@@ -582,18 +583,20 @@
                 # 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):
         """

=== modified file 'tests/functional/openlp_plugins/presentations/test_mediaitem.py'
--- tests/functional/openlp_plugins/presentations/test_mediaitem.py	2014-03-14 22:08:44 +0000
+++ tests/functional/openlp_plugins/presentations/test_mediaitem.py	2014-10-14 09:12:37 +0000
@@ -71,7 +71,7 @@
         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 @@
         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')

=== modified file 'tests/functional/openlp_plugins/remotes/test_router.py'
--- tests/functional/openlp_plugins/remotes/test_router.py	2014-07-11 13:35:44 +0000
+++ tests/functional/openlp_plugins/remotes/test_router.py	2014-10-14 09:12:37 +0000
@@ -132,6 +132,7 @@
         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()

=== modified file 'tests/functional/openlp_plugins/songs/test_ewimport.py'
--- tests/functional/openlp_plugins/songs/test_ewimport.py	2014-07-04 09:31:06 +0000
+++ tests/functional/openlp_plugins/songs/test_ewimport.py	2014-10-14 09:12:37 +0000
@@ -35,6 +35,7 @@
 
 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 @@
     """
     Test the functions in the :mod:`ewimport` module.
     """
+    def setUp(self):
+        """
+        Create the registry
+        """
+        Registry.create()
 
     def create_field_desc_entry_test(self):
         """

=== modified file 'tests/functional/openlp_plugins/songs/test_openlyricsimport.py'
--- tests/functional/openlp_plugins/songs/test_openlyricsimport.py	2014-07-04 09:31:06 +0000
+++ tests/functional/openlp_plugins/songs/test_openlyricsimport.py	2014-10-14 09:12:37 +0000
@@ -31,11 +31,18 @@
 """
 
 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,33 @@
     }
 }
 
-
-class TestOpenLyricsImport(TestCase):
+start_tags = [{"protected": False, "desc": "z", "start tag": "{z}", "end html": "</strong>", "temporary": False,
+               "end tag": "{/z}", "start html": "strong>"}]
+result_tags = [{"temporary": False, "protected": False, "desc": "z", "start tag": "{z}", "start html": "strong>",
+                "end html": "</strong>", "end tag": "{/z}"},
+               {"temporary": False, "end tag": "{/c}", "desc": "c", "start tag": "{c}",
+                "start html": "<span class=\"chord\" style=\"display:none\"><strong>", "end html": "</strong></span>",
+                "protected": False}]
+
+
+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()
+
+    def tearDown(self):
+        """
+        Cleanup
+        """
+        self.destroy_settings()
+
     def create_importer_test(self):
         """
         Test creating an instance of the OpenLyrics file importer
@@ -97,3 +126,24 @@
 
             # 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 tags and a mocked out manager
+        mocked_manager = MagicMock()
+        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)
+        xml = etree.tostring(parsed_file).decode()
+        song_xml = objectify.fromstring(xml)
+
+        # WHEN: processing the formatting tags
+        ol._process_formatting_tags(song_xml, False)
+
+        # THEN: New tags should have been saved
+        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')

=== modified file 'tests/functional/openlp_plugins/songs/test_opensongimport.py'
--- tests/functional/openlp_plugins/songs/test_opensongimport.py	2014-07-04 09:31:06 +0000
+++ tests/functional/openlp_plugins/songs/test_opensongimport.py	2014-10-14 09:12:37 +0000
@@ -35,6 +35,7 @@
 
 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 @@
     """
     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

=== modified file 'tests/functional/openlp_plugins/songs/test_powerpraiseimport.py'
--- tests/functional/openlp_plugins/songs/test_powerpraiseimport.py	2014-08-21 12:51:34 +0000
+++ tests/functional/openlp_plugins/songs/test_powerpraiseimport.py	2014-10-14 09:12:37 +0000
@@ -34,6 +34,7 @@
 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'))

=== modified file 'tests/functional/openlp_plugins/songs/test_songbeamerimport.py'
--- tests/functional/openlp_plugins/songs/test_songbeamerimport.py	2014-07-04 09:31:06 +0000
+++ tests/functional/openlp_plugins/songs/test_songbeamerimport.py	2014-10-14 09:12:37 +0000
@@ -36,6 +36,7 @@
 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 @@
     """
     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

=== modified file 'tests/functional/openlp_plugins/songs/test_zionworximport.py'
--- tests/functional/openlp_plugins/songs/test_zionworximport.py	2014-07-04 09:31:06 +0000
+++ tests/functional/openlp_plugins/songs/test_zionworximport.py	2014-10-14 09:12:37 +0000
@@ -35,12 +35,19 @@
 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

=== modified file 'tests/helpers/songfileimport.py'
--- tests/helpers/songfileimport.py	2014-07-07 16:21:45 +0000
+++ tests/helpers/songfileimport.py	2014-10-14 09:12:37 +0000
@@ -34,6 +34,8 @@
 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 @@
         """
         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' %

=== added file 'tests/resources/openlyricssongs/duchu-tags.xml'
--- tests/resources/openlyricssongs/duchu-tags.xml	1970-01-01 00:00:00 +0000
+++ tests/resources/openlyricssongs/duchu-tags.xml	2014-10-14 09:12:37 +0000
@@ -0,0 +1,27 @@
+<?xml version='1.0' encoding='utf-8'?>
+<song xmlns="http://openlyrics.info/namespace/2009/song"; version="0.8" createdIn="OpenLP 2.0.4" modifiedIn="OpenLP 2.0.4" modifiedDate="2014-06-27T09:55:49">
+  <properties>
+    <titles>
+      <title>Duchu svätý volám príď &lt;akordy&gt;</title>
+    </titles>
+    <authors>
+      <author>Author Unknown</author>
+    </authors>
+  </properties>
+  <format>
+    <tags application="OpenLP">
+      <tag name="c">
+        <open>&lt;span class="chord" style="display:none"&gt;&lt;strong&gt;</open>
+        <close>&lt;/strong&gt;&lt;/span&gt;</close>
+      </tag>
+    </tags>
+  </format>
+  <lyrics>
+    <verse name="v1">
+      <lines><tag name="c">[D]</tag>Duchu svätý volám príď, <tag name="c">[Ami]</tag>oheň mojej duši daj,<br/><tag name="c">[G]</tag>Oheň môjmu telu daj, <tag name="c">[D]</tag>rozpáľ ma.</lines>
+    </verse>
+    <verse name="c1">
+      <lines>Všemoh<tag name="c">[Ami]</tag>úci <tag name="c">[G]</tag>Boh tu s nami <tag name="c">[D]</tag>je,<br/>neko<tag name="c">[Ami]</tag>nečne <tag name="c">[G]</tag>milostivý <tag name="c">[D]</tag>je,<br/>Uka<tag name="c">[Ami]</tag>zuje <tag name="c">[G]</tag>dobrotivú <tag name="c">[D]</tag>tvár voči <tag name="c">[Ami]</tag>t<tag name="c">[G]</tag>ým,<br/>ktorí milovať ho <tag name="c">[D]</tag>chcú.</lines>
+    </verse>
+  </lyrics>
+</song>
\ No newline at end of file


References