openlp-core team mailing list archive
-
openlp-core team
-
Mailing list archive
-
Message #25947
[Merge] lp:~oliwee/openlp/newtransition into lp:openlp
Oliver Wieland has proposed merging lp:~oliwee/openlp/newtransition into lp:openlp.
Requested reviews:
OpenLP Core (openlp-core)
For more details, see:
https://code.launchpad.net/~oliwee/openlp/newtransition/+merge/248188
Added a second type of transition, which is more a crossfade than a fade-out-then-fade-in.
Added / adapted tests for htmlbuilder to match the new html code
--
Your team OpenLP Core is requested to review the proposed merge of lp:~oliwee/openlp/newtransition into lp:openlp.
=== modified file 'openlp/core/lib/htmlbuilder.py'
--- openlp/core/lib/htmlbuilder.py 2015-01-18 13:39:21 +0000
+++ openlp/core/lib/htmlbuilder.py 2015-01-31 10:00:29 +0000
@@ -117,6 +117,9 @@
.lyricsmain {
-webkit-text-stroke: 0.125em #000000; -webkit-text-fill-color: #FFFFFF; text-shadow: #000000 5px 5px;
}
+ .lyricstext {
+ -webkit-transition: opacity 0.4s ease;
+ }
sup {
font-size: 0.6em;
@@ -128,6 +131,7 @@
<script>
var timer = null;
var transition = false;
+ var transition_type = '0';
function show_video(state, path, volume, loop, variable_value){
// Sometimes video.currentTime stops slightly short of video.duration and video.ended is intermittent!
@@ -342,16 +346,34 @@
/*
Show the text.
*/
- var text = document.getElementById(id);
- if(text == null) return;
+ var text1 = document.getElementById(id).childNodes[0];
+ var text2 = document.getElementById(id).childNodes[1];
+ if(text1 == null) return;
+ if(text2 == null) return;
if(!transition){
- text.innerHTML = new_text;
+ text1.innerHTML = new_text;
+ text2.innerHTML = new_text;
return;
}
- // Fade text out. 0.1 to minimize the time "nothing" is shown on the screen.
- text.style.opacity = '0.1';
- // Fade new text in after the old text has finished fading out.
- timer = window.setTimeout(function(){_show_text(text, new_text)}, 400);
+ if(transition_type == 0){
+ // Fade text out. 0.1 to minimize the time "nothing" is shown on the screen.
+ text1.style.opacity = '0.1';
+ // Fade new text in after the old text has finished fading out.
+ timer = window.setTimeout(function(){_show_text(text1, new_text)}, 400);
+ }else{
+ // Toggle visible text element by fading out / in
+ if (text1.style.opacity == '1'){
+ text2.innerHTML = new_text;
+ text1.style.opacity = '0';
+ text2.style.opacity = '1';
+ }
+ else{
+ text1.innerHTML = new_text;
+ text2.style.opacity = '0';
+ text1.style.opacity = '1';
+ }
+ timer = window.setTimeout(function(){timer = null;}, 400);
+ }
}
function _show_text(text, new_text) {
@@ -381,7 +403,7 @@
<div id="alert" style="visibility:hidden"></div>
- <div class="lyricstable"><div id="lyricsmain" style="opacity:1" class="lyricscell lyricsmain"></div></div>
+ <div class="lyricstable"><div id="lyricsmain" style="opacity:1" class="lyricscell lyricsmain"><div id="lyricstext1" class="lyricstext" style="opacity:1;"></div><div id="lyricstext2" class="lyricstext" style="opacity:0;position:absolute;top:0px;left:0px;"></div></div></div>
<div id="footer" class="footer"></div>
<div id="black" class="size"></div>
</body>
@@ -448,6 +470,7 @@
<script>
var timer = null;
var transition = %s;
+ var transition_type = %s;
%s
function show_image(src){
@@ -474,6 +497,7 @@
}
document.getElementById('black').style.display = black;
document.getElementById('lyricsmain').style.visibility = lyrics;
+ document.getElementById('lyricsmain2').style.visibility = lyrics;
document.getElementById('image').style.visibility = lyrics;
document.getElementById('footer').style.visibility = lyrics;
}
@@ -501,23 +525,51 @@
new_text = '<span>' + new_text + '</span>';
}
}
- text_fade('lyricsmain', new_text);
+ txt = document.getElementById('lyricsmain2');
+ if(window.getComputedStyle(txt).textAlign == 'justify'){
+ if(window.getComputedStyle(txt).webkitTextStrokeWidth != '0px'){
+ new_text = new_text.replace(/(\s| )+(?![^<]*>)/g,
+ function(match) {
+ return '</span>' + match + '<span>';
+ });
+ new_text = '<span>' + new_text + '</span>';
+ }
+ }
+ text_fade('lyricsmain', 'lyricsmain2', new_text);
}
- function text_fade(id, new_text){
+ function text_fade(id, id2, new_text){
/*
Show the text.
*/
- var text = document.getElementById(id);
- if(text == null) return;
+ var text1 = document.getElementById(id);
+ var text2 = document.getElementById(id2);
+ if(text1 == null) return;
+ if(text2 == null) return;
if(!transition){
- text.innerHTML = new_text;
+ text1.innerHTML = new_text;
+ text2.innerHTML = new_text;
return;
}
- // Fade text out. 0.1 to minimize the time "nothing" is shown on the screen.
- text.style.opacity = '0.1';
- // Fade new text in after the old text has finished fading out.
- timer = window.setTimeout(function(){_show_text(text, new_text)}, 400);
+ if(transition_type == 0){
+ // Fade text out. 0.1 to minimize the time "nothing" is shown on the screen.
+ text1.style.opacity = '0.1';
+ // Fade new text in after the old text has finished fading out.
+ timer = window.setTimeout(function(){_show_text(text1, new_text)}, 400);
+ }else{
+ // Toggle visible text element by fading out / in
+ if (text1.style.opacity == '1'){
+ text2.innerHTML = new_text;
+ text1.style.opacity = '0';
+ text2.style.opacity = '1';
+ }
+ else{
+ text1.innerHTML = new_text;
+ text2.style.opacity = '0';
+ text1.style.opacity = '1';
+ }
+ timer = window.setTimeout(function(){timer = null;}, 400);
+ }
}
function _show_text(text, new_text) {
@@ -541,6 +593,7 @@
<img id="image" class="size" %s />
%s
<div class="lyricstable"><div id="lyricsmain" style="opacity:1" class="lyricscell lyricsmain"></div></div>
+<div class="lyricstable"><div id="lyricsmain2" style="opacity:0" class="lyricscell lyricsmain"></div></div>
<div id="footer" class="footer"></div>
<div id="black" class="size"></div>
</body>
@@ -587,6 +640,7 @@
build_footer_css(item, height),
build_lyrics_css(item),
'true' if theme_data and theme_data.display_slide_transition and is_live else 'false',
+ get_transition_type(item),
js_additions,
bgimage_src,
image_src,
@@ -754,3 +808,15 @@
lyrics_html = style % (item.footer.x(), bottom, item.footer.width(),
theme.font_footer_name, theme.font_footer_size, theme.font_footer_color, whitespace)
return lyrics_html
+
+def get_transition_type(item):
+ """
+ Returns the transition type of the theme
+
+ :param item: Service Item to be processed.
+ """
+ theme= item.theme_data
+ if not theme:
+ return '0'
+
+ return theme.display_slide_transition_type
\ No newline at end of file
=== modified file 'openlp/core/lib/json/theme.json'
--- openlp/core/lib/json/theme.json 2013-10-18 18:10:47 +0000
+++ openlp/core/lib/json/theme.json 2015-01-31 10:00:29 +0000
@@ -11,6 +11,7 @@
"display" :{
"horizontal_align": 0,
"slide_transition": false,
+ "slide_transition_type": 0,
"vertical_align": 0
},
"font": {
=== modified file 'openlp/core/lib/theme.py'
--- openlp/core/lib/theme.py 2015-01-18 13:39:21 +0000
+++ openlp/core/lib/theme.py 2015-01-31 10:00:29 +0000
@@ -140,6 +140,33 @@
Names = ['top', 'middle', 'bottom']
+class TransitionType(object):
+ """
+ Type enumeration for backgrounds.
+ """
+ Fadeout_fadein = 0
+ Crossfade = 1
+
+ @staticmethod
+ def to_string(transition_type):
+ """
+ Return a string representation of a transition type.
+ """
+ if transition_type == TransitionType.Fadeout_fadein:
+ return 'Fade Out - Fade In'
+ elif transition_type == TransitionType.Crossfade:
+ return 'Crossfade'
+
+ @staticmethod
+ def from_string(type_string):
+ """
+ Return a transition type for the given string.
+ """
+ if type_string == 'Fade Out - Fade In':
+ return TransitionType.Fadeout_fadein
+ elif type_string == 'Crossfade':
+ return TransitionType.Crossfade
+
BOOLEAN_LIST = ['bold', 'italics', 'override', 'outline', 'shadow', 'slide_transition']
INTEGER_LIST = ['size', 'line_adjustment', 'x', 'height', 'y', 'width', 'shadow_size', 'outline_size',
@@ -318,13 +345,14 @@
element.appendChild(value)
background.appendChild(element)
- def add_display(self, horizontal, vertical, transition):
+ def add_display(self, horizontal, vertical, transition, transition_type):
"""
Add a Display options.
:param horizontal: The horizontal alignment of the text.
:param vertical: The vertical alignment of the text.
:param transition: Whether the slide transition is active.
+ _param transition_type: Type of the slide transition.
"""
background = self.theme_xml.createElement('display')
self.theme.appendChild(background)
@@ -343,6 +371,11 @@
value = self.theme_xml.createTextNode(str(transition))
element.appendChild(value)
background.appendChild(element)
+ # Slide Transition Type
+ element = self.theme_xml.createElement('slideTransitionType')
+ value = self.theme_xml.createTextNode(str(transition_type))
+ element.appendChild(value)
+ background.appendChild(element)
def child_element(self, element, tag, value):
"""
@@ -555,5 +588,6 @@
self.add_display(
self.display_horizontal_align,
self.display_vertical_align,
- self.display_slide_transition
+ self.display_slide_transition,
+ self.display_slide_transition_type
)
=== modified file 'openlp/core/ui/themeform.py'
--- openlp/core/ui/themeform.py 2015-01-18 13:39:21 +0000
+++ openlp/core/ui/themeform.py 2015-01-31 10:00:29 +0000
@@ -28,7 +28,7 @@
from PyQt4 import QtCore, QtGui
from openlp.core.common import Registry, RegistryProperties, UiStrings, translate
-from openlp.core.lib.theme import BackgroundType, BackgroundGradientType
+from openlp.core.lib.theme import BackgroundType, BackgroundGradientType, TransitionType
from openlp.core.lib.ui import critical_error_message_box
from openlp.core.ui import ThemeLayoutForm
from openlp.core.utils import get_images_filter, is_not_image_file
@@ -88,6 +88,7 @@
self.main_font_combo_box.activated.connect(self.calculate_lines)
self.footer_font_combo_box.activated.connect(self.update_theme)
self.footer_size_spin_box.valueChanged.connect(self.update_theme)
+ self.transitions_combo_box.currentIndexChanged.connect(self.on_transitions_combo_box_current_index_changed)
def set_defaults(self):
"""
@@ -134,6 +135,7 @@
self.background_page.registerField('horizontal', self.horizontal_combo_box)
self.background_page.registerField('vertical', self.vertical_combo_box)
self.background_page.registerField('slide_transition', self.transitions_check_box)
+ self.background_page.registerField('slide_transition_type', self.transitions_combo_box)
self.background_page.registerField('name', self.theme_name_edit)
def calculate_lines(self):
@@ -366,6 +368,7 @@
self.setField('horizontal', self.theme.display_horizontal_align)
self.setField('vertical', self.theme.display_vertical_align)
self.setField('slide_transition', self.theme.display_slide_transition)
+ self.setField('slide_transition_type', self.theme.display_slide_transition_type)
def set_preview_page_values(self):
"""
@@ -464,6 +467,14 @@
"""
self.theme.font_footer_color = color
+ def on_transitions_combo_box_current_index_changed(self, index):
+ """
+ Transition style Combo box has changed.
+ """
+ # do not allow updates when screen is building for the first time.
+ if self.update_theme_allowed:
+ self.theme.transition_type = TransitionType.to_string(index)
+
def update_theme(self):
"""
Update the theme object from the UI for fields not already updated
@@ -496,6 +507,7 @@
self.theme.display_horizontal_align = self.horizontal_combo_box.currentIndex()
self.theme.display_vertical_align = self.vertical_combo_box.currentIndex()
self.theme.display_slide_transition = self.field('slide_transition')
+ self.theme.display_slide_transition_type = self.field('slide_transition_type')
def accept(self):
"""
=== modified file 'openlp/core/ui/themewizard.py'
--- openlp/core/ui/themewizard.py 2015-01-18 13:39:21 +0000
+++ openlp/core/ui/themewizard.py 2015-01-31 10:00:29 +0000
@@ -26,7 +26,7 @@
from openlp.core.common import UiStrings, translate, is_macosx
from openlp.core.lib import build_icon, ColorButton
-from openlp.core.lib.theme import HorizontalType, BackgroundType, BackgroundGradientType
+from openlp.core.lib.theme import HorizontalType, BackgroundType, BackgroundGradientType, TransitionType
from openlp.core.lib.ui import add_welcome_page, create_valign_selection_widgets
@@ -257,9 +257,17 @@
self.alignment_layout.addRow(self.vertical_label, self.vertical_combo_box)
self.transitions_label = QtGui.QLabel(self.alignment_page)
self.transitions_label.setObjectName('transitions_label')
+ self.transitions_properties_layout = QtGui.QHBoxLayout()
+ self.transitions_properties_layout.setObjectName('transitions_properties_layout')
self.transitions_check_box = QtGui.QCheckBox(self.alignment_page)
self.transitions_check_box.setObjectName('transitions_check_box')
- self.alignment_layout.addRow(self.transitions_label, self.transitions_check_box)
+ self.transitions_properties_layout.addWidget(self.transitions_check_box)
+ self.transitions_properties_layout.addSpacing(20)
+ self.transitions_combo_box = QtGui.QComboBox(self.alignment_page)
+ self.transitions_combo_box.addItems(['', ''])
+ self.transitions_combo_box.setObjectName('transitions_combo_box')
+ self.transitions_properties_layout.addWidget(self.transitions_combo_box)
+ self.alignment_layout.addRow(self.transitions_label, self.transitions_properties_layout)
self.alignment_layout.setItem(3, QtGui.QFormLayout.LabelRole, self.spacer)
theme_wizard.addPage(self.alignment_page)
# Area Position Page
@@ -458,6 +466,10 @@
self.horizontal_combo_box.setItemText(HorizontalType.Center, translate('OpenLP.ThemeWizard', 'Center'))
self.horizontal_combo_box.setItemText(HorizontalType.Justify, translate('OpenLP.ThemeWizard', 'Justify'))
self.transitions_label.setText(translate('OpenLP.ThemeWizard', 'Transitions:'))
+ self.transitions_combo_box.setItemText(TransitionType.Fadeout_fadein,
+ translate('OpenLP.ThemeWizard', 'Fade out - Fade in'))
+ self.transitions_combo_box.setItemText(TransitionType.Crossfade,
+ translate('OpenLP.ThemeWizard', 'Crossfade'))
self.area_position_page.setTitle(translate('OpenLP.ThemeWizard', 'Output Area Locations'))
self.area_position_page.setSubTitle(translate('OpenLP.ThemeWizard', 'Allows you to change and move the'
' Main and Footer areas.'))
=== modified file 'tests/functional/openlp_core_lib/test_htmlbuilder.py'
--- tests/functional/openlp_core_lib/test_htmlbuilder.py 2014-07-24 21:57:16 +0000
+++ tests/functional/openlp_core_lib/test_htmlbuilder.py 2015-01-31 10:00:29 +0000
@@ -8,7 +8,7 @@
from openlp.core.common import Settings
from openlp.core.lib.htmlbuilder import build_html, build_background_css, build_lyrics_css, build_lyrics_outline_css, \
- build_lyrics_format_css, build_footer_css
+ build_lyrics_format_css, build_footer_css, get_transition_type
from openlp.core.lib.theme import HorizontalType, VerticalType
from tests.functional import MagicMock, patch
from tests.helpers.testmixin import TestMixin
@@ -65,6 +65,7 @@
<script>
var timer = null;
var transition = false;
+ var transition_type = 0;
plugin JS
function show_image(src){
@@ -91,6 +92,7 @@
}
document.getElementById('black').style.display = black;
document.getElementById('lyricsmain').style.visibility = lyrics;
+ document.getElementById('lyricsmain2').style.visibility = lyrics;
document.getElementById('image').style.visibility = lyrics;
document.getElementById('footer').style.visibility = lyrics;
}
@@ -100,7 +102,7 @@
}
function show_text(new_text){
- var match = /-webkit-text-fill-color:[^;"]+/gi;
+ var match = /-webkit-text-fill-color:[^;\"]+/gi;
if(timer != null)
clearTimeout(timer);
/*
@@ -118,23 +120,51 @@
new_text = '<span>' + new_text + '</span>';
}
}
- text_fade('lyricsmain', new_text);
+ txt = document.getElementById('lyricsmain2');
+ if(window.getComputedStyle(txt).textAlign == 'justify'){
+ if(window.getComputedStyle(txt).webkitTextStrokeWidth != '0px'){
+ new_text = new_text.replace(/(\s| )+(?![^<]*>)/g,
+ function(match) {
+ return '</span>' + match + '<span>';
+ });
+ new_text = '<span>' + new_text + '</span>';
+ }
+ }
+ text_fade('lyricsmain', 'lyricsmain2', new_text);
}
- function text_fade(id, new_text){
+ function text_fade(id, id2, new_text){
/*
Show the text.
*/
- var text = document.getElementById(id);
- if(text == null) return;
+ var text1 = document.getElementById(id);
+ var text2 = document.getElementById(id2);
+ if(text1 == null) return;
+ if(text2 == null) return;
if(!transition){
- text.innerHTML = new_text;
+ text1.innerHTML = new_text;
+ text2.innerHTML = new_text;
return;
}
- // Fade text out. 0.1 to minimize the time "nothing" is shown on the screen.
- text.style.opacity = '0.1';
- // Fade new text in after the old text has finished fading out.
- timer = window.setTimeout(function(){_show_text(text, new_text)}, 400);
+ if(transition_type == 0){
+ // Fade text out. 0.1 to minimize the time "nothing" is shown on the screen.
+ text1.style.opacity = '0.1';
+ // Fade new text in after the old text has finished fading out.
+ timer = window.setTimeout(function(){_show_text(text1, new_text)}, 400);
+ }else{
+ // Toggle visible text element by fading out / in
+ if (text1.style.opacity == '1'){
+ text2.innerHTML = new_text;
+ text1.style.opacity = '0';
+ text2.style.opacity = '1';
+ }
+ else{
+ text1.innerHTML = new_text;
+ text2.style.opacity = '0';
+ text1.style.opacity = '1';
+ }
+ timer = window.setTimeout(function(){timer = null;}, 400);
+ }
}
function _show_text(text, new_text) {
@@ -158,6 +188,7 @@
<img id="image" class="size" style="display:none;" />
plugin HTML
<div class="lyricstable"><div id="lyricsmain" style="opacity:1" class="lyricscell lyricsmain"></div></div>
+<div class="lyricstable"><div id="lyricsmain2" style="opacity:0" class="lyricscell lyricsmain"></div></div>
<div id="footer" class="footer"></div>
<div id="black" class="size"></div>
</body>
@@ -230,6 +261,7 @@
# Mocked arguments.
item = MagicMock()
item.bg_image_bytes = None
+ item.theme_data.display_slide_transition_type = 0
screen = MagicMock()
is_live = False
background = None
@@ -238,6 +270,7 @@
plugin.get_display_javascript.return_value = 'plugin JS'
plugin.get_display_html.return_value = 'plugin HTML'
plugins = [plugin]
+ self.maxDiff = None
# WHEN: Create the html.
html = build_html(item, screen, is_live, background, plugins=plugins)
@@ -358,3 +391,18 @@
# THEN: Footer should wrap
self.assertEqual(FOOTER_CSS_WRAP, css, 'The footer strings should be equal.')
+
+ def get_transition_type_test(self):
+ """
+ Test the get_transition_type() function
+ """
+ # GIVEN: Create a theme.
+ item = MagicMock()
+ item.theme_data.display_slide_transition_type = 1
+
+ #WHEN: get transition type
+ transition_type = get_transition_type(item);
+
+ #THEN: transition type should be 1
+ self.assertEqual(1, transition_type, 'The transition type should be 1.');
+
\ No newline at end of file
Follow ups