This commit is contained in:
Tim Bentley 2019-08-30 10:32:05 +01:00
commit 19dfcc15aa
12 changed files with 728 additions and 644 deletions

View File

@ -17,3 +17,4 @@ include LICENSE
include README.txt include README.txt
include openlp/.version include openlp/.version
include package.json include package.json
include karma.conf.js

View File

@ -26,18 +26,21 @@ module.exports = function(config) {
// source files, that you wanna generate coverage for // source files, that you wanna generate coverage for
// do not include tests or libraries // do not include tests or libraries
// (these files will be instrumented by Istanbul) // (these files will be instrumented by Istanbul)
"display.js": ["coverage"] // "display.js": ["coverage"]
}, },
// test results reporter to use // test results reporter to use
// possible values: "dots", "progress" // possible values: "dots", "progress"
// available reporters: https://npmjs.org/browse/keyword/karma-reporter // available reporters: https://npmjs.org/browse/keyword/karma-reporter
reporters: ["progress", "coverage"], reporters: ["dots", "junit"],
// configure the coverateReporter // configure the coverateReporter
coverageReporter: { /* coverageReporter: {
type : "html", type : "html",
dir : "htmlcov/" dir : "htmlcov/"
}, */
junitReporter: {
outputFile: "test-results.xml"
}, },
// web server port // web server port
@ -60,11 +63,11 @@ module.exports = function(config) {
// start these browsers // start these browsers
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
browsers: ["Firefox"], browsers: ["Chromium"],
// Continuous Integration mode // Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits // if true, Karma captures browsers, runs the tests and exits
singleRun: false, singleRun: true,
// Concurrency level // Concurrency level
// how many browser should be started simultaneous // how many browser should be started simultaneous

View File

@ -67,7 +67,7 @@ def database_exists(url):
create_database(engine.url) create_database(engine.url)
database_exists(engine.url) #=> True database_exists(engine.url) #=> True
Borrowed from SQLAlchemy_Utils (v0.32.14 )since we only need this one function. Borrowed from SQLAlchemy_Utils (v0.32.14) since we only need this one function.
""" """
url = copy(make_url(url)) url = copy(make_url(url))

File diff suppressed because it is too large Load Diff

View File

@ -50,19 +50,20 @@ class AboutForm(QtWidgets.QDialog, UiAboutDialog):
Set up the dialog. This method is mocked out in tests. Set up the dialog. This method is mocked out in tests.
""" """
self.setup_ui(self) self.setup_ui(self)
self.button_box.buttons()[0].setFocus()
application_version = get_version() application_version = get_version()
about_text = self.about_text_edit.toPlainText() about_text = self.about_text_edit.toHtml()
about_text = about_text.replace('<version>', application_version['version']) about_text = about_text.replace('{version}', application_version['version'])
if application_version['build']: if application_version['build']:
build_text = translate('OpenLP.AboutForm', ' build {version}').format(version=application_version['build']) build_text = translate('OpenLP.AboutForm', ' build {version}').format(version=application_version['build'])
else: else:
build_text = '' build_text = ''
about_text = about_text.replace('<revision>', build_text) about_text = about_text.replace('{revision}', build_text)
self.about_text_edit.setPlainText(about_text) self.about_text_edit.setHtml(about_text)
self.volunteer_button.clicked.connect(self.on_volunteer_button_clicked) self.contribute_button.clicked.connect(self.on_contribute_button_clicked)
def on_volunteer_button_clicked(self): def on_contribute_button_clicked(self):
""" """
Launch a web browser and go to the contribute page on the site. Launch a web browser and go to the contribute page on the site.
""" """
webbrowser.open_new('http://openlp.org/en/contribute') webbrowser.open_new('http://openlp.org/contribute')

View File

@ -28,6 +28,7 @@ import re
from openlp.core.common.settings import Settings from openlp.core.common.settings import Settings
from openlp.plugins.songs.lib.importers.songimport import SongImport from openlp.plugins.songs.lib.importers.songimport import SongImport
from openlp.plugins.songs.lib.db import AuthorType
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -39,6 +40,7 @@ class ChordProImport(SongImport):
This importer is based on the information available on these webpages: This importer is based on the information available on these webpages:
- https://www.chordpro.org
- http://webchord.sourceforge.net/tech.html - http://webchord.sourceforge.net/tech.html
- http://www.vromans.org/johan/projects/Chordii/chordpro/ - http://www.vromans.org/johan/projects/Chordii/chordpro/
- http://www.tenbyten.com/software/songsgen/help/HtmlHelp/files_reference.htm - http://www.tenbyten.com/software/songsgen/help/HtmlHelp/files_reference.htm
@ -73,6 +75,29 @@ class ChordProImport(SongImport):
self.title = tag_value self.title = tag_value
elif tag_name in ['subtitle', 'su', 'st']: elif tag_name in ['subtitle', 'su', 'st']:
self.alternate_title = tag_value self.alternate_title = tag_value
elif tag_name == 'composer':
self.parse_author(tag_value, AuthorType.Music)
elif tag_name in ['lyricist', 'artist', 'author']: # author is not an official directive
self.parse_author(tag_value, AuthorType.Words)
elif tag_name == 'meta':
meta_tag_name, meta_tag_value = tag_value.split(' ', 1)
# Skip, if no value
if not meta_tag_value:
continue
# The meta-tag can contain anything. We check for the ones above and a few more
if meta_tag_name in ['title', 't']:
self.title = meta_tag_value
elif meta_tag_name in ['subtitle', 'su', 'st']:
self.alternate_title = meta_tag_value
elif meta_tag_name == 'composer':
self.parse_author(meta_tag_value, AuthorType.Music)
elif meta_tag_name in ['lyricist', 'artist', 'author']:
self.parse_author(meta_tag_value, AuthorType.Words)
elif meta_tag_name in ['topic', 'topics']:
for topic in meta_tag_value.split(','):
self.topics.append(topic.strip())
elif 'ccli' in meta_tag_name:
self.ccli_number = meta_tag_value
elif tag_name in ['comment', 'c', 'comment_italic', 'ci', 'comment_box', 'cb']: elif tag_name in ['comment', 'c', 'comment_italic', 'ci', 'comment_box', 'cb']:
# Detect if the comment is used as a chorus repeat marker # Detect if the comment is used as a chorus repeat marker
if tag_value.lower().startswith('chorus'): if tag_value.lower().startswith('chorus'):
@ -156,6 +181,13 @@ class ChordProImport(SongImport):
'songs/disable chords import'): 'songs/disable chords import'):
current_verse = re.sub(r'\[.*?\]', '', current_verse) 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 no title was in directives, get it from the first line
if not self.title:
(verse_def, verse_text, lang) = self.verses[0]
# strip any chords from the title
self.title = re.sub(r'\[.*?\]', '', verse_text.split('\n')[0])
# strip the last char if it a punctuation
self.title = re.sub(r'[^\w\s]$', '', self.title)
if not self.finish(): if not self.finish():
self.log_error(song_file.name) self.log_error(song_file.name)

View File

@ -9,9 +9,11 @@
"dependencies": { "dependencies": {
"jasmine-core": "^2.6.4", "jasmine-core": "^2.6.4",
"karma": "^3.1.4", "karma": "^3.1.4",
"karma-chrome-launcher": "^3.1.0",
"karma-coverage": "^1.1.2", "karma-coverage": "^1.1.2",
"karma-jasmine": "^1.1.0",
"karma-firefox-launcher": "^1.2.0", "karma-firefox-launcher": "^1.2.0",
"karma-jasmine": "^1.1.0",
"karma-junit-reporter": "^1.2.0",
"karma-log-reporter": "0.0.4" "karma-log-reporter": "0.0.4"
}, },
"scripts": { "scripts": {

View File

@ -97,7 +97,7 @@ MODULES = [
OPTIONAL_MODULES = [ OPTIONAL_MODULES = [
('qdarkstyle', '(dark style support)'), ('qdarkstyle', '(dark style support)'),
('mysql.connector', '(MySQL support)'), ('pymysql', '(MySQL support)'),
('pyodbc', '(ODBC support)'), ('pyodbc', '(ODBC support)'),
('psycopg2', '(PostgreSQL support)'), ('psycopg2', '(PostgreSQL support)'),
('enchant', '(spell checker)'), ('enchant', '(spell checker)'),

View File

@ -191,7 +191,7 @@ using a computer and a data projector.""",
extras_require={ extras_require={
'agpl-pdf': ['PyMuPDF'], 'agpl-pdf': ['PyMuPDF'],
'darkstyle': ['QDarkStyle'], 'darkstyle': ['QDarkStyle'],
'mysql': ['mysql-connector-python'], 'mysql': ['pymysql'],
'odbc': ['pyodbc'], 'odbc': ['pyodbc'],
'postgresql': ['psycopg2'], 'postgresql': ['psycopg2'],
'spellcheck': ['pyenchant >= 1.6'], 'spellcheck': ['pyenchant >= 1.6'],

View File

@ -30,10 +30,10 @@ from openlp.core.ui.aboutform import AboutForm
from tests.helpers.testmixin import TestMixin from tests.helpers.testmixin import TestMixin
class TestFirstTimeForm(TestCase, TestMixin): class TestAboutForm(TestCase, TestMixin):
@patch('openlp.core.ui.aboutform.webbrowser') @patch('openlp.core.ui.aboutform.webbrowser')
def test_on_volunteer_button_clicked(self, mocked_webbrowser): def test_on_contribute_button_clicked(self, mocked_webbrowser):
""" """
Test that clicking on the "Volunteer" button opens a web page. Test that clicking on the "Volunteer" button opens a web page.
""" """
@ -41,10 +41,10 @@ class TestFirstTimeForm(TestCase, TestMixin):
about_form = AboutForm(None) about_form = AboutForm(None)
# WHEN: The "Volunteer" button is "clicked" # WHEN: The "Volunteer" button is "clicked"
about_form.on_volunteer_button_clicked() about_form.on_contribute_button_clicked()
# THEN: A web browser is opened # THEN: A web browser is opened
mocked_webbrowser.open_new.assert_called_with('http://openlp.org/en/contribute') mocked_webbrowser.open_new.assert_called_with('http://openlp.org/contribute')
@patch('openlp.core.ui.aboutform.get_version') @patch('openlp.core.ui.aboutform.get_version')
def test_about_form_build_number(self, mocked_get_version): def test_about_form_build_number(self, mocked_get_version):
@ -66,11 +66,11 @@ class TestFirstTimeForm(TestCase, TestMixin):
Test that the copyright date is included correctly Test that the copyright date is included correctly
""" """
# GIVEN: A correct application date # GIVEN: A correct application date
date_string = "2004-%s" % datetime.date.today().year date_string = '2004-{year}'.format(year=datetime.date.today().year)
# WHEN: The about form is created # WHEN: The about form is created
about_form = AboutForm(None) about_form = AboutForm(None)
license_text = about_form.license_text_edit.toPlainText() about_text = about_form.about_text_edit.toPlainText()
# THEN: The date should be in the text twice. # THEN: The date should be in the text twice.
assert license_text.count(date_string, 0) == 2, "The text string should be added twice to the license string" assert about_text.count(date_string, 0) == 1, "The text string should be added twice to the license string"

View File

@ -1,5 +1,7 @@
{title:Swing Low Sweet Chariot} {title:Swing Low Sweet Chariot}
{st:Traditional} {st:Traditional}
{lyricist:Wallis Willis}
{meta:composer Wallis Willis}
{start_of_chorus} {start_of_chorus}
Swing [D]low, sweet [G]chari[D]ot, Swing [D]low, sweet [G]chari[D]ot,

View File

@ -1,6 +1,10 @@
{ {
"title": "Swing Low Sweet Chariot", "title": "Swing Low Sweet Chariot",
"alternative_title": "Traditional", "alternative_title": "Traditional",
"authors": [
["Wallis Willis", "words"],
["Wallis Willis", "music"]
],
"verses": [ "verses": [
[ [
"Swing [D]low, sweet [G]chari[D]ot,\nComin' for to carry me [A7]home.\nSwing [D7]low, sweet [G]chari[D]ot,\nComin' for to [A7]carry me [D]home.", "Swing [D]low, sweet [G]chari[D]ot,\nComin' for to carry me [A7]home.\nSwing [D7]low, sweet [G]chari[D]ot,\nComin' for to [A7]carry me [D]home.",