Merge lp:~trb143/openlp/splitter into lp:openlp

Proposed by Tim Bentley
Status: Merged
Merged at revision: 2777
Proposed branch: lp:~trb143/openlp/splitter
Merge into: lp:openlp
Diff against target: 412 lines (+122/-60)
10 files modified
openlp/core/common/uistrings.py (+1/-1)
openlp/core/lib/renderer.py (+3/-0)
openlp/core/ui/lib/listpreviewwidget.py (+5/-5)
openlp/plugins/songs/forms/duplicatesongremovalform.py (+1/-2)
openlp/plugins/songs/forms/editversedialog.py (+13/-6)
openlp/plugins/songs/forms/editverseform.py (+24/-9)
openlp/plugins/songs/lib/__init__.py (+34/-33)
openlp/plugins/songs/lib/mediaitem.py (+7/-3)
openlp/plugins/songs/lib/openlyricsxml.py (+6/-1)
tests/functional/openlp_plugins/songs/test_editverseform.py (+28/-0)
To merge this branch: bzr merge lp:~trb143/openlp/splitter
Reviewer Review Type Date Requested Status
Raoul Snyman Approve
Tomas Groth Pending
Review via email: mp+331629@code.launchpad.net

This proposal supersedes a proposal from 2017-09-30.

Description of the change

Add option to add a split to a song
This will split the verse when added to the service but keep the verse together for editing.
Useful for the 10 line hymn verses which need 2 slides to display.

Fix some iffy spelling

lp:~trb143/openlp/splitter (revision 2738)
[SUCCESS] https://ci.openlp.io/job/Branch-01-Pull/2182/
[SUCCESS] https://ci.openlp.io/job/Branch-02-Functional-Tests/2085/
[SUCCESS] https://ci.openlp.io/job/Branch-03-Interface-Tests/1972/
[SUCCESS] https://ci.openlp.io/job/Branch-04a-Code_Analysis/1342/
[SUCCESS] https://ci.openlp.io/job/Branch-04b-Test_Coverage/1178/
[SUCCESS] https://ci.openlp.io/job/Branch-04c-Code_Analysis2/308/
[FAILURE] https://ci.openlp.io/job/Branch-05-AppVeyor-Tests/150/

To post a comment you must log in.
Revision history for this message
Raoul Snyman (raoul-snyman) wrote : Posted in a previous version of this proposal

As per IRC, mrs_fly's suggestion was "Auto Split" and "Force Split". I'm going to e-mail the mailing list and see what others think.

Revision history for this message
Tomas Groth (tomasgroth) wrote : Posted in a previous version of this proposal

The openlyrics export does handle the new spilt, which I believe it should. The import should of course also be able to restore it. I'll admit I'm not sure how it should be done...

review: Needs Fixing
Revision history for this message
Raoul Snyman (raoul-snyman) wrote : Posted in a previous version of this proposal

Let's call the buttons "Overflow Split" and "Forced Split"

Revision history for this message
Tomas Groth (tomasgroth) wrote : Posted in a previous version of this proposal

The openlyrics import/export still needs to handle the new spilt...

review: Needs Fixing
Revision history for this message
Raoul Snyman (raoul-snyman) wrote :

I would prefer a different splitter, but that is just personal preference. Other than that, this looks fine to me.

Also, I'm not entirely sure that the <p> tag is a valid element in OpenLyrics, but let's roll with it and we can always sort out OpenLyrics later.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'openlp/core/common/uistrings.py'
--- openlp/core/common/uistrings.py 2017-09-06 21:36:31 +0000
+++ openlp/core/common/uistrings.py 2017-10-01 20:11:51 +0000
@@ -147,7 +147,7 @@
147 self.SaveService = translate('OpenLP.Ui', 'Save Service')147 self.SaveService = translate('OpenLP.Ui', 'Save Service')
148 self.Service = translate('OpenLP.Ui', 'Service')148 self.Service = translate('OpenLP.Ui', 'Service')
149 self.ShortResults = translate('OpenLP.Ui', 'Please type more text to use \'Search As You Type\'')149 self.ShortResults = translate('OpenLP.Ui', 'Please type more text to use \'Search As You Type\'')
150 self.Split = translate('OpenLP.Ui', 'Optional &Split')150 self.Split = translate('OpenLP.Ui', 'Overflow &Split')
151 self.SplitToolTip = translate('OpenLP.Ui',151 self.SplitToolTip = translate('OpenLP.Ui',
152 'Split a slide into two only if it does not fit on the screen as one slide.')152 'Split a slide into two only if it does not fit on the screen as one slide.')
153 self.StartingImport = translate('OpenLP.Ui', 'Starting import...')153 self.StartingImport = translate('OpenLP.Ui', 'Starting import...')
154154
=== modified file 'openlp/core/lib/renderer.py'
--- openlp/core/lib/renderer.py 2017-09-26 16:39:13 +0000
+++ openlp/core/lib/renderer.py 2017-10-01 20:11:51 +0000
@@ -243,6 +243,9 @@
243 elif item.is_capable(ItemCapabilities.CanSoftBreak):243 elif item.is_capable(ItemCapabilities.CanSoftBreak):
244 pages = []244 pages = []
245 if '[---]' in text:245 if '[---]' in text:
246 # Remove Overflow split if at start of the text
247 if text.startswith('[---]'):
248 text = text[5:]
246 # Remove two or more option slide breaks next to each other (causing infinite loop).249 # Remove two or more option slide breaks next to each other (causing infinite loop).
247 while '\n[---]\n[---]\n' in text:250 while '\n[---]\n[---]\n' in text:
248 text = text.replace('\n[---]\n[---]\n', '\n[---]\n')251 text = text.replace('\n[---]\n[---]\n', '\n[---]\n')
249252
=== modified file 'openlp/core/ui/lib/listpreviewwidget.py'
--- openlp/core/ui/lib/listpreviewwidget.py 2016-12-31 11:01:36 +0000
+++ openlp/core/ui/lib/listpreviewwidget.py 2017-10-01 20:11:51 +0000
@@ -209,21 +209,21 @@
209 Switches to the given row.209 Switches to the given row.
210 """210 """
211 # Retrieve setting211 # Retrieve setting
212 autoscrolling = Settings().value('advanced/autoscrolling')212 auto_scrolling = Settings().value('advanced/autoscrolling')
213 # Check if auto-scroll disabled (None) and validate value as dict containing 'dist' and 'pos'213 # Check if auto-scroll disabled (None) and validate value as dict containing 'dist' and 'pos'
214 # 'dist' represents the slide to scroll to relative to the new slide (-1 = previous, 0 = current, 1 = next)214 # 'dist' represents the slide to scroll to relative to the new slide (-1 = previous, 0 = current, 1 = next)
215 # 'pos' represents the vert position of of the slide (0 = in view, 1 = top, 2 = middle, 3 = bottom)215 # 'pos' represents the vert position of of the slide (0 = in view, 1 = top, 2 = middle, 3 = bottom)
216 if not (isinstance(autoscrolling, dict) and 'dist' in autoscrolling and 'pos' in autoscrolling and216 if not (isinstance(auto_scrolling, dict) and 'dist' in auto_scrolling and 'pos' in auto_scrolling and
217 isinstance(autoscrolling['dist'], int) and isinstance(autoscrolling['pos'], int)):217 isinstance(auto_scrolling['dist'], int) and isinstance(auto_scrolling['pos'], int)):
218 return218 return
219 # prevent scrolling past list bounds219 # prevent scrolling past list bounds
220 scroll_to_slide = slide + autoscrolling['dist']220 scroll_to_slide = slide + auto_scrolling['dist']
221 if scroll_to_slide < 0:221 if scroll_to_slide < 0:
222 scroll_to_slide = 0222 scroll_to_slide = 0
223 if scroll_to_slide >= self.slide_count():223 if scroll_to_slide >= self.slide_count():
224 scroll_to_slide = self.slide_count() - 1224 scroll_to_slide = self.slide_count() - 1
225 # Scroll to item if possible.225 # Scroll to item if possible.
226 self.scrollToItem(self.item(scroll_to_slide, 0), autoscrolling['pos'])226 self.scrollToItem(self.item(scroll_to_slide, 0), auto_scrolling['pos'])
227 self.selectRow(slide)227 self.selectRow(slide)
228228
229 def current_slide_number(self):229 def current_slide_number(self):
230230
=== modified file 'openlp/plugins/songs/forms/duplicatesongremovalform.py'
--- openlp/plugins/songs/forms/duplicatesongremovalform.py 2017-06-09 06:06:49 +0000
+++ openlp/plugins/songs/forms/duplicatesongremovalform.py 2017-10-01 20:11:51 +0000
@@ -25,14 +25,13 @@
2525
26import logging26import logging
27import multiprocessing27import multiprocessing
28import os
2928
30from PyQt5 import QtCore, QtWidgets29from PyQt5 import QtCore, QtWidgets
3130
32from openlp.core.common import Registry, RegistryProperties, translate31from openlp.core.common import Registry, RegistryProperties, translate
33from openlp.core.ui.lib.wizard import OpenLPWizard, WizardStrings32from openlp.core.ui.lib.wizard import OpenLPWizard, WizardStrings
34from openlp.plugins.songs.lib import delete_song33from openlp.plugins.songs.lib import delete_song
35from openlp.plugins.songs.lib.db import Song, MediaFile34from openlp.plugins.songs.lib.db import Song
36from openlp.plugins.songs.forms.songreviewwidget import SongReviewWidget35from openlp.plugins.songs.forms.songreviewwidget import SongReviewWidget
37from openlp.plugins.songs.lib.songcompare import songs_probably_equal36from openlp.plugins.songs.lib.songcompare import songs_probably_equal
3837
3938
=== modified file 'openlp/plugins/songs/forms/editversedialog.py'
--- openlp/plugins/songs/forms/editversedialog.py 2017-07-04 23:13:51 +0000
+++ openlp/plugins/songs/forms/editversedialog.py 2017-10-01 20:11:51 +0000
@@ -42,10 +42,14 @@
42 self.dialog_layout.addWidget(self.verse_text_edit)42 self.dialog_layout.addWidget(self.verse_text_edit)
43 self.verse_type_layout = QtWidgets.QHBoxLayout()43 self.verse_type_layout = QtWidgets.QHBoxLayout()
44 self.verse_type_layout.setObjectName('verse_type_layout')44 self.verse_type_layout.setObjectName('verse_type_layout')
45 self.split_button = QtWidgets.QPushButton(edit_verse_dialog)45 self.forced_split_button = QtWidgets.QPushButton(edit_verse_dialog)
46 self.split_button.setIcon(build_icon(':/general/general_add.png'))46 self.forced_split_button.setIcon(build_icon(':/general/general_add.png'))
47 self.split_button.setObjectName('split_button')47 self.forced_split_button.setObjectName('forced_split_button')
48 self.verse_type_layout.addWidget(self.split_button)48 self.verse_type_layout.addWidget(self.forced_split_button)
49 self.overflow_split_button = QtWidgets.QPushButton(edit_verse_dialog)
50 self.overflow_split_button.setIcon(build_icon(':/general/general_add.png'))
51 self.overflow_split_button.setObjectName('overflow_split_button')
52 self.verse_type_layout.addWidget(self.overflow_split_button)
49 self.verse_type_label = QtWidgets.QLabel(edit_verse_dialog)53 self.verse_type_label = QtWidgets.QLabel(edit_verse_dialog)
50 self.verse_type_label.setObjectName('verse_type_label')54 self.verse_type_label.setObjectName('verse_type_label')
51 self.verse_type_layout.addWidget(self.verse_type_label)55 self.verse_type_layout.addWidget(self.verse_type_label)
@@ -93,8 +97,11 @@
93 self.verse_type_combo_box.setItemText(VerseType.Intro, VerseType.translated_names[VerseType.Intro])97 self.verse_type_combo_box.setItemText(VerseType.Intro, VerseType.translated_names[VerseType.Intro])
94 self.verse_type_combo_box.setItemText(VerseType.Ending, VerseType.translated_names[VerseType.Ending])98 self.verse_type_combo_box.setItemText(VerseType.Ending, VerseType.translated_names[VerseType.Ending])
95 self.verse_type_combo_box.setItemText(VerseType.Other, VerseType.translated_names[VerseType.Other])99 self.verse_type_combo_box.setItemText(VerseType.Other, VerseType.translated_names[VerseType.Other])
96 self.split_button.setText(UiStrings().Split)100 self.overflow_split_button.setText(UiStrings().Split)
97 self.split_button.setToolTip(UiStrings().SplitToolTip)101 self.overflow_split_button.setToolTip(UiStrings().SplitToolTip)
102 self.forced_split_button.setText(translate('SongsPlugin.EditVerseForm', '&Forced Split'))
103 self.forced_split_button.setToolTip(translate('SongsPlugin.EditVerseForm', 'Split the verse when displayed '
104 'regardless of the screen size.'))
98 self.insert_button.setText(translate('SongsPlugin.EditVerseForm', '&Insert'))105 self.insert_button.setText(translate('SongsPlugin.EditVerseForm', '&Insert'))
99 self.insert_button.setToolTip(translate('SongsPlugin.EditVerseForm',106 self.insert_button.setToolTip(translate('SongsPlugin.EditVerseForm',
100 'Split a slide into two by inserting a verse splitter.'))107 'Split a slide into two by inserting a verse splitter.'))
101108
=== modified file 'openlp/plugins/songs/forms/editverseform.py'
--- openlp/plugins/songs/forms/editverseform.py 2017-06-04 12:14:23 +0000
+++ openlp/plugins/songs/forms/editverseform.py 2017-10-01 20:11:51 +0000
@@ -48,12 +48,13 @@
48 self.setupUi(self)48 self.setupUi(self)
49 self.has_single_verse = False49 self.has_single_verse = False
50 self.insert_button.clicked.connect(self.on_insert_button_clicked)50 self.insert_button.clicked.connect(self.on_insert_button_clicked)
51 self.split_button.clicked.connect(self.on_split_button_clicked)51 self.overflow_split_button.clicked.connect(self.on_overflow_split_button_clicked)
52 self.verse_text_edit.cursorPositionChanged.connect(self.on_cursor_position_changed)52 self.verse_text_edit.cursorPositionChanged.connect(self.on_cursor_position_changed)
53 self.verse_type_combo_box.currentIndexChanged.connect(self.on_verse_type_combo_box_changed)53 self.verse_type_combo_box.currentIndexChanged.connect(self.on_verse_type_combo_box_changed)
54 self.forced_split_button.clicked.connect(self.on_forced_split_button_clicked)
54 if Settings().value('songs/enable chords'):55 if Settings().value('songs/enable chords'):
55 self.transpose_down_button.clicked.connect(self.on_transepose_down_button_clicked)56 self.transpose_down_button.clicked.connect(self.on_transpose_down_button_clicked)
56 self.transpose_up_button.clicked.connect(self.on_transepose_up_button_clicked)57 self.transpose_up_button.clicked.connect(self.on_transpose_up_button_clicked)
5758
58 def insert_verse(self, verse_tag, verse_num=1):59 def insert_verse(self, verse_tag, verse_num=1):
59 """60 """
@@ -68,13 +69,27 @@
68 self.verse_text_edit.insertPlainText('---[{tag}:{number}]---\n'.format(tag=verse_tag, number=verse_num))69 self.verse_text_edit.insertPlainText('---[{tag}:{number}]---\n'.format(tag=verse_tag, number=verse_num))
69 self.verse_text_edit.setFocus()70 self.verse_text_edit.setFocus()
7071
71 def on_split_button_clicked(self):72 def on_overflow_split_button_clicked(self):
72 """73 """
73 The split button has been pressed74 The optional split button has been pressed so we need add the split
75 """
76 self._add_splitter_to_text('[---]')
77
78 def on_forced_split_button_clicked(self):
79 """
80 The force split button has been pressed so we need add the split
81 """
82 self._add_splitter_to_text('[--}{--]')
83
84 def _add_splitter_to_text(self, insert_string):
85 """
86 Add a custom splitter to the song text
87
88 :param insert_string: The string to insert
89 :return:
74 """90 """
75 text = self.verse_text_edit.toPlainText()91 text = self.verse_text_edit.toPlainText()
76 position = self.verse_text_edit.textCursor().position()92 position = self.verse_text_edit.textCursor().position()
77 insert_string = '[---]'
78 if position and text[position - 1] != '\n':93 if position and text[position - 1] != '\n':
79 insert_string = '\n' + insert_string94 insert_string = '\n' + insert_string
80 if position == len(text) or text[position] != '\n':95 if position == len(text) or text[position] != '\n':
@@ -101,7 +116,7 @@
101 """116 """
102 self.update_suggested_verse_number()117 self.update_suggested_verse_number()
103118
104 def on_transepose_up_button_clicked(self):119 def on_transpose_up_button_clicked(self):
105 """120 """
106 The transpose up button clicked121 The transpose up button clicked
107 """122 """
@@ -118,7 +133,7 @@
118 self.verse_text_edit.setFocus()133 self.verse_text_edit.setFocus()
119 self.verse_text_edit.moveCursor(QtGui.QTextCursor.End)134 self.verse_text_edit.moveCursor(QtGui.QTextCursor.End)
120135
121 def on_transepose_down_button_clicked(self):136 def on_transpose_down_button_clicked(self):
122 """137 """
123 The transpose down button clicked138 The transpose down button clicked
124 """139 """
125140
=== modified file 'openlp/plugins/songs/lib/__init__.py'
--- openlp/plugins/songs/lib/__init__.py 2017-09-30 20:16:30 +0000
+++ openlp/plugins/songs/lib/__init__.py 2017-10-01 20:11:51 +0000
@@ -546,12 +546,12 @@
546 song_plugin.manager.delete_object(Song, song_id)546 song_plugin.manager.delete_object(Song, song_id)
547547
548548
549def transpose_lyrics(lyrics, transepose_value):549def transpose_lyrics(lyrics, transpose_value):
550 """550 """
551 Transepose lyrics551 Transpose lyrics
552552
553 :param lyrcs: The lyrics to be transposed553 :param lyrics: The lyrics to be transposed
554 :param transepose_value: The value to transpose the lyrics with554 :param transpose_value: The value to transpose the lyrics with
555 :return: The transposed lyrics555 :return: The transposed lyrics
556 """556 """
557 # Split text by verse delimiter - both normal and optional557 # Split text by verse delimiter - both normal and optional
@@ -562,16 +562,17 @@
562 if verse.startswith('---[') or verse == '[---]':562 if verse.startswith('---[') or verse == '[---]':
563 transposed_lyrics += verse563 transposed_lyrics += verse
564 else:564 else:
565 transposed_lyrics += transpose_verse(verse, transepose_value, notation)565 transposed_lyrics += transpose_verse(verse, transpose_value, notation)
566 return transposed_lyrics566 return transposed_lyrics
567567
568568
569def transpose_verse(verse_text, transepose_value, notation):569def transpose_verse(verse_text, transpose_value, notation):
570 """570 """
571 Transepose lyrics571 Transpose Verse
572572
573 :param lyrcs: The lyrics to be transposed573 :param verse_text: The lyrics to be transposed
574 :param transepose_value: The value to transpose the lyrics with574 :param transpose_value: The value to transpose the lyrics with
575 :param notation: which notation to use
575 :return: The transposed lyrics576 :return: The transposed lyrics
576 """577 """
577 if '[' not in verse_text:578 if '[' not in verse_text:
@@ -589,11 +590,11 @@
589 if word == ']':590 if word == ']':
590 in_tag = False591 in_tag = False
591 transposed_lyrics += word592 transposed_lyrics += word
592 elif word == '/':593 elif word == '/' or word == '--}{--':
593 transposed_lyrics += word594 transposed_lyrics += word
594 else:595 else:
595 # This MUST be a chord596 # This MUST be a chord
596 transposed_lyrics += transpose_chord(word, transepose_value, notation)597 transposed_lyrics += transpose_chord(word, transpose_value, notation)
597 # If still inside a chord tag something is wrong!598 # If still inside a chord tag something is wrong!
598 if in_tag:599 if in_tag:
599 return verse_text600 return verse_text
@@ -629,36 +630,36 @@
629 for i in range(0, len(chord_split)):630 for i in range(0, len(chord_split)):
630 if i > 0:631 if i > 0:
631 transposed_chord += '/'632 transposed_chord += '/'
632 currentchord = chord_split[i]633 current_chord = chord_split[i]
633 if currentchord and currentchord[0] == '(':634 if current_chord and current_chord[0] == '(':
634 transposed_chord += '('635 transposed_chord += '('
635 if len(currentchord) > 1:636 if len(current_chord) > 1:
636 currentchord = currentchord[1:]637 current_chord = current_chord[1:]
637 else:638 else:
638 currentchord = ''639 current_chord = ''
639 if len(currentchord) > 0:640 if len(current_chord) > 0:
640 if len(currentchord) > 1:641 if len(current_chord) > 1:
641 if '#b'.find(currentchord[1]) == -1:642 if '#b'.find(current_chord[1]) == -1:
642 note = currentchord[0:1]643 note = current_chord[0:1]
643 rest = currentchord[1:]644 rest = current_chord[1:]
644 else:645 else:
645 note = currentchord[0:2]646 note = current_chord[0:2]
646 rest = currentchord[2:]647 rest = current_chord[2:]
647 else:648 else:
648 note = currentchord649 note = current_chord
649 rest = ''650 rest = ''
650 notenumber = notes_flat.index(note) if note not in notes_sharp else notes_sharp.index(note)651 note_number = notes_flat.index(note) if note not in notes_sharp else notes_sharp.index(note)
651 notenumber += transpose_value652 note_number += transpose_value
652 while notenumber > 11:653 while note_number > 11:
653 notenumber -= 12654 note_number -= 12
654 while notenumber < 0:655 while note_number < 0:
655 notenumber += 12656 note_number += 12
656 if i == 0:657 if i == 0:
657 current_chord = notes_sharp[notenumber] if notes_preferred[notenumber] == '#' else notes_flat[658 current_chord = notes_sharp[note_number] if notes_preferred[note_number] == '#' else notes_flat[
658 notenumber]659 note_number]
659 last_chord = current_chord660 last_chord = current_chord
660 else:661 else:
661 current_chord = notes_flat[notenumber] if last_chord not in notes_sharp else notes_sharp[notenumber]662 current_chord = notes_flat[note_number] if last_chord not in notes_sharp else notes_sharp[note_number]
662 if not (note not in notes_flat and note not in notes_sharp):663 if not (note not in notes_flat and note not in notes_sharp):
663 transposed_chord += current_chord + rest664 transposed_chord += current_chord + rest
664 else:665 else:
665666
=== modified file 'openlp/plugins/songs/lib/mediaitem.py'
--- openlp/plugins/songs/lib/mediaitem.py 2017-09-30 20:16:30 +0000
+++ openlp/plugins/songs/lib/mediaitem.py 2017-10-01 20:11:51 +0000
@@ -577,7 +577,7 @@
577 if not song.verse_order.strip():577 if not song.verse_order.strip():
578 for verse in verse_list:578 for verse in verse_list:
579 # We cannot use from_loose_input() here, because database is supposed to contain English lowercase579 # We cannot use from_loose_input() here, because database is supposed to contain English lowercase
580 # singlechar tags.580 # single char tags.
581 verse_tag = verse[0]['type']581 verse_tag = verse[0]['type']
582 verse_index = None582 verse_index = None
583 if len(verse_tag) > 1:583 if len(verse_tag) > 1:
@@ -588,7 +588,9 @@
588 verse_index = VerseType.from_tag(verse_tag)588 verse_index = VerseType.from_tag(verse_tag)
589 verse_tag = VerseType.translated_tags[verse_index].upper()589 verse_tag = VerseType.translated_tags[verse_index].upper()
590 verse_def = '{tag}{label}'.format(tag=verse_tag, label=verse[0]['label'])590 verse_def = '{tag}{label}'.format(tag=verse_tag, label=verse[0]['label'])
591 service_item.add_from_text(str(verse[1]), verse_def)591 force_verse = verse[1].split('[--}{--]\n')
592 for split_verse in force_verse:
593 service_item.add_from_text(split_verse, verse_def)
592 else:594 else:
593 # Loop through the verse list and expand the song accordingly.595 # Loop through the verse list and expand the song accordingly.
594 for order in song.verse_order.lower().split():596 for order in song.verse_order.lower().split():
@@ -603,7 +605,9 @@
603 verse_index = VerseType.from_tag(verse[0]['type'])605 verse_index = VerseType.from_tag(verse[0]['type'])
604 verse_tag = VerseType.translated_tags[verse_index]606 verse_tag = VerseType.translated_tags[verse_index]
605 verse_def = '{tag}{label}'.format(tag=verse_tag, label=verse[0]['label'])607 verse_def = '{tag}{label}'.format(tag=verse_tag, label=verse[0]['label'])
606 service_item.add_from_text(verse[1], verse_def)608 force_verse = verse[1].split('[--}{--]\n')
609 for split_verse in force_verse:
610 service_item.add_from_text(split_verse, verse_def)
607 service_item.title = song.title611 service_item.title = song.title
608 author_list = self.generate_footer(service_item, song)612 author_list = self.generate_footer(service_item, song)
609 service_item.data_string = {'title': song.search_title, 'authors': ', '.join(author_list)}613 service_item.data_string = {'title': song.search_title, 'authors': ', '.join(author_list)}
610614
=== modified file 'openlp/plugins/songs/lib/openlyricsxml.py'
--- openlp/plugins/songs/lib/openlyricsxml.py 2017-09-13 06:08:38 +0000
+++ openlp/plugins/songs/lib/openlyricsxml.py 2017-10-01 20:11:51 +0000
@@ -71,6 +71,7 @@
7171
72NAMESPACE = 'http://openlyrics.info/namespace/2009/song'72NAMESPACE = 'http://openlyrics.info/namespace/2009/song'
73NSMAP = '{{' + NAMESPACE + '}}{tag}'73NSMAP = '{{' + NAMESPACE + '}}{tag}'
74NEWPAGETAG = '<p style="page-break-after: always;"/>'
7475
7576
76class SongXML(object):77class SongXML(object):
@@ -281,7 +282,7 @@
281 tags_element = None282 tags_element = None
282 match = re.search('\{/?\w+\}', song.lyrics, re.UNICODE)283 match = re.search('\{/?\w+\}', song.lyrics, re.UNICODE)
283 if match:284 if match:
284 # Named 'format_' - 'format' is built-in fuction in Python.285 # Named 'format_' - 'format' is built-in function in Python.
285 format_ = etree.SubElement(song_xml, 'format')286 format_ = etree.SubElement(song_xml, 'format')
286 tags_element = etree.SubElement(format_, 'tags')287 tags_element = etree.SubElement(format_, 'tags')
287 tags_element.set('application', 'OpenLP')288 tags_element.set('application', 'OpenLP')
@@ -472,6 +473,7 @@
472 text = text.replace('{{/{tag}}}'.format(tag=tag), '</tag>')473 text = text.replace('{{/{tag}}}'.format(tag=tag), '</tag>')
473 # Replace \n with <br/>.474 # Replace \n with <br/>.
474 text = text.replace('\n', '<br/>')475 text = text.replace('\n', '<br/>')
476 text = text.replace('[--}{--]', NEWPAGETAG)
475 element = etree.XML('<lines>{text}</lines>'.format(text=text))477 element = etree.XML('<lines>{text}</lines>'.format(text=text))
476 verse_element.append(element)478 verse_element.append(element)
477 return element479 return element
@@ -634,6 +636,9 @@
634 if element.tail:636 if element.tail:
635 text += element.tail637 text += element.tail
636 return text638 return text
639 elif newlines and element.tag == NSMAP.format(tag='p') and 'page-break-after' in str(element.attrib):
640 text += '[--}{--]'
641 return text
637 # Start formatting tag.642 # Start formatting tag.
638 if element.tag == NSMAP.format(tag='tag'):643 if element.tag == NSMAP.format(tag='tag'):
639 text += '{{{name}}}'.format(name=element.get('name'))644 text += '{{{name}}}'.format(name=element.get('name'))
640645
=== modified file 'tests/functional/openlp_plugins/songs/test_editverseform.py'
--- tests/functional/openlp_plugins/songs/test_editverseform.py 2017-05-30 20:06:27 +0000
+++ tests/functional/openlp_plugins/songs/test_editverseform.py 2017-10-01 20:11:51 +0000
@@ -72,3 +72,31 @@
7272
73 # THEN the verse number must not be changed73 # THEN the verse number must not be changed
74 self.assertEqual(3, self.edit_verse_form.verse_number_box.value(), 'The verse number should be 3')74 self.assertEqual(3, self.edit_verse_form.verse_number_box.value(), 'The verse number should be 3')
75
76 def test_on_divide_split_button_clicked(self):
77 """
78 Test that divide adds text at the correct position
79 """
80 # GIVEN some input values
81 self.edit_verse_form.verse_type_combo_box.currentIndex = MagicMock(return_value=4)
82 self.edit_verse_form.verse_text_edit.setPlainText('Text\n')
83
84 # WHEN the method is called
85 self.edit_verse_form.on_forced_split_button_clicked()
86 # THEN the verse number must not be changed
87 self.assertEqual('[--}{--]\nText\n', self.edit_verse_form.verse_text_edit.toPlainText(),
88 'The verse number should be [--}{--]\nText\n')
89
90 def test_on_split_button_clicked(self):
91 """
92 Test that divide adds text at the correct position
93 """
94 # GIVEN some input values
95 self.edit_verse_form.verse_type_combo_box.currentIndex = MagicMock(return_value=4)
96 self.edit_verse_form.verse_text_edit.setPlainText('Text\n')
97
98 # WHEN the method is called
99 self.edit_verse_form.on_overflow_split_button_clicked()
100 # THEN the verse number must not be changed
101 self.assertEqual('[---]\nText\n', self.edit_verse_form.verse_text_edit.toPlainText(),
102 'The verse number should be [---]\nText\n')