forked from openlp/openlp
Fix upgrade on song db with lost version. Fixes bug 1391638.
Treat slide notes and servicemanager notes differently in the web remote and stage view. Fixes bug 1390015. When escaping live display stop looping to prevent display to reappear. Fixes bug 1266271. bzr-revno: 2451
This commit is contained in:
commit
df6c533387
@ -493,6 +493,11 @@ class SlideController(DisplayController, RegistryProperties):
|
|||||||
"""
|
"""
|
||||||
self.display.setVisible(False)
|
self.display.setVisible(False)
|
||||||
self.media_controller.media_stop(self)
|
self.media_controller.media_stop(self)
|
||||||
|
# Stop looping if active
|
||||||
|
if self.play_slides_loop.isChecked():
|
||||||
|
self.on_play_slides_loop(False)
|
||||||
|
elif self.play_slides_once.isChecked():
|
||||||
|
self.on_play_slides_once(False)
|
||||||
|
|
||||||
def toggle_display(self, action):
|
def toggle_display(self, action):
|
||||||
"""
|
"""
|
||||||
|
@ -67,8 +67,12 @@ window.OpenLP = {
|
|||||||
var ul = $("#service-manager > div[data-role=content] > ul[data-role=listview]");
|
var ul = $("#service-manager > div[data-role=content] > ul[data-role=listview]");
|
||||||
ul.html("");
|
ul.html("");
|
||||||
$.each(data.results.items, function (idx, value) {
|
$.each(data.results.items, function (idx, value) {
|
||||||
|
var text = value["title"];
|
||||||
|
if (value["notes"]) {
|
||||||
|
text += ' - ' + value["notes"];
|
||||||
|
}
|
||||||
var li = $("<li data-icon=\"false\">").append(
|
var li = $("<li data-icon=\"false\">").append(
|
||||||
$("<a href=\"#\">").attr("value", parseInt(idx, 10)).text(value["title"]));
|
$("<a href=\"#\">").attr("value", parseInt(idx, 10)).text(text));
|
||||||
li.attr("uuid", value["id"])
|
li.attr("uuid", value["id"])
|
||||||
li.children("a").click(OpenLP.setItem);
|
li.children("a").click(OpenLP.setItem);
|
||||||
ul.append(li);
|
ul.append(li);
|
||||||
@ -98,8 +102,8 @@ window.OpenLP = {
|
|||||||
} else {
|
} else {
|
||||||
text += slide["text"];
|
text += slide["text"];
|
||||||
}
|
}
|
||||||
if (slide["notes"]) {
|
if (slide["slide_notes"]) {
|
||||||
text += ("<div style='font-size:smaller;font-weight:normal'>" + slide["notes"] + "</div>");
|
text += ("<div style='font-size:smaller;font-weight:normal'>" + slide["slide_notes"] + "</div>");
|
||||||
}
|
}
|
||||||
text = text.replace(/\n/g, '<br />');
|
text = text.replace(/\n/g, '<br />');
|
||||||
if (slide["img"]) {
|
if (slide["img"]) {
|
||||||
|
@ -114,8 +114,8 @@ window.OpenLP = {
|
|||||||
text += "<br /><img src='" + slide["img"].replace("/thumbnails/", "/thumbnails320x240/") + "'><br />";
|
text += "<br /><img src='" + slide["img"].replace("/thumbnails/", "/thumbnails320x240/") + "'><br />";
|
||||||
}
|
}
|
||||||
// use notes if available
|
// use notes if available
|
||||||
if (slide["notes"]) {
|
if (slide["slide_notes"]) {
|
||||||
text += '<br />' + slide["notes"];
|
text += '<br />' + slide["slide_notes"];
|
||||||
}
|
}
|
||||||
text = text.replace(/\n/g, "<br />");
|
text = text.replace(/\n/g, "<br />");
|
||||||
$("#currentslide").html(text);
|
$("#currentslide").html(text);
|
||||||
|
@ -521,7 +521,7 @@ class HttpRouter(RegistryProperties):
|
|||||||
if current_item.is_capable(ItemCapabilities.HasDisplayTitle):
|
if current_item.is_capable(ItemCapabilities.HasDisplayTitle):
|
||||||
item['title'] = str(frame['display_title'])
|
item['title'] = str(frame['display_title'])
|
||||||
if current_item.is_capable(ItemCapabilities.HasNotes):
|
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 \
|
if current_item.is_capable(ItemCapabilities.HasThumbnails) and \
|
||||||
Settings().value('remotes/thumbnails'):
|
Settings().value('remotes/thumbnails'):
|
||||||
# If the file is under our app directory tree send the portion after the match
|
# 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['text'] = str(frame['title'])
|
||||||
item['html'] = str(frame['title'])
|
item['html'] = str(frame['title'])
|
||||||
item['selected'] = (self.live_controller.selected_row == index)
|
item['selected'] = (self.live_controller.selected_row == index)
|
||||||
if current_item.notes:
|
|
||||||
item['notes'] = item.get('notes', '') + '\n' + current_item.notes
|
|
||||||
data.append(item)
|
data.append(item)
|
||||||
json_data = {'results': {'slides': data}}
|
json_data = {'results': {'slides': data}}
|
||||||
if current_item:
|
if current_item:
|
||||||
|
@ -32,10 +32,11 @@ backend for the Songs plugin
|
|||||||
"""
|
"""
|
||||||
import logging
|
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 sqlalchemy.sql.expression import func, false, null, text
|
||||||
|
|
||||||
from openlp.core.lib.db import get_upgrade_op
|
from openlp.core.lib.db import get_upgrade_op
|
||||||
|
from openlp.core.common import trace_error_handler
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
__version__ = 4
|
__version__ = 4
|
||||||
@ -57,12 +58,16 @@ def upgrade_1(session, metadata):
|
|||||||
:param metadata:
|
:param metadata:
|
||||||
"""
|
"""
|
||||||
op = get_upgrade_op(session)
|
op = get_upgrade_op(session)
|
||||||
|
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.drop_table('media_files_songs')
|
||||||
op.add_column('media_files', Column('song_id', types.Integer(), server_default=null()))
|
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')))
|
op.add_column('media_files', Column('weight', types.Integer(), server_default=text('0')))
|
||||||
if metadata.bind.url.get_dialect().name != 'sqlite':
|
if metadata.bind.url.get_dialect().name != 'sqlite':
|
||||||
# SQLite doesn't support ALTER TABLE ADD CONSTRAINT
|
# SQLite doesn't support ALTER TABLE ADD CONSTRAINT
|
||||||
op.create_foreign_key('fk_media_files_song_id', 'media_files', 'songs', ['song_id', 'id'])
|
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):
|
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
|
This upgrade adds a create_date and last_modified date to the songs table
|
||||||
"""
|
"""
|
||||||
op = get_upgrade_op(session)
|
op = get_upgrade_op(session)
|
||||||
|
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('create_date', types.DateTime(), default=func.now()))
|
||||||
op.add_column('songs', Column('last_modified', 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):
|
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
|
This upgrade adds a temporary song flag to the songs table
|
||||||
"""
|
"""
|
||||||
op = get_upgrade_op(session)
|
op = get_upgrade_op(session)
|
||||||
|
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':
|
if metadata.bind.url.get_dialect().name == 'sqlite':
|
||||||
op.add_column('songs', Column('temporary', types.Boolean(create_constraint=False), server_default=false()))
|
op.add_column('songs', Column('temporary', types.Boolean(create_constraint=False), server_default=false()))
|
||||||
else:
|
else:
|
||||||
op.add_column('songs', Column('temporary', types.Boolean(), server_default=false()))
|
op.add_column('songs', Column('temporary', types.Boolean(), server_default=false()))
|
||||||
|
else:
|
||||||
|
log.warning('Skipping upgrade_3 step of upgrading the song db')
|
||||||
|
|
||||||
|
|
||||||
def upgrade_4(session, metadata):
|
def upgrade_4(session, metadata):
|
||||||
@ -98,6 +111,8 @@ def upgrade_4(session, metadata):
|
|||||||
# Since SQLite doesn't support changing the primary key of a table, we need to recreate the table
|
# Since SQLite doesn't support changing the primary key of a table, we need to recreate the table
|
||||||
# and copy the old values
|
# and copy the old values
|
||||||
op = get_upgrade_op(session)
|
op = get_upgrade_op(session)
|
||||||
|
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',
|
op.create_table('authors_songs_tmp',
|
||||||
Column('author_id', types.Integer(), ForeignKey('authors.id'), primary_key=True),
|
Column('author_id', types.Integer(), ForeignKey('authors.id'), primary_key=True),
|
||||||
Column('song_id', types.Integer(), ForeignKey('songs.id'), primary_key=True),
|
Column('song_id', types.Integer(), ForeignKey('songs.id'), primary_key=True),
|
||||||
@ -106,3 +121,5 @@ def upgrade_4(session, metadata):
|
|||||||
op.execute('INSERT INTO authors_songs_tmp SELECT author_id, song_id, "" FROM authors_songs')
|
op.execute('INSERT INTO authors_songs_tmp SELECT author_id, song_id, "" FROM authors_songs')
|
||||||
op.drop_table('authors_songs')
|
op.drop_table('authors_songs')
|
||||||
op.rename_table('authors_songs_tmp', 'authors_songs')
|
op.rename_table('authors_songs_tmp', 'authors_songs')
|
||||||
|
else:
|
||||||
|
log.warning('Skipping upgrade_4 step of upgrading the song db')
|
||||||
|
@ -225,6 +225,10 @@ class TestSlideController(TestCase):
|
|||||||
Registry().register('media_controller', mocked_media_controller)
|
Registry().register('media_controller', mocked_media_controller)
|
||||||
slide_controller = SlideController(None)
|
slide_controller = SlideController(None)
|
||||||
slide_controller.display = mocked_display
|
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
|
# WHEN: live_escape() is called
|
||||||
slide_controller.live_escape()
|
slide_controller.live_escape()
|
||||||
|
@ -29,9 +29,15 @@
|
|||||||
"""
|
"""
|
||||||
This module contains tests for the db submodule of the Songs plugin.
|
This module contains tests for the db submodule of the Songs plugin.
|
||||||
"""
|
"""
|
||||||
|
import os
|
||||||
|
import shutil
|
||||||
from unittest import TestCase
|
from unittest import TestCase
|
||||||
|
from tempfile import mkdtemp
|
||||||
|
|
||||||
from openlp.plugins.songs.lib.db import Song, Author, AuthorType
|
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):
|
class TestDB(TestCase):
|
||||||
@ -39,6 +45,18 @@ class TestDB(TestCase):
|
|||||||
Test the functions in the :mod:`db` module.
|
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):
|
def test_add_author(self):
|
||||||
"""
|
"""
|
||||||
Test adding an author to a song
|
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
|
# THEN: It should return the name with the type in brackets
|
||||||
self.assertEqual("John Doe (Words)", display_name)
|
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')
|
||||||
|
BIN
tests/resources/songs/songs-1.9.7.sqlite
Normal file
BIN
tests/resources/songs/songs-1.9.7.sqlite
Normal file
Binary file not shown.
BIN
tests/resources/songs/songs-2.2-invalid.sqlite
Normal file
BIN
tests/resources/songs/songs-2.2-invalid.sqlite
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user