From 6b23a2224f5f3298a30066e5074b124959e3ee4c Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Fri, 15 Jan 2016 21:22:08 +0100 Subject: [PATCH 01/11] Fix playback of linked audio. Fixes bug 1533280. Fixes: https://launchpad.net/bugs/1533280 --- openlp/core/ui/maindisplay.py | 3 ++- openlp/core/ui/slidecontroller.py | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/openlp/core/ui/maindisplay.py b/openlp/core/ui/maindisplay.py index e22b8f2ba..822181c6c 100644 --- a/openlp/core/ui/maindisplay.py +++ b/openlp/core/ui/maindisplay.py @@ -576,6 +576,7 @@ class AudioPlayer(OpenLPMixin, QtCore.QObject): self.player = QtMultimedia.QMediaPlayer() self.playlist = QtMultimedia.QMediaPlaylist(self.player) self.volume_slider = None + self.player.setPlaylist(self.playlist) self.player.positionChanged.connect(self._on_position_changed) def __del__(self): @@ -643,7 +644,7 @@ class AudioPlayer(OpenLPMixin, QtCore.QObject): if not isinstance(file_names, list): file_names = [file_names] for file_name in file_names: - self.playlist.addMedia(QtCore.QUrl(file_name)) + self.playlist.addMedia(QtMultimedia.QMediaContent(QtCore.QUrl.fromLocalFile(file_name))) def next(self): """ diff --git a/openlp/core/ui/slidecontroller.py b/openlp/core/ui/slidecontroller.py index f93c52c06..231c282ba 100644 --- a/openlp/core/ui/slidecontroller.py +++ b/openlp/core/ui/slidecontroller.py @@ -1420,7 +1420,7 @@ class SlideController(DisplayController, RegistryProperties): :param time: the time remaining """ - seconds = self.display.audio_player.media_object.remainingTime() // 1000 + seconds = (self.display.audio_player.player.duration() - self.display.audio_player.player.position()) // 1000 minutes = seconds // 60 seconds %= 60 self.audio_time_label.setText(' %02d:%02d ' % (minutes, seconds)) From 85c329fb269c4d2dc111f2fa42292011cb28f961 Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Wed, 20 Jan 2016 23:25:40 +0100 Subject: [PATCH 02/11] Workaround for windows display not updating, webkit player does not work yet. Partial fix for bug 1531319. Fixes: https://launchpad.net/bugs/1531319 --- openlp/core/ui/maindisplay.py | 9 ++++++++- openlp/core/ui/slidecontroller.py | 5 ++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/openlp/core/ui/maindisplay.py b/openlp/core/ui/maindisplay.py index 822181c6c..9a5259a5d 100644 --- a/openlp/core/ui/maindisplay.py +++ b/openlp/core/ui/maindisplay.py @@ -90,7 +90,7 @@ class Display(QtWidgets.QGraphicsView): # OpenGL. Only white blank screen is shown on the 2nd monitor all the # time. We need to investigate more how to use OpenGL properly on Mac OS # X. - if not is_macosx() and not is_win(): + if not is_macosx(): self.setViewport(QtOpenGL.QGLWidget()) def setup(self): @@ -559,6 +559,13 @@ class MainDisplay(OpenLPMixin, Display, RegistryProperties): if window_id == main_window_id: self.main_window.raise_() + def shake_web_view(self): + """ + Resizes the web_view a bit to force an update. Workaround for bug #1531319, should not be needed with PyQt 5.6. + """ + self.web_view.setGeometry(0, 0, self.width(), self.height()-1) + self.web_view.setGeometry(0, 0, self.width(), self.height()) + class AudioPlayer(OpenLPMixin, QtCore.QObject): """ diff --git a/openlp/core/ui/slidecontroller.py b/openlp/core/ui/slidecontroller.py index 231c282ba..e2f4a61aa 100644 --- a/openlp/core/ui/slidecontroller.py +++ b/openlp/core/ui/slidecontroller.py @@ -31,7 +31,7 @@ from threading import Lock from PyQt5 import QtCore, QtGui, QtWidgets from openlp.core.common import Registry, RegistryProperties, Settings, SlideLimits, UiStrings, translate, \ - RegistryMixin, OpenLPMixin + RegistryMixin, OpenLPMixin, is_win from openlp.core.lib import OpenLPToolbar, ItemCapabilities, ServiceItem, ImageSource, ServiceItemAction, \ ScreenList, build_icon, build_html from openlp.core.ui import HideMode, MainDisplay, Display, DisplayControllerType @@ -1101,6 +1101,9 @@ class SlideController(DisplayController, RegistryProperties): self.display.image(to_display) # reset the store used to display first image self.service_item.bg_image_bytes = None + # Workaround for bug #1531319, should not be needed with PyQt 5.6. + if self.is_live and is_win(): + self.display.shake_web_view() self.selected_row = row self.update_preview() self.preview_widget.change_slide(row) From 7d677025b5e9f600fd7ff7763315af2bf4475b16 Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Thu, 21 Jan 2016 22:18:56 +0100 Subject: [PATCH 03/11] Disable OpenGL on windows to make webkit player work. --- openlp/core/ui/maindisplay.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openlp/core/ui/maindisplay.py b/openlp/core/ui/maindisplay.py index 9a5259a5d..dd9de07ca 100644 --- a/openlp/core/ui/maindisplay.py +++ b/openlp/core/ui/maindisplay.py @@ -90,7 +90,7 @@ class Display(QtWidgets.QGraphicsView): # OpenGL. Only white blank screen is shown on the 2nd monitor all the # time. We need to investigate more how to use OpenGL properly on Mac OS # X. - if not is_macosx(): + if not is_macosx() and not is_win(): self.setViewport(QtOpenGL.QGLWidget()) def setup(self): From 9415018899a49d39e2262768c9cd141d9662ee38 Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Fri, 22 Jan 2016 20:52:50 +0100 Subject: [PATCH 04/11] Disable OpenGL on linux (too). Fixes bug 1535332. Fixes: https://launchpad.net/bugs/1535332 --- openlp/core/ui/maindisplay.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/openlp/core/ui/maindisplay.py b/openlp/core/ui/maindisplay.py index dd9de07ca..f27adec1b 100644 --- a/openlp/core/ui/maindisplay.py +++ b/openlp/core/ui/maindisplay.py @@ -86,12 +86,6 @@ class Display(QtWidgets.QGraphicsView): super(Display, self).__init__() self.controller = parent self.screen = {} - # FIXME: On Mac OS X (tested on 10.7) the display screen is corrupt with - # OpenGL. Only white blank screen is shown on the 2nd monitor all the - # time. We need to investigate more how to use OpenGL properly on Mac OS - # X. - if not is_macosx() and not is_win(): - self.setViewport(QtOpenGL.QGLWidget()) def setup(self): """ From 692a08f8889a37184ceeec2f7bdf20b4e7fe8f25 Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Fri, 22 Jan 2016 21:04:31 +0100 Subject: [PATCH 05/11] When setting the verseorder to uppercase, remember the cursor position. Fixes bug 1536411. Fixes: https://launchpad.net/bugs/1536411 --- openlp/plugins/songs/forms/editsongform.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openlp/plugins/songs/forms/editsongform.py b/openlp/plugins/songs/forms/editsongform.py index 33b106aa0..2ee408a3c 100644 --- a/openlp/plugins/songs/forms/editsongform.py +++ b/openlp/plugins/songs/forms/editsongform.py @@ -843,7 +843,9 @@ class EditSongForm(QtWidgets.QDialog, Ui_EditSongDialog, RegistryProperties): :param text: The text of the verse order edit (ignored). """ # First make sure that all letters entered in the verse order field are uppercase + pos = self.verse_order_edit.cursorPosition() self.verse_order_edit.setText(text.upper()) + self.verse_order_edit.setCursorPosition(pos) # Extract all verses which were used in the order. verses_in_order = self._extract_verse_order(self.verse_order_edit.text()) # Find the verses which were not used in the order. From e593d77e14e3daa7afdcfa21c9095a364b762c73 Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Fri, 22 Jan 2016 22:26:25 +0100 Subject: [PATCH 06/11] Fix some broken tests that was not being used due to naming. --- openlp/core/lib/renderer.py | 10 +++++++--- .../openlp_core_lib/test_renderer.py | 18 +++++++++--------- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/openlp/core/lib/renderer.py b/openlp/core/lib/renderer.py index 0513b70e4..97540e42d 100644 --- a/openlp/core/lib/renderer.py +++ b/openlp/core/lib/renderer.py @@ -20,6 +20,7 @@ # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### +import re from PyQt5 import QtGui, QtCore, QtWebKitWidgets @@ -441,7 +442,7 @@ class Renderer(OpenLPMixin, RegistryMixin, RegistryProperties): previous_raw = line + line_end continue # Figure out how many words of the line will fit on screen as the line will not fit as a whole. - raw_words = Renderer.words_split(line) + raw_words = words_split(line) html_words = list(map(expand_tags, raw_words)) previous_html, previous_raw = \ self._binary_chop(formatted, previous_html, previous_raw, html_words, raw_words, ' ', line_end) @@ -528,8 +529,7 @@ def words_split(line): :param line: Line to be split """ # this parse we are to be wordy - line = line.replace('\n', ' ') - return line.split(' ') + return re.split('\s+', line) def get_start_tags(raw_text): @@ -548,11 +548,15 @@ def get_start_tags(raw_text): raw_tags = [] html_tags = [] for tag in FormattingTags.get_html_tags(): + print('looking at tag...') if tag['start tag'] == '{br}': continue if raw_text.count(tag['start tag']) != raw_text.count(tag['end tag']): + print('should append') raw_tags.append((raw_text.find(tag['start tag']), tag['start tag'], tag['end tag'])) html_tags.append((raw_text.find(tag['start tag']), tag['start html'])) + print(raw_tags) + print(html_tags) # Sort the lists, so that the tags which were opened first on the first slide (the text we are checking) will be # opened first on the next slide as well. raw_tags.sort(key=lambda tag: tag[0]) diff --git a/tests/functional/openlp_core_lib/test_renderer.py b/tests/functional/openlp_core_lib/test_renderer.py index 2c1273480..dba3c9902 100644 --- a/tests/functional/openlp_core_lib/test_renderer.py +++ b/tests/functional/openlp_core_lib/test_renderer.py @@ -27,7 +27,8 @@ from unittest import TestCase from PyQt5 import QtCore from openlp.core.common import Registry -from openlp.core.lib import Renderer, ScreenList, ServiceItem +from openlp.core.lib import Renderer, ScreenList, ServiceItem, FormattingTags +from openlp.core.lib.renderer import words_split, get_start_tags from tests.functional import MagicMock @@ -71,34 +72,33 @@ class TestRenderer(TestCase): self.assertEqual(renderer.screen_ratio, 0.75, 'The base renderer should be a live controller') self.assertEqual(renderer.footer_start, 691, 'The base renderer should be a live controller') - def _get_start_tags_test(self): + def get_start_tags_test(self): """ - Test the _get_start_tags() method + Test the get_start_tags() method """ # GIVEN: A new renderer instance. Broken raw_text (missing closing tags). - renderer = Renderer() given_raw_text = '{st}{r}Text text text' expected_tuple = ('{st}{r}Text text text{/r}{/st}', '{st}{r}', '') + FormattingTags.load_tags() # WHEN: The renderer converts the start tags - result = renderer._get_start_tags(given_raw_text) + result = get_start_tags(given_raw_text) # THEN: Check if the correct tuple is returned. self.assertEqual(result, expected_tuple), 'A tuple should be returned containing the text with correct ' \ 'tags, the opening tags, and the opening html tags.' - def _word_split_test(self): + def word_split_test(self): """ - Test the _word_split() method + Test the word_split() method """ # GIVEN: A line of text - renderer = Renderer() given_line = 'beginning asdf \n end asdf' expected_words = ['beginning', 'asdf', 'end', 'asdf'] # WHEN: Split the line based on word split rules - result_words = renderer._words_split(given_line) + result_words = words_split(given_line) # THEN: The word lists should be the same. self.assertListEqual(result_words, expected_words) From 4594fcefbd259531fc73a1c4310f18f290e0dd2d Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Fri, 22 Jan 2016 22:33:20 +0100 Subject: [PATCH 07/11] pep fixes --- openlp/core/ui/maindisplay.py | 4 ++-- openlp/core/ui/slidecontroller.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/openlp/core/ui/maindisplay.py b/openlp/core/ui/maindisplay.py index f27adec1b..a16c7c6c0 100644 --- a/openlp/core/ui/maindisplay.py +++ b/openlp/core/ui/maindisplay.py @@ -555,9 +555,9 @@ class MainDisplay(OpenLPMixin, Display, RegistryProperties): def shake_web_view(self): """ - Resizes the web_view a bit to force an update. Workaround for bug #1531319, should not be needed with PyQt 5.6. + Resizes the web_view a bit to force an update. Workaround for bug #1531319, should not be needed with PyQt 5.6. """ - self.web_view.setGeometry(0, 0, self.width(), self.height()-1) + self.web_view.setGeometry(0, 0, self.width(), self.height() - 1) self.web_view.setGeometry(0, 0, self.width(), self.height()) diff --git a/openlp/core/ui/slidecontroller.py b/openlp/core/ui/slidecontroller.py index c1c291580..bed5d07c4 100644 --- a/openlp/core/ui/slidecontroller.py +++ b/openlp/core/ui/slidecontroller.py @@ -1101,7 +1101,7 @@ class SlideController(DisplayController, RegistryProperties): self.display.image(to_display) # reset the store used to display first image self.service_item.bg_image_bytes = None - # Workaround for bug #1531319, should not be needed with PyQt 5.6. + # Workaround for bug #1531319, should not be needed with PyQt 5.6. if self.is_live and is_win(): self.display.shake_web_view() self.selected_row = row From c34bfd6d951a464d76a878c1c6bb08e083419eb4 Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Sat, 23 Jan 2016 09:15:37 +0100 Subject: [PATCH 08/11] Adjusted string --- openlp/core/common/uistrings.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openlp/core/common/uistrings.py b/openlp/core/common/uistrings.py index 3f221ab08..33ebb0a5b 100644 --- a/openlp/core/common/uistrings.py +++ b/openlp/core/common/uistrings.py @@ -122,8 +122,8 @@ class UiStrings(object): self.Projectors = translate('OpenLP.Ui', 'Projectors', 'Plural') self.ReplaceBG = translate('OpenLP.Ui', 'Replace Background') self.ReplaceLiveBG = translate('OpenLP.Ui', 'Replace live background.') - self.ReplaceLiveBGDisabled = translate('OpenLP.Ui', 'Replace live background is not available on this ' - 'platform in this version of OpenLP.') + self.ReplaceLiveBGDisabled = translate('OpenLP.Ui', 'Replace live background is not available when the WebKit ' + 'player is disabled.') self.ResetBG = translate('OpenLP.Ui', 'Reset Background') self.ResetLiveBG = translate('OpenLP.Ui', 'Reset live background.') self.Seconds = translate('OpenLP.Ui', 's', 'The abbreviated unit for seconds') From c1108b1593d631984edbcb4ef1ad0bac34ec8f8e Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Sat, 23 Jan 2016 09:19:12 +0100 Subject: [PATCH 09/11] Fix traceback where OpenSong importer crashed if non-numbers were in the CCLI field. --- .../plugins/songs/lib/importers/opensong.py | 1 + .../songs/test_opensongimport.py | 2 + tests/resources/opensongsongs/Amazing Grace2 | 56 +++++++++++++++++++ 3 files changed, 59 insertions(+) create mode 100644 tests/resources/opensongsongs/Amazing Grace2 diff --git a/openlp/plugins/songs/lib/importers/opensong.py b/openlp/plugins/songs/lib/importers/opensong.py index b051af914..3c0644ff6 100644 --- a/openlp/plugins/songs/lib/importers/opensong.py +++ b/openlp/plugins/songs/lib/importers/opensong.py @@ -157,6 +157,7 @@ class OpenSongImport(SongImport): if isinstance(fn_or_string, str): if attr in ['ccli']: if ustring: + ustring = ''.join(re.findall('\d+', ustring)) setattr(self, fn_or_string, int(ustring)) else: setattr(self, fn_or_string, None) diff --git a/tests/functional/openlp_plugins/songs/test_opensongimport.py b/tests/functional/openlp_plugins/songs/test_opensongimport.py index 43eb89f01..b6514532c 100644 --- a/tests/functional/openlp_plugins/songs/test_opensongimport.py +++ b/tests/functional/openlp_plugins/songs/test_opensongimport.py @@ -52,6 +52,8 @@ class TestOpenSongFileImport(SongImportTestHelper): self.load_external_result_data(os.path.join(TEST_PATH, 'Beautiful Garden Of Prayer.json'))) self.file_import([os.path.join(TEST_PATH, 'One, Two, Three, Four, Five')], self.load_external_result_data(os.path.join(TEST_PATH, 'One, Two, Three, Four, Five.json'))) + self.file_import([os.path.join(TEST_PATH, 'Amazing Grace2')], + self.load_external_result_data(os.path.join(TEST_PATH, 'Amazing Grace.json'))) class TestOpenSongImport(TestCase): diff --git a/tests/resources/opensongsongs/Amazing Grace2 b/tests/resources/opensongsongs/Amazing Grace2 new file mode 100644 index 000000000..c14ba8fa9 --- /dev/null +++ b/tests/resources/opensongsongs/Amazing Grace2 @@ -0,0 +1,56 @@ + + + Amazing Grace (Demonstration) + John Newton, Edwin Excell & John P. Rees + Public Domain + V1 V2 V3 V4 V5 + + + CC: 22025 number + God: Assurance/Grace/Salvation + Worship: Praise + + + + [V] +;Test the chords format +;Chords beging with . +;Verses begin with their verse number +;Link words with _ +;Comments begin with ; +. D D7 G D +1A______ma________zing grace! How sweet the sound! +2'Twas grace that taught my heart to fear, +3The Lord has pro____mised good to me, +4Thro' ma________ny dan____gers, toils and snares +5When we've been there ten thou__sand years, + +. Bm E A A7 +1That saved a wretch like me! +2And grace my fears re___lieved. +3His Word my hope se___cures. +4I have al___rea____dy come. +5Bright shi___ning as the sun, + +. D D7 G D +1I once was lost, but now am found; +2How pre___cious did that grace ap____pear, +3He will my shield and por___tion be +4'Tis grace that brought me safe thus far, +5We've no less days to sing God's praise, + +. Bm A G D +1Was blind, but now I see. +2The hour I first be_lieved. +3As long as life en_dures. +4And grace will lead me home. +5Than when we first be_gun. + + + Demonstration Songs 0 + + + + + + \ No newline at end of file From f61ac941d0112bb5a79baedfd530910a6b66d372 Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Sat, 23 Jan 2016 10:53:34 +0100 Subject: [PATCH 10/11] Mock FormattingTags in test, instead of loading all tags. --- tests/functional/openlp_core_lib/test_renderer.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/tests/functional/openlp_core_lib/test_renderer.py b/tests/functional/openlp_core_lib/test_renderer.py index dba3c9902..697c8ae85 100644 --- a/tests/functional/openlp_core_lib/test_renderer.py +++ b/tests/functional/openlp_core_lib/test_renderer.py @@ -30,7 +30,7 @@ from openlp.core.common import Registry from openlp.core.lib import Renderer, ScreenList, ServiceItem, FormattingTags from openlp.core.lib.renderer import words_split, get_start_tags -from tests.functional import MagicMock +from tests.functional import MagicMock, patch SCREEN = { 'primary': False, @@ -72,7 +72,8 @@ class TestRenderer(TestCase): self.assertEqual(renderer.screen_ratio, 0.75, 'The base renderer should be a live controller') self.assertEqual(renderer.footer_start, 691, 'The base renderer should be a live controller') - def get_start_tags_test(self): + @patch('openlp.core.lib.renderer.FormattingTags.get_html_tags') + def get_start_tags_test(self, mocked_get_html_tags): """ Test the get_start_tags() method """ @@ -80,7 +81,12 @@ class TestRenderer(TestCase): given_raw_text = '{st}{r}Text text text' expected_tuple = ('{st}{r}Text text text{/r}{/st}', '{st}{r}', '') - FormattingTags.load_tags() + mocked_get_html_tags.return_value = [{'temporary': False, 'end tag': '{/r}', 'desc': 'Red', + 'start html': '', + 'end html': '', 'start tag': '{r}', 'protected': True}, + {'temporary': False, 'end tag': '{/st}', 'desc': 'Bold', + 'start html': '', 'end html': '', 'start tag': '{st}', + 'protected': True}] # WHEN: The renderer converts the start tags result = get_start_tags(given_raw_text) From fb048130885b4afb630c126b32991eca0739cded Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Sat, 23 Jan 2016 13:38:08 +0100 Subject: [PATCH 11/11] remove debug prints --- openlp/core/lib/renderer.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/openlp/core/lib/renderer.py b/openlp/core/lib/renderer.py index 97540e42d..f76d28853 100644 --- a/openlp/core/lib/renderer.py +++ b/openlp/core/lib/renderer.py @@ -548,15 +548,11 @@ def get_start_tags(raw_text): raw_tags = [] html_tags = [] for tag in FormattingTags.get_html_tags(): - print('looking at tag...') if tag['start tag'] == '{br}': continue if raw_text.count(tag['start tag']) != raw_text.count(tag['end tag']): - print('should append') raw_tags.append((raw_text.find(tag['start tag']), tag['start tag'], tag['end tag'])) html_tags.append((raw_text.find(tag['start tag']), tag['start html'])) - print(raw_tags) - print(html_tags) # Sort the lists, so that the tags which were opened first on the first slide (the text we are checking) will be # opened first on the next slide as well. raw_tags.sort(key=lambda tag: tag[0])