diff --git a/openlp/core/common/settings.py b/openlp/core/common/settings.py
index 56a48319a..13ca5fb8f 100644
--- a/openlp/core/common/settings.py
+++ b/openlp/core/common/settings.py
@@ -252,7 +252,8 @@ class Settings(QtCore.QSettings):
'shortcuts/blankScreen': [QtGui.QKeySequence(QtCore.Qt.Key_Period)],
'shortcuts/collapse': [QtGui.QKeySequence(QtCore.Qt.Key_Minus)],
'shortcuts/desktopScreen': [QtGui.QKeySequence(QtCore.Qt.Key_D)],
- 'shortcuts/delete': [QtGui.QKeySequence(QtGui.QKeySequence.Delete), QtGui.QKeySequence(QtCore.Qt.Key_Delete)],
+ 'shortcuts/delete': [QtGui.QKeySequence(QtGui.QKeySequence.Delete),
+ QtGui.QKeySequence(QtCore.Qt.Key_Delete)],
'shortcuts/down': [QtGui.QKeySequence(QtCore.Qt.Key_Down)],
'shortcuts/editSong': [],
'shortcuts/escapeItem': [QtGui.QKeySequence(QtCore.Qt.Key_Escape)],
@@ -329,7 +330,8 @@ class Settings(QtCore.QSettings):
'shortcuts/moveBottom': [QtGui.QKeySequence(QtCore.Qt.Key_End)],
'shortcuts/moveDown': [QtGui.QKeySequence(QtCore.Qt.Key_PageDown)],
'shortcuts/nextTrackItem': [],
- 'shortcuts/nextItem_live': [QtGui.QKeySequence(QtCore.Qt.Key_Down), QtGui.QKeySequence(QtCore.Qt.Key_PageDown)],
+ 'shortcuts/nextItem_live': [QtGui.QKeySequence(QtCore.Qt.Key_Down),
+ QtGui.QKeySequence(QtCore.Qt.Key_PageDown)],
'shortcuts/nextItem_preview': [QtGui.QKeySequence(QtCore.Qt.Key_Down),
QtGui.QKeySequence(QtCore.Qt.Key_PageDown)],
'shortcuts/nextService': [QtGui.QKeySequence(QtCore.Qt.Key_Right)],
@@ -339,7 +341,8 @@ class Settings(QtCore.QSettings):
QtGui.QKeySequence(QtCore.Qt.ALT + QtCore.Qt.Key_F1)],
'shortcuts/openService': [],
'shortcuts/saveService': [],
- 'shortcuts/previousItem_live': [QtGui.QKeySequence(QtCore.Qt.Key_Up), QtGui.QKeySequence(QtCore.Qt.Key_PageUp)],
+ 'shortcuts/previousItem_live': [QtGui.QKeySequence(QtCore.Qt.Key_Up),
+ QtGui.QKeySequence(QtCore.Qt.Key_PageUp)],
'shortcuts/playbackPause': [],
'shortcuts/playbackPlay': [],
'shortcuts/playbackStop': [],
diff --git a/openlp/core/lib/__init__.py b/openlp/core/lib/__init__.py
index a6a3c6efe..d2192f711 100644
--- a/openlp/core/lib/__init__.py
+++ b/openlp/core/lib/__init__.py
@@ -27,6 +27,7 @@ OpenLP work.
from distutils.version import LooseVersion
import logging
import os
+import re
from PyQt5 import QtCore, QtGui, Qt, QtWidgets
@@ -258,11 +259,12 @@ def check_item_selected(list_widget, message):
return True
-def clean_tags(text):
+def clean_tags(text, chords=False):
"""
Remove Tags from text for display
:param text: Text to be cleaned
+ :param chords: Clean ChordPro tags
"""
text = text.replace('
', '\n')
text = text.replace('{br}', '\n')
@@ -270,21 +272,47 @@ def clean_tags(text):
for tag in FormattingTags.get_html_tags():
text = text.replace(tag['start tag'], '')
text = text.replace(tag['end tag'], '')
+ # Remove ChordPro tags
+ if chords:
+ text = re.sub(r'\[.+?\]', r'', text)
return text
-def expand_tags(text):
+def expand_tags(text, chords=False):
"""
Expand tags HTML for display
:param text: The text to be expanded.
+ :param chords: Convert ChordPro tags to html
"""
+ if chords:
+ text = expand_chords(text)
for tag in FormattingTags.get_html_tags():
text = text.replace(tag['start tag'], tag['start html'])
text = text.replace(tag['end tag'], tag['end html'])
return text
+def expand_chords(text):
+ """
+ Expand ChordPro tags
+
+ :param text:
+ """
+ text_lines = text.split('{br}')
+ expanded_text_lines = []
+ for line in text_lines:
+ # If a ChordPro is detected in the line, replace it with a html-span tag and wrap the line in a span tag.
+ if '[' in line and ']' in line:
+ new_line = ''
+ new_line += re.sub(r'(.*?)\[(.+?)\](.*?)', r'\1'
+ expanded_text_lines.append(new_line)
+ else:
+ expanded_text_lines.append(line)
+ return '{br}'.join(expanded_text_lines)
+
+
def create_separated_list(string_list):
"""
Returns a string that represents a join of a list of strings with a localized separator. This function corresponds
diff --git a/openlp/core/lib/renderer.py b/openlp/core/lib/renderer.py
index 74922b78d..1378b6742 100644
--- a/openlp/core/lib/renderer.py
+++ b/openlp/core/lib/renderer.py
@@ -254,11 +254,11 @@ class Renderer(OpenLPMixin, RegistryMixin, RegistryProperties):
# If there are (at least) two occurrences of [---] we use the first two slides (and neglect the last
# for now).
if len(slides) == 3:
- html_text = expand_tags('\n'.join(slides[:2]))
+ html_text = expand_tags('\n'.join(slides[:2]), item.is_capable(ItemCapabilities.HasChords))
# We check both slides to determine if the optional split is needed (there is only one optional
# split).
else:
- html_text = expand_tags('\n'.join(slides))
+ html_text = expand_tags('\n'.join(slides), item.is_capable(ItemCapabilities.HasChords))
html_text = html_text.replace('\n', ' \3', line)
+ new_line += '
')
if self._text_fits_on_slide(html_text):
# The first two optional slides fit (as a whole) on one slide. Replace the first occurrence
diff --git a/openlp/core/lib/serviceitem.py b/openlp/core/lib/serviceitem.py
index c99229f7a..a4ea2b9c1 100644
--- a/openlp/core/lib/serviceitem.py
+++ b/openlp/core/lib/serviceitem.py
@@ -34,7 +34,7 @@ import ntpath
from PyQt5 import QtGui
from openlp.core.common import RegistryProperties, Settings, translate, AppLocation, md5_hash
-from openlp.core.lib import ImageSource, build_icon, clean_tags, expand_tags, create_thumb
+from openlp.core.lib import ImageSource, build_icon, clean_tags, expand_tags, expand_chords
log = logging.getLogger(__name__)
@@ -118,6 +118,8 @@ class ItemCapabilities(object):
``HasThumbnails``
The item has related thumbnails available
+ ``HasChords``
+ The item has chords - only for songs
"""
CanPreview = 1
CanEdit = 2
@@ -140,6 +142,7 @@ class ItemCapabilities(object):
HasDisplayTitle = 19
HasNotes = 20
HasThumbnails = 21
+ HasChords = 22
class ServiceItem(RegistryProperties):
@@ -260,13 +263,16 @@ class ServiceItem(RegistryProperties):
previous_pages[verse_tag] = (slide['raw_slide'], pages)
for page in pages:
page = page.replace('
', '{br}')
- html_data = expand_tags(html.escape(page.rstrip()))
- self._display_frames.append({
+ html_data = expand_tags(html.escape(page.rstrip()), self.is_capable(ItemCapabilities.HasChords))
+ new_frame = {
'title': clean_tags(page),
- 'text': clean_tags(page.rstrip()),
+ 'text': clean_tags(page.rstrip(), self.is_capable(ItemCapabilities.HasChords)),
'html': html_data.replace(' ', ' '),
'verseTag': verse_tag
- })
+ }
+ if self.is_capable(ItemCapabilities.HasChords):
+ new_frame['chords_text'] = expand_chords(clean_tags(page.rstrip()))
+ self._display_frames.append(new_frame)
elif self.service_item_type == ServiceItemType.Image or self.service_item_type == ServiceItemType.Command:
pass
else:
diff --git a/openlp/plugins/remotes/html/stage.css b/openlp/plugins/remotes/html/stage.css
index 621722161..7444240d8 100644
--- a/openlp/plugins/remotes/html/stage.css
+++ b/openlp/plugins/remotes/html/stage.css
@@ -16,22 +16,22 @@
* with this program; if not, write to the Free Software Foundation, Inc., 59 *
* Temple Place, Suite 330, Boston, MA 02111-1307 USA *
******************************************************************************/
-
body {
background-color: black;
- font-family: sans-serif;
+ font-family: 'Arial Narrow', 'Avenir Next Condensed', sans-serif-condensed, Arial, sans-serif;
+ font-size: 4.4vw;
overflow: hidden;
}
#currentslide {
- font-size: 40pt;
- color: white;
+ font-size: 100%;
+ color: lightgray;
padding-bottom: 0px;
}
#nextslide {
- font-size: 40pt;
- color: grey;
+ font-size: 100%;
+ color: gray;
padding-top: 0px;
padding-bottom: 0px;
}
@@ -41,24 +41,90 @@ body {
}
#clock {
- font-size: 30pt;
+ font-size: 75%;
color: yellow;
text-align: right;
}
#notes {
- font-size: 36pt;
+ font-size: 90%;
color: salmon;
text-align: right;
}
+#controls {
+ display: none;
+}
+
+#chords {
+ font-size: 50%;
+ color: gray;
+ background-color: gray;
+ color: white;
+ cursor: pointer;
+}
+
+#header {
+ height: 1.4em;
+}
+
+#transpose,
+#transposevalue,
+#capodisplay {
+ display: inline-block;
+ font-size: 75%;
+ color: gray;
+ vertical-align: middle;
+}
+
+#header .button,
+#plus,
+#minus {
+ display: inline-block;
+ width: 3vw;
+ line-height: 3vw;
+ vertical-align: middle;
+ color: white;
+ background-color: gray;
+ font-size: 75%;
+ text-align: center;
+ cursor: pointer;
+}
+
#verseorder {
- font-size: 30pt;
+ font-size: 75%;
color: green;
text-align: left;
+ line-height: 1.5;
+ display: inline-block;
+ vertical-align: middle;
}
.currenttag {
- color: lightgreen;
- font-weight: bold;
+ color: lightgreen;
+ font-weight: bold;
}
+
+.chordline {
+ line-height: 2.0;
+}
+
+.chordline1 {
+ line-height: 1.0
+}
+
+.chordline span.chord span {
+ position: relative;
+}
+
+.chordline span.chord span strong {
+ position: absolute;
+ top: -1em;
+ left: 0;
+ font: 500 75% 'Arial Narrow', 'Avenir Next Condensed', sans-serif-condensed, Arial, sans-serif;
+ color: yellow;
+}
+
+.nextslide .chordline span.chord span strong {
+ color: gray;
+}
\ No newline at end of file
diff --git a/openlp/plugins/remotes/html/stage.html b/openlp/plugins/remotes/html/stage.html
index be25497bd..e3621f752 100644
--- a/openlp/plugins/remotes/html/stage.html
+++ b/openlp/plugins/remotes/html/stage.html
@@ -32,9 +32,15 @@