Made to possible to disable chord support completely. Now everything between [ and ] is considered a chord.

This commit is contained in:
Tomas Groth 2017-02-26 22:14:49 +01:00
parent aac10c5d2c
commit dbdc4a6712
17 changed files with 61 additions and 27 deletions

View File

@ -252,4 +252,5 @@ def url_get_file(callback, url, f_path, sha256=None):
os.remove(f_path) os.remove(f_path)
return True return True
__all__ = ['get_web_page'] __all__ = ['get_web_page']

View File

@ -409,7 +409,7 @@ def expand_chords(text):
new_line = '<span class="chordline firstchordline">' new_line = '<span class="chordline firstchordline">'
chords_on_prev_line = True chords_on_prev_line = True
# Matches a chord, a tail, a remainder and a line end. See expand_and_align_chords_in_line() for more info. # Matches a chord, a tail, a remainder and a line end. See expand_and_align_chords_in_line() for more info.
new_line += re.sub(r'\[(\w.*?)\]([\u0080-\uFFFF,\w]*)' new_line += re.sub(r'\[(.*?)\]([\u0080-\uFFFF,\w]*)'
'([\u0080-\uFFFF,\w,\s,\.,\,,\!,\?,\;,\:,\|,\",\',\-,\_]*)(\Z)?', '([\u0080-\uFFFF,\w,\s,\.,\,,\!,\?,\;,\:,\|,\",\',\-,\_]*)(\Z)?',
expand_and_align_chords_in_line, line) expand_and_align_chords_in_line, line)
new_line += '</span>' new_line += '</span>'
@ -493,7 +493,7 @@ def expand_chords_for_printing(text, line_split):
:param text: :param text:
:param line_split: :param line_split:
""" """
if not re.search(r'\[\w+.*?\]', text): if not re.search(r'\[.*?\]', text):
return text return text
text_lines = text.split(line_split) text_lines = text.split(line_split)
expanded_text_lines = [] expanded_text_lines = []
@ -501,7 +501,7 @@ def expand_chords_for_printing(text, line_split):
# If a ChordPro is detected in the line, build html tables. # If a ChordPro is detected in the line, build html tables.
new_line = '<table class="line" width="100%" cellpadding="0" cellspacing="0" border="0"><tr><td>' new_line = '<table class="line" width="100%" cellpadding="0" cellspacing="0" border="0"><tr><td>'
active_formatting_tags = [] active_formatting_tags = []
if re.search(r'\[\w+.*?\]', line): if re.search(r'\[.*?\]', line):
words = line.split(' ') words = line.split(' ')
in_chord = False in_chord = False
for word in words: for word in words:
@ -509,7 +509,7 @@ def expand_chords_for_printing(text, line_split):
lyrics = [] lyrics = []
new_line += '<table class="segment" cellpadding="0" cellspacing="0" border="0" align="left">' new_line += '<table class="segment" cellpadding="0" cellspacing="0" border="0" align="left">'
# If the word contains a chord, we need to handle it. # If the word contains a chord, we need to handle it.
if re.search(r'\[\w+.*?\]', word): if re.search(r'\[.*?\]', word):
chord = '' chord = ''
lyric = '' lyric = ''
# Loop over each character of the word # Loop over each character of the word

View File

@ -816,7 +816,7 @@ def build_footer_css(item, height):
def build_chords_css(): def build_chords_css():
if Settings().value('songs/mainview chords'): if Settings().value('songs/enable chords') and Settings().value('songs/mainview chords'):
chord_line_height = '2.0em' chord_line_height = '2.0em'
chords_display = 'inline' chords_display = 'inline'
first_chord_line_height = '2.1em' first_chord_line_height = '2.1em'

View File

@ -263,7 +263,6 @@ class ServiceItem(RegistryProperties):
new_frame = { new_frame = {
'title': clean_tags(page), 'title': clean_tags(page),
'text': clean_tags(page.rstrip(), True), 'text': clean_tags(page.rstrip(), True),
# 'chords_text': expand_chords(clean_tags(page.rstrip(), False), '\n'),
'chords_text': expand_chords(clean_tags(page.rstrip(), False)), 'chords_text': expand_chords(clean_tags(page.rstrip(), False)),
'html': html_data.replace('&amp;nbsp;', '&nbsp;'), 'html': html_data.replace('&amp;nbsp;', '&nbsp;'),
'printing_html': expand_tags(html.escape(page.rstrip()), True), 'printing_html': expand_tags(html.escape(page.rstrip()), True),

View File

@ -25,6 +25,9 @@ ChordPro files into the current database.
""" """
import logging import logging
import re
from openlp.core.common import Settings
from .songimport import SongImport from .songimport import SongImport
@ -77,6 +80,10 @@ class ChordProImport(SongImport):
if tag_value.lower().startswith('chorus'): if tag_value.lower().startswith('chorus'):
if current_verse.strip(): if current_verse.strip():
# Add collected verse to the lyrics # Add collected verse to the lyrics
# Strip out chords if set up to
if not Settings().value('songs/enable chords') or Settings().value(
'songs/disable chords import'):
current_verse = re.sub(r'\[.*?\]', '', current_verse)
self.add_verse(current_verse.rstrip(), current_verse_type) self.add_verse(current_verse.rstrip(), current_verse_type)
current_verse_type = 'v' current_verse_type = 'v'
current_verse = '' current_verse = ''
@ -87,12 +94,19 @@ class ChordProImport(SongImport):
current_verse_type = 'c' current_verse_type = 'c'
elif tag_name in ['end_of_chorus', 'eoc']: elif tag_name in ['end_of_chorus', 'eoc']:
# Add collected chorus to the lyrics # Add collected chorus to the lyrics
# Strip out chords if set up to
if not Settings().value('songs/enable chords') or Settings().value('songs/disable chords import'):
current_verse = re.sub(r'\[.*?\]', '', current_verse)
self.add_verse(current_verse.rstrip(), current_verse_type) self.add_verse(current_verse.rstrip(), current_verse_type)
current_verse_type = 'v' current_verse_type = 'v'
current_verse = '' current_verse = ''
elif tag_name in ['start_of_tab', 'sot']: elif tag_name in ['start_of_tab', 'sot']:
if current_verse.strip(): if current_verse.strip():
# Add collected verse to the lyrics # Add collected verse to the lyrics
# Strip out chords if set up to
if not Settings().value('songs/enable chords') or Settings().value(
'songs/disable chords import'):
current_verse = re.sub(r'\[.*?\]', '', current_verse)
self.add_verse(current_verse.rstrip(), current_verse_type) self.add_verse(current_verse.rstrip(), current_verse_type)
current_verse_type = 'v' current_verse_type = 'v'
current_verse = '' current_verse = ''
@ -103,6 +117,10 @@ class ChordProImport(SongImport):
# A new song starts below this tag # A new song starts below this tag
if self.verses and self.title: if self.verses and self.title:
if current_verse.strip(): if current_verse.strip():
# Strip out chords if set up to
if not Settings().value('songs/enable chords') or Settings().value(
'songs/disable chords import'):
current_verse = re.sub(r'\[.*?\]', '', current_verse)
self.add_verse(current_verse.rstrip(), current_verse_type) self.add_verse(current_verse.rstrip(), current_verse_type)
if not self.finish(): if not self.finish():
self.log_error(song_file.name) self.log_error(song_file.name)
@ -123,6 +141,9 @@ class ChordProImport(SongImport):
continue continue
elif line == '' and current_verse.strip() and current_verse_type != 'c': elif line == '' and current_verse.strip() and current_verse_type != 'c':
# Add collected verse to the lyrics # Add collected verse to the lyrics
# Strip out chords if set up to
if not Settings().value('songs/enable chords') or Settings().value('songs/disable chords import'):
current_verse = re.sub(r'\[.*?\]', '', current_verse)
self.add_verse(current_verse.rstrip(), current_verse_type) self.add_verse(current_verse.rstrip(), current_verse_type)
current_verse_type = 'v' current_verse_type = 'v'
current_verse = '' current_verse = ''
@ -132,6 +153,10 @@ class ChordProImport(SongImport):
else: else:
current_verse += line + '\n' current_verse += line + '\n'
if current_verse.strip(): if current_verse.strip():
# Strip out chords if set up to
if not Settings().value('songs/enable chords') or Settings().value(
'songs/disable chords import'):
current_verse = re.sub(r'\[.*?\]', '', current_verse)
self.add_verse(current_verse.rstrip(), current_verse_type) self.add_verse(current_verse.rstrip(), current_verse_type)
if not self.finish(): if not self.finish():
self.log_error(song_file.name) self.log_error(song_file.name)

View File

@ -255,7 +255,8 @@ class OpenSongImport(SongImport):
verses[verse_tag][verse_num][inst] = [] verses[verse_tag][verse_num][inst] = []
our_verse_order.append([verse_tag, verse_num, inst]) our_verse_order.append([verse_tag, verse_num, inst])
# If chords exists insert them # If chords exists insert them
if chords and not Settings().value('songs/disable chords import'): if chords and Settings().value('songs/enable chords') and not Settings().value(
'songs/disable chords import'):
offset = 0 offset = 0
for (column, chord) in chords: for (column, chord) in chords:
this_line = '{pre}[{chord}]{post}'.format(pre=this_line[:offset + column], chord=chord, this_line = '{pre}[{chord}]{post}'.format(pre=this_line[:offset + column], chord=chord,

View File

@ -22,14 +22,12 @@
""" """
The :mod:`songbeamer` module provides the functionality for importing SongBeamer songs into the OpenLP database. The :mod:`songbeamer` module provides the functionality for importing SongBeamer songs into the OpenLP database.
""" """
import chardet
import logging import logging
import os import os
import re import re
import base64 import base64
import math import math
from openlp.core.common import get_file_encoding
from openlp.plugins.songs.lib import VerseType from openlp.plugins.songs.lib import VerseType
from openlp.plugins.songs.lib.importers.songimport import SongImport from openlp.plugins.songs.lib.importers.songimport import SongImport
from openlp.core.common import Settings, is_win, is_macosx, get_file_encoding from openlp.core.common import Settings, is_win, is_macosx, get_file_encoding
@ -177,7 +175,8 @@ class SongBeamerImport(SongImport):
:param linenumber: Number of the current line :param linenumber: Number of the current line
:param line: The line of lyrics to insert chords :param line: The line of lyrics to insert chords
""" """
if self.chord_table and not Settings().value('songs/disable chords import') and line_number in self.chord_table: if self.chord_table and Settings().value('songs/enable chords') and not Settings().value(
'songs/disable chords import') and line_number in self.chord_table:
line_idx = sorted(self.chord_table[line_number].keys(), reverse=True) line_idx = sorted(self.chord_table[line_number].keys(), reverse=True)
for idx in line_idx: for idx in line_idx:
# In SongBeamer the column position of the chord can be a decimal, we just round it up. # In SongBeamer the column position of the chord can be a decimal, we just round it up.

View File

@ -126,8 +126,8 @@ class VideoPsalmImport(SongImport):
continue continue
verse_text = verse['Text'] verse_text = verse['Text']
# Strip out chords if set up to # Strip out chords if set up to
if Settings().value('songs/disable chords import'): if not Settings().value('songs/enable chords') or Settings().value('songs/disable chords import'):
verse_text = re.sub(r'\[\w.*?\]', '', verse_text) verse_text = re.sub(r'\[.*?\]', '', verse_text)
self.add_verse(verse_text, 'v') self.add_verse(verse_text, 'v')
if not self.finish(): if not self.finish():
self.log_error('Could not import {title}'.format(title=self.title)) self.log_error('Could not import {title}'.format(title=self.title))

View File

@ -625,7 +625,7 @@ class OpenLyrics(object):
# Convert chords to ChordPro format which OpenLP uses internally # Convert chords to ChordPro format which OpenLP uses internally
# TODO: Verify format() with template variables # TODO: Verify format() with template variables
elif element.tag == NSMAP % 'chord': elif element.tag == NSMAP % 'chord':
if not Settings().value('songs/disable chords import'): if Settings().value('songs/enable chords') and not Settings().value('songs/disable chords import'):
text += '[{chord}]'.format(chord=element.get('name')) text += '[{chord}]'.format(chord=element.get('name'))
if element.tail: if element.tail:
# Append tail text at chord element. # Append tail text at chord element.

View File

@ -60,19 +60,22 @@ class SongsTab(SettingsTab):
self.display_copyright_check_box.setObjectName('copyright_check_box') self.display_copyright_check_box.setObjectName('copyright_check_box')
self.mode_layout.addWidget(self.display_copyright_check_box) self.mode_layout.addWidget(self.display_copyright_check_box)
self.left_layout.addWidget(self.mode_group_box) self.left_layout.addWidget(self.mode_group_box)
# Chords group box
self.chords_group_box = QtWidgets.QGroupBox(self.left_column) self.chords_group_box = QtWidgets.QGroupBox(self.left_column)
self.chords_group_box.setObjectName('chords_group_box') self.chords_group_box.setObjectName('chords_group_box')
self.chords_group_box.setCheckable(True)
self.chords_layout = QtWidgets.QVBoxLayout(self.chords_group_box) self.chords_layout = QtWidgets.QVBoxLayout(self.chords_group_box)
self.chords_layout.setObjectName('chords_layout') self.chords_layout.setObjectName('chords_layout')
self.chords_info_label = QtWidgets.QLabel(self.chords_group_box)
self.chords_info_label.setWordWrap(True)
self.chords_layout.addWidget(self.chords_info_label)
self.mainview_chords_check_box = QtWidgets.QCheckBox(self.mode_group_box) self.mainview_chords_check_box = QtWidgets.QCheckBox(self.mode_group_box)
self.mainview_chords_check_box.setObjectName('tool_bar_active_check_box') self.mainview_chords_check_box.setObjectName('mainview_chords_check_box')
self.chords_layout.addWidget(self.mainview_chords_check_box) self.chords_layout.addWidget(self.mainview_chords_check_box)
self.disable_chords_import_check_box = QtWidgets.QCheckBox(self.mode_group_box) self.disable_chords_import_check_box = QtWidgets.QCheckBox(self.mode_group_box)
self.disable_chords_import_check_box.setObjectName('tool_bar_active_check_box') self.disable_chords_import_check_box.setObjectName('disable_chords_import_check_box')
self.chords_layout.addWidget(self.disable_chords_import_check_box) self.chords_layout.addWidget(self.disable_chords_import_check_box)
# Chords notation group box
# Chords notation
self.chord_notation_label = QtWidgets.QLabel(self.chords_group_box) self.chord_notation_label = QtWidgets.QLabel(self.chords_group_box)
self.chord_notation_label.setWordWrap(True) self.chord_notation_label.setWordWrap(True)
self.chords_layout.addWidget(self.chord_notation_label) self.chords_layout.addWidget(self.chord_notation_label)
@ -85,9 +88,7 @@ class SongsTab(SettingsTab):
self.neolatin_notation_radio_button = QtWidgets.QRadioButton(self.chords_group_box) self.neolatin_notation_radio_button = QtWidgets.QRadioButton(self.chords_group_box)
self.neolatin_notation_radio_button.setObjectName('neolatin_notation_radio_button') self.neolatin_notation_radio_button.setObjectName('neolatin_notation_radio_button')
self.chords_layout.addWidget(self.neolatin_notation_radio_button) self.chords_layout.addWidget(self.neolatin_notation_radio_button)
self.left_layout.addWidget(self.chords_group_box) self.left_layout.addWidget(self.chords_group_box)
self.left_layout.addStretch() self.left_layout.addStretch()
self.right_layout.addStretch() self.right_layout.addStretch()
self.tool_bar_active_check_box.stateChanged.connect(self.on_tool_bar_active_check_box_changed) self.tool_bar_active_check_box.stateChanged.connect(self.on_tool_bar_active_check_box_changed)
@ -115,6 +116,8 @@ class SongsTab(SettingsTab):
self.display_copyright_check_box.setText(translate('SongsPlugin.SongsTab', self.display_copyright_check_box.setText(translate('SongsPlugin.SongsTab',
'Display "{symbol}" symbol before copyright ' 'Display "{symbol}" symbol before copyright '
'info').format(symbol=SongStrings.CopyrightSymbol)) 'info').format(symbol=SongStrings.CopyrightSymbol))
self.chords_info_label.setText(translate('SongsPlugin.SongsTab', 'If enabled all text between "[" and "]" will '
'be regarded as chords.'))
self.chords_group_box.setTitle(translate('SongsPlugin.SongsTab', 'Chords')) self.chords_group_box.setTitle(translate('SongsPlugin.SongsTab', 'Chords'))
self.mainview_chords_check_box.setText(translate('SongsPlugin.SongsTab', 'Display chords in the main view')) self.mainview_chords_check_box.setText(translate('SongsPlugin.SongsTab', 'Display chords in the main view'))
self.disable_chords_import_check_box.setText(translate('SongsPlugin.SongsTab', self.disable_chords_import_check_box.setText(translate('SongsPlugin.SongsTab',
@ -170,6 +173,7 @@ class SongsTab(SettingsTab):
self.display_songbook = settings.value('display songbook') self.display_songbook = settings.value('display songbook')
self.display_written_by = settings.value('display written by') self.display_written_by = settings.value('display written by')
self.display_copyright_symbol = settings.value('display copyright symbol') self.display_copyright_symbol = settings.value('display copyright symbol')
self.enable_chords = settings.value('enable chords')
self.chord_notation = settings.value('chord notation') self.chord_notation = settings.value('chord notation')
self.mainview_chords = settings.value('mainview chords') self.mainview_chords = settings.value('mainview chords')
self.disable_chords_import = settings.value('disable chords import') self.disable_chords_import = settings.value('disable chords import')
@ -179,6 +183,7 @@ class SongsTab(SettingsTab):
self.display_songbook_check_box.setChecked(self.display_songbook) self.display_songbook_check_box.setChecked(self.display_songbook)
self.display_written_by_check_box.setChecked(self.display_written_by) self.display_written_by_check_box.setChecked(self.display_written_by)
self.display_copyright_check_box.setChecked(self.display_copyright_symbol) self.display_copyright_check_box.setChecked(self.display_copyright_symbol)
self.chords_group_box.setChecked(self.enable_chords)
self.mainview_chords_check_box.setChecked(self.mainview_chords) self.mainview_chords_check_box.setChecked(self.mainview_chords)
self.disable_chords_import_check_box.setChecked(self.disable_chords_import) self.disable_chords_import_check_box.setChecked(self.disable_chords_import)
if self.chord_notation == 'german': if self.chord_notation == 'german':
@ -198,6 +203,7 @@ class SongsTab(SettingsTab):
settings.setValue('display songbook', self.display_songbook) settings.setValue('display songbook', self.display_songbook)
settings.setValue('display written by', self.display_written_by) settings.setValue('display written by', self.display_written_by)
settings.setValue('display copyright symbol', self.display_copyright_symbol) settings.setValue('display copyright symbol', self.display_copyright_symbol)
settings.setValue('enable chords', self.chords_group_box.isChecked())
settings.setValue('mainview chords', self.mainview_chords) settings.setValue('mainview chords', self.mainview_chords)
settings.setValue('disable chords import', self.disable_chords_import) settings.setValue('disable chords import', self.disable_chords_import)
settings.setValue('chord notation', self.chord_notation) settings.setValue('chord notation', self.chord_notation)

View File

@ -67,6 +67,7 @@ __default_settings__ = {
'songs/songselect username': '', 'songs/songselect username': '',
'songs/songselect password': '', 'songs/songselect password': '',
'songs/songselect searches': '', 'songs/songselect searches': '',
'songs/enable chords': True,
'songs/chord notation': 'english', # Can be english, german or neo-latin 'songs/chord notation': 'english', # Can be english, german or neo-latin
'songs/mainview chords': False, 'songs/mainview chords': False,
'songs/disable chords import': False, 'songs/disable chords import': False,

View File

@ -1,4 +1,4 @@
[pep8] [pep8]
exclude=resources.py,vlc.py exclude=resources.py,vlc.py
max-line-length = 120 max-line-length = 120
ignore = E402 ignore = E402,E722

View File

@ -260,6 +260,7 @@ CHORD_CSS_ENABLED = """
__default_settings__ = { __default_settings__ = {
'songs/mainview chords': False, 'songs/mainview chords': False,
'songs/enable chords': True
} }
@ -460,6 +461,7 @@ class Htmbuilder(TestCase, TestMixin):
Test the build_chords_css() function Test the build_chords_css() function
""" """
# GIVEN: A setting that activates chords on the mainview # GIVEN: A setting that activates chords on the mainview
Settings().setValue('songs/enable chords', True)
Settings().setValue('songs/mainview chords', True) Settings().setValue('songs/mainview chords', True)
# WHEN: Building the chord CSS # WHEN: Building the chord CSS

View File

@ -4,7 +4,7 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2016 OpenLP Developers # # Copyright (c) 2008-2017 OpenLP Developers #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# This program is free software; you can redistribute it and/or modify it # # 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 # # under the terms of the GNU General Public License as published by the Free #
@ -38,14 +38,14 @@ class TestChordProFileImport(SongImportTestHelper):
self.importer_module_name = 'chordpro' self.importer_module_name = 'chordpro'
super(TestChordProFileImport, self).__init__(*args, **kwargs) super(TestChordProFileImport, self).__init__(*args, **kwargs)
@patch('openlp.plugins.songs.lib.importers.opensong.Settings') @patch('openlp.plugins.songs.lib.importers.chordpro.Settings')
def test_song_import(self, mocked_settings): def test_song_import(self, mocked_settings):
""" """
Test that loading an ChordPro file works correctly on various files Test that loading an ChordPro file works correctly on various files
""" """
# Mock out the settings - always return False # Mock out the settings - always return False
mocked_returned_settings = MagicMock() mocked_returned_settings = MagicMock()
mocked_returned_settings.value.return_value = False mocked_returned_settings.value.side_effect = lambda value: True if value == 'songs/enable chords' else False
mocked_settings.return_value = mocked_returned_settings mocked_settings.return_value = mocked_returned_settings
# Do the test import # Do the test import
self.file_import([os.path.join(TEST_PATH, 'swing-low.chordpro')], self.file_import([os.path.join(TEST_PATH, 'swing-low.chordpro')],

View File

@ -49,7 +49,7 @@ class TestOpenSongFileImport(SongImportTestHelper):
""" """
# Mock out the settings - always return False # Mock out the settings - always return False
mocked_returned_settings = MagicMock() mocked_returned_settings = MagicMock()
mocked_returned_settings.value.return_value = False mocked_returned_settings.value.side_effect = lambda value: True if value == 'songs/enable chords' else False
mocked_settings.return_value = mocked_returned_settings mocked_settings.return_value = mocked_returned_settings
# Do the test import # Do the test import
self.file_import([os.path.join(TEST_PATH, 'Amazing Grace')], self.file_import([os.path.join(TEST_PATH, 'Amazing Grace')],

View File

@ -49,7 +49,7 @@ class TestSongBeamerFileImport(SongImportTestHelper):
""" """
# Mock out the settings - always return False # Mock out the settings - always return False
mocked_returned_settings = MagicMock() mocked_returned_settings = MagicMock()
mocked_returned_settings.value.return_value = False mocked_returned_settings.value.side_effect = lambda value: True if value == 'songs/enable chords' else False
mocked_settings.return_value = mocked_returned_settings mocked_settings.return_value = mocked_returned_settings
self.file_import([os.path.join(TEST_PATH, 'Amazing Grace.sng')], self.file_import([os.path.join(TEST_PATH, 'Amazing Grace.sng')],
self.load_external_result_data(os.path.join(TEST_PATH, 'Amazing Grace.json'))) self.load_external_result_data(os.path.join(TEST_PATH, 'Amazing Grace.json')))

View File

@ -45,7 +45,7 @@ class TestVideoPsalmFileImport(SongImportTestHelper):
""" """
# Mock out the settings - always return False # Mock out the settings - always return False
mocked_returned_settings = MagicMock() mocked_returned_settings = MagicMock()
mocked_returned_settings.value.return_value = False mocked_returned_settings.value.side_effect = lambda value: True if value == 'songs/enable chords' else False
mocked_settings.return_value = mocked_returned_settings mocked_settings.return_value = mocked_returned_settings
# Do the test import # Do the test import
self.file_import(os.path.join(TEST_PATH, 'videopsalm-as-safe-a-stronghold.json'), self.file_import(os.path.join(TEST_PATH, 'videopsalm-as-safe-a-stronghold.json'),