").attr("value", parseInt(idx, 10)).text(text));
li.attr("uuid", value["id"])
li.children("a").click(OpenLP.setItem);
ul.append(li);
@@ -98,8 +102,8 @@ window.OpenLP = {
} else {
text += slide["text"];
}
- if (slide["notes"]) {
- text += ("" + slide["notes"] + "
");
+ if (slide["slide_notes"]) {
+ text += ("" + slide["slide_notes"] + "
");
}
text = text.replace(/\n/g, '
');
if (slide["img"]) {
diff --git a/openlp/plugins/remotes/html/stage.js b/openlp/plugins/remotes/html/stage.js
index e63025b80..4834b4664 100644
--- a/openlp/plugins/remotes/html/stage.js
+++ b/openlp/plugins/remotes/html/stage.js
@@ -114,8 +114,8 @@ window.OpenLP = {
text += "
![](" + slide["img"].replace("/thumbnails/", "/thumbnails320x240/") + ")
";
}
// use notes if available
- if (slide["notes"]) {
- text += '
' + slide["notes"];
+ if (slide["slide_notes"]) {
+ text += '
' + slide["slide_notes"];
}
text = text.replace(/\n/g, "
");
$("#currentslide").html(text);
diff --git a/openlp/plugins/remotes/lib/httprouter.py b/openlp/plugins/remotes/lib/httprouter.py
index 22e2495c0..1313c9f9c 100644
--- a/openlp/plugins/remotes/lib/httprouter.py
+++ b/openlp/plugins/remotes/lib/httprouter.py
@@ -521,7 +521,7 @@ class HttpRouter(RegistryProperties):
if current_item.is_capable(ItemCapabilities.HasDisplayTitle):
item['title'] = str(frame['display_title'])
if current_item.is_capable(ItemCapabilities.HasNotes):
- item['notes'] = str(frame['notes'])
+ item['slide_notes'] = str(frame['notes'])
if current_item.is_capable(ItemCapabilities.HasThumbnails) and \
Settings().value('remotes/thumbnails'):
# If the file is under our app directory tree send the portion after the match
@@ -531,8 +531,6 @@ class HttpRouter(RegistryProperties):
item['text'] = str(frame['title'])
item['html'] = str(frame['title'])
item['selected'] = (self.live_controller.selected_row == index)
- if current_item.notes:
- item['notes'] = item.get('notes', '') + '\n' + current_item.notes
data.append(item)
json_data = {'results': {'slides': data}}
if current_item:
diff --git a/openlp/plugins/songs/lib/upgrade.py b/openlp/plugins/songs/lib/upgrade.py
index 5b7255266..b8945f8a9 100644
--- a/openlp/plugins/songs/lib/upgrade.py
+++ b/openlp/plugins/songs/lib/upgrade.py
@@ -32,10 +32,11 @@ backend for the Songs plugin
"""
import logging
-from sqlalchemy import Column, ForeignKey, types
+from sqlalchemy import Table, Column, ForeignKey, types
from sqlalchemy.sql.expression import func, false, null, text
from openlp.core.lib.db import get_upgrade_op
+from openlp.core.common import trace_error_handler
log = logging.getLogger(__name__)
__version__ = 4
@@ -57,12 +58,16 @@ def upgrade_1(session, metadata):
:param metadata:
"""
op = get_upgrade_op(session)
- op.drop_table('media_files_songs')
- op.add_column('media_files', Column('song_id', types.Integer(), server_default=null()))
- op.add_column('media_files', Column('weight', types.Integer(), server_default=text('0')))
- if metadata.bind.url.get_dialect().name != 'sqlite':
- # SQLite doesn't support ALTER TABLE ADD CONSTRAINT
- op.create_foreign_key('fk_media_files_song_id', 'media_files', 'songs', ['song_id', 'id'])
+ songs_table = Table('songs', metadata, autoload=True)
+ if 'media_files_songs' in [t.name for t in metadata.tables.values()]:
+ op.drop_table('media_files_songs')
+ op.add_column('media_files', Column('song_id', types.Integer(), server_default=null()))
+ op.add_column('media_files', Column('weight', types.Integer(), server_default=text('0')))
+ if metadata.bind.url.get_dialect().name != 'sqlite':
+ # SQLite doesn't support ALTER TABLE ADD CONSTRAINT
+ op.create_foreign_key('fk_media_files_song_id', 'media_files', 'songs', ['song_id', 'id'])
+ else:
+ log.warning('Skipping upgrade_1 step of upgrading the song db')
def upgrade_2(session, metadata):
@@ -72,8 +77,12 @@ def upgrade_2(session, metadata):
This upgrade adds a create_date and last_modified date to the songs table
"""
op = get_upgrade_op(session)
- op.add_column('songs', Column('create_date', types.DateTime(), default=func.now()))
- op.add_column('songs', Column('last_modified', types.DateTime(), default=func.now()))
+ songs_table = Table('songs', metadata, autoload=True)
+ if 'create_date' not in [col.name for col in songs_table.c.values()]:
+ op.add_column('songs', Column('create_date', types.DateTime(), default=func.now()))
+ op.add_column('songs', Column('last_modified', types.DateTime(), default=func.now()))
+ else:
+ log.warning('Skipping upgrade_2 step of upgrading the song db')
def upgrade_3(session, metadata):
@@ -83,10 +92,14 @@ def upgrade_3(session, metadata):
This upgrade adds a temporary song flag to the songs table
"""
op = get_upgrade_op(session)
- if metadata.bind.url.get_dialect().name == 'sqlite':
- op.add_column('songs', Column('temporary', types.Boolean(create_constraint=False), server_default=false()))
+ songs_table = Table('songs', metadata, autoload=True)
+ if 'temporary' not in [col.name for col in songs_table.c.values()]:
+ if metadata.bind.url.get_dialect().name == 'sqlite':
+ op.add_column('songs', Column('temporary', types.Boolean(create_constraint=False), server_default=false()))
+ else:
+ op.add_column('songs', Column('temporary', types.Boolean(), server_default=false()))
else:
- op.add_column('songs', Column('temporary', types.Boolean(), server_default=false()))
+ log.warning('Skipping upgrade_3 step of upgrading the song db')
def upgrade_4(session, metadata):
@@ -98,11 +111,15 @@ def upgrade_4(session, metadata):
# Since SQLite doesn't support changing the primary key of a table, we need to recreate the table
# and copy the old values
op = get_upgrade_op(session)
- op.create_table('authors_songs_tmp',
- Column('author_id', types.Integer(), ForeignKey('authors.id'), primary_key=True),
- Column('song_id', types.Integer(), ForeignKey('songs.id'), primary_key=True),
- Column('author_type', types.String(), primary_key=True,
- nullable=False, server_default=text('""')))
- op.execute('INSERT INTO authors_songs_tmp SELECT author_id, song_id, "" FROM authors_songs')
- op.drop_table('authors_songs')
- op.rename_table('authors_songs_tmp', 'authors_songs')
+ songs_table = Table('songs', metadata)
+ if 'author_type' not in [col.name for col in songs_table.c.values()]:
+ op.create_table('authors_songs_tmp',
+ Column('author_id', types.Integer(), ForeignKey('authors.id'), primary_key=True),
+ Column('song_id', types.Integer(), ForeignKey('songs.id'), primary_key=True),
+ Column('author_type', types.String(), primary_key=True,
+ nullable=False, server_default=text('""')))
+ op.execute('INSERT INTO authors_songs_tmp SELECT author_id, song_id, "" FROM authors_songs')
+ op.drop_table('authors_songs')
+ op.rename_table('authors_songs_tmp', 'authors_songs')
+ else:
+ log.warning('Skipping upgrade_4 step of upgrading the song db')
diff --git a/tests/functional/openlp_core_ui/test_slidecontroller.py b/tests/functional/openlp_core_ui/test_slidecontroller.py
index 1d241a317..d8663c20c 100644
--- a/tests/functional/openlp_core_ui/test_slidecontroller.py
+++ b/tests/functional/openlp_core_ui/test_slidecontroller.py
@@ -225,6 +225,10 @@ class TestSlideController(TestCase):
Registry().register('media_controller', mocked_media_controller)
slide_controller = SlideController(None)
slide_controller.display = mocked_display
+ play_slides = MagicMock()
+ play_slides.isChecked.return_value = False
+ slide_controller.play_slides_loop = play_slides
+ slide_controller.play_slides_once = play_slides
# WHEN: live_escape() is called
slide_controller.live_escape()
diff --git a/tests/functional/openlp_plugins/songs/test_db.py b/tests/functional/openlp_plugins/songs/test_db.py
index e696ea94b..690b89a18 100644
--- a/tests/functional/openlp_plugins/songs/test_db.py
+++ b/tests/functional/openlp_plugins/songs/test_db.py
@@ -29,9 +29,15 @@
"""
This module contains tests for the db submodule of the Songs plugin.
"""
+import os
+import shutil
from unittest import TestCase
+from tempfile import mkdtemp
from openlp.plugins.songs.lib.db import Song, Author, AuthorType
+from openlp.plugins.songs.lib import upgrade
+from openlp.core.lib.db import upgrade_db
+from tests.utils.constants import TEST_RESOURCES_PATH
class TestDB(TestCase):
@@ -39,6 +45,18 @@ class TestDB(TestCase):
Test the functions in the :mod:`db` module.
"""
+ def setUp(self):
+ """
+ Setup for tests
+ """
+ self.tmp_folder = mkdtemp()
+
+ def tearDown(self):
+ """
+ Clean up after tests
+ """
+ shutil.rmtree(self.tmp_folder)
+
def test_add_author(self):
"""
Test adding an author to a song
@@ -153,3 +171,37 @@ class TestDB(TestCase):
# THEN: It should return the name with the type in brackets
self.assertEqual("John Doe (Words)", display_name)
+
+ def test_upgrade_old_song_db(self):
+ """
+ Test that we can upgrade an old song db to the current schema
+ """
+ # GIVEN: An old song db
+ old_db_path = os.path.join(TEST_RESOURCES_PATH, "songs", 'songs-1.9.7.sqlite')
+ old_db_tmp_path = os.path.join(self.tmp_folder, 'songs-1.9.7.sqlite')
+ shutil.copyfile(old_db_path, old_db_tmp_path)
+ db_url = 'sqlite:///' + old_db_tmp_path
+
+ # WHEN: upgrading the db
+ updated_to_version, latest_version = upgrade_db(db_url, upgrade)
+
+ # Then the song db should have been upgraded to the latest version
+ self.assertEqual(updated_to_version, latest_version,
+ 'The song DB should have been upgrade to the latest version')
+
+ def test_upgrade_invalid_song_db(self):
+ """
+ Test that we can upgrade an invalid song db to the current schema
+ """
+ # GIVEN: A song db with invalid version
+ invalid_db_path = os.path.join(TEST_RESOURCES_PATH, "songs", 'songs-2.2-invalid.sqlite')
+ invalid_db_tmp_path = os.path.join(self.tmp_folder, 'songs-2.2-invalid.sqlite')
+ shutil.copyfile(invalid_db_path, invalid_db_tmp_path)
+ db_url = 'sqlite:///' + invalid_db_tmp_path
+
+ # WHEN: upgrading the db
+ updated_to_version, latest_version = upgrade_db(db_url, upgrade)
+
+ # Then the song db should have been upgraded to the latest version without errors
+ self.assertEqual(updated_to_version, latest_version,
+ 'The song DB should have been upgrade to the latest version')
diff --git a/tests/resources/songs/songs-1.9.7.sqlite b/tests/resources/songs/songs-1.9.7.sqlite
new file mode 100644
index 000000000..98505464b
Binary files /dev/null and b/tests/resources/songs/songs-1.9.7.sqlite differ
diff --git a/tests/resources/songs/songs-2.2-invalid.sqlite b/tests/resources/songs/songs-2.2-invalid.sqlite
new file mode 100644
index 000000000..0c991d5a3
Binary files /dev/null and b/tests/resources/songs/songs-2.2-invalid.sqlite differ