forked from openlp/openlp
Head
This commit is contained in:
commit
63d65da6c1
|
@ -26,7 +26,372 @@
|
||||||
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
||||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
"""
|
||||||
|
This module is responsible for generating the HTML for :class:`~openlp.core.ui.maindisplay`. The ``build_html`` function
|
||||||
|
is the function which has to be called from outside. The generated and returned HTML will look similar to this::
|
||||||
|
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>OpenLP Display</title>
|
||||||
|
<style>
|
||||||
|
*{
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
border: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
background-color: #000000;
|
||||||
|
}
|
||||||
|
.size {
|
||||||
|
position: absolute;
|
||||||
|
left: 0px;
|
||||||
|
top: 0px;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
#black {
|
||||||
|
z-index: 8;
|
||||||
|
background-color: black;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
#bgimage {
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
#image {
|
||||||
|
z-index: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
#videobackboard {
|
||||||
|
z-index:3;
|
||||||
|
background-color: #000000;
|
||||||
|
}
|
||||||
|
#video {
|
||||||
|
background-color: #000000;
|
||||||
|
z-index:4;
|
||||||
|
}
|
||||||
|
|
||||||
|
#flash {
|
||||||
|
z-index:5;
|
||||||
|
}
|
||||||
|
|
||||||
|
#alert {
|
||||||
|
position: absolute;
|
||||||
|
left: 0px;
|
||||||
|
top: 0px;
|
||||||
|
z-index: 10;
|
||||||
|
width: 100%;
|
||||||
|
vertical-align: bottom;
|
||||||
|
font-family: DejaVu Sans;
|
||||||
|
font-size: 40pt;
|
||||||
|
color: #ffffff;
|
||||||
|
background-color: #660000;
|
||||||
|
word-wrap: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
#footer {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 6;
|
||||||
|
|
||||||
|
left: 10px;
|
||||||
|
bottom: 0px;
|
||||||
|
width: 1580px;
|
||||||
|
font-family: Nimbus Sans L;
|
||||||
|
font-size: 12pt;
|
||||||
|
color: #FFFFFF;
|
||||||
|
text-align: left;
|
||||||
|
white-space: nowrap;
|
||||||
|
|
||||||
|
}
|
||||||
|
/* lyric css */
|
||||||
|
|
||||||
|
.lyricstable {
|
||||||
|
z-index: 5;
|
||||||
|
position: absolute;
|
||||||
|
display: table;
|
||||||
|
left: 10px; top: 0px;
|
||||||
|
}
|
||||||
|
.lyricscell {
|
||||||
|
display: table-cell;
|
||||||
|
word-wrap: break-word;
|
||||||
|
-webkit-transition: opacity 0.4s ease;
|
||||||
|
white-space:pre-wrap; word-wrap: break-word; text-align: left; vertical-align: top; font-family: Nimbus Sans L; font-size: 40pt; color: #FFFFFF; line-height: 100%; margin: 0;padding: 0; padding-bottom: 0; padding-left: 4px; width: 1580px; height: 810px;
|
||||||
|
}
|
||||||
|
.lyricsmain {
|
||||||
|
-webkit-text-stroke: 0.125em #000000; -webkit-text-fill-color: #FFFFFF; text-shadow: #000000 5px 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
sup {
|
||||||
|
font-size: 0.6em;
|
||||||
|
vertical-align: top;
|
||||||
|
position: relative;
|
||||||
|
top: -0.3em;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<script>
|
||||||
|
var timer = null;
|
||||||
|
var transition = false;
|
||||||
|
|
||||||
|
function show_video(state, path, volume, loop, variable_value){
|
||||||
|
// Sometimes video.currentTime stops slightly short of video.duration and video.ended is intermittent!
|
||||||
|
|
||||||
|
var video = document.getElementById('video');
|
||||||
|
if(volume != null){
|
||||||
|
video.volume = volume;
|
||||||
|
}
|
||||||
|
switch(state){
|
||||||
|
case 'load':
|
||||||
|
video.src = 'file:///' + path;
|
||||||
|
if(loop == true) {
|
||||||
|
video.loop = true;
|
||||||
|
}
|
||||||
|
video.load();
|
||||||
|
break;
|
||||||
|
case 'play':
|
||||||
|
video.play();
|
||||||
|
break;
|
||||||
|
case 'pause':
|
||||||
|
video.pause();
|
||||||
|
break;
|
||||||
|
case 'stop':
|
||||||
|
show_video('pause');
|
||||||
|
video.currentTime = 0;
|
||||||
|
break;
|
||||||
|
case 'close':
|
||||||
|
show_video('stop');
|
||||||
|
video.src = '';
|
||||||
|
break;
|
||||||
|
case 'length':
|
||||||
|
return video.duration;
|
||||||
|
case 'current_time':
|
||||||
|
return video.currentTime;
|
||||||
|
case 'seek':
|
||||||
|
video.currentTime = variable_value;
|
||||||
|
break;
|
||||||
|
case 'isEnded':
|
||||||
|
return video.ended;
|
||||||
|
case 'setVisible':
|
||||||
|
video.style.visibility = variable_value;
|
||||||
|
break;
|
||||||
|
case 'setBackBoard':
|
||||||
|
var back = document.getElementById('videobackboard');
|
||||||
|
back.style.visibility = variable_value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getFlashMovieObject(movieName)
|
||||||
|
{
|
||||||
|
if (window.document[movieName]){
|
||||||
|
return window.document[movieName];
|
||||||
|
}
|
||||||
|
if (document.embeds && document.embeds[movieName]){
|
||||||
|
return document.embeds[movieName];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function show_flash(state, path, volume, variable_value){
|
||||||
|
var text = document.getElementById('flash');
|
||||||
|
var flashMovie = getFlashMovieObject("OpenLPFlashMovie");
|
||||||
|
var src = "src = 'file:///" + path + "'";
|
||||||
|
var view_parm = " wmode='opaque'" + " width='100%%'" + " height='100%%'";
|
||||||
|
var swf_parm = " name='OpenLPFlashMovie'" + " autostart='true' loop='false' play='true'" +
|
||||||
|
" hidden='false' swliveconnect='true' allowscriptaccess='always'" + " volume='" + volume + "'";
|
||||||
|
|
||||||
|
switch(state){
|
||||||
|
case 'load':
|
||||||
|
text.innerHTML = "<embed " + src + view_parm + swf_parm + "/>";
|
||||||
|
flashMovie = getFlashMovieObject("OpenLPFlashMovie");
|
||||||
|
flashMovie.Play();
|
||||||
|
break;
|
||||||
|
case 'play':
|
||||||
|
flashMovie.Play();
|
||||||
|
break;
|
||||||
|
case 'pause':
|
||||||
|
flashMovie.StopPlay();
|
||||||
|
break;
|
||||||
|
case 'stop':
|
||||||
|
flashMovie.StopPlay();
|
||||||
|
tempHtml = text.innerHTML;
|
||||||
|
text.innerHTML = '';
|
||||||
|
text.innerHTML = tempHtml;
|
||||||
|
break;
|
||||||
|
case 'close':
|
||||||
|
flashMovie.StopPlay();
|
||||||
|
text.innerHTML = '';
|
||||||
|
break;
|
||||||
|
case 'length':
|
||||||
|
return flashMovie.TotalFrames();
|
||||||
|
case 'current_time':
|
||||||
|
return flashMovie.CurrentFrame();
|
||||||
|
case 'seek':
|
||||||
|
// flashMovie.GotoFrame(variable_value);
|
||||||
|
break;
|
||||||
|
case 'isEnded':
|
||||||
|
//TODO check flash end
|
||||||
|
return false;
|
||||||
|
case 'setVisible':
|
||||||
|
text.style.visibility = variable_value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function show_alert(alerttext, position){
|
||||||
|
var text = document.getElementById('alert');
|
||||||
|
text.innerHTML = alerttext;
|
||||||
|
if(alerttext == '') {
|
||||||
|
text.style.visibility = 'hidden';
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(position == ''){
|
||||||
|
position = getComputedStyle(text, '').verticalAlign;
|
||||||
|
}
|
||||||
|
switch(position)
|
||||||
|
{
|
||||||
|
case 'top':
|
||||||
|
text.style.top = '0px';
|
||||||
|
break;
|
||||||
|
case 'middle':
|
||||||
|
text.style.top = ((window.innerHeight - text.clientHeight) / 2)
|
||||||
|
+ 'px';
|
||||||
|
break;
|
||||||
|
case 'bottom':
|
||||||
|
text.style.top = (window.innerHeight - text.clientHeight)
|
||||||
|
+ 'px';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
text.style.visibility = 'visible';
|
||||||
|
return text.clientHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
function update_css(align, font, size, color, bgcolor){
|
||||||
|
var text = document.getElementById('alert');
|
||||||
|
text.style.fontSize = size + "pt";
|
||||||
|
text.style.fontFamily = font;
|
||||||
|
text.style.color = color;
|
||||||
|
text.style.backgroundColor = bgcolor;
|
||||||
|
switch(align)
|
||||||
|
{
|
||||||
|
case 'top':
|
||||||
|
text.style.top = '0px';
|
||||||
|
break;
|
||||||
|
case 'middle':
|
||||||
|
text.style.top = ((window.innerHeight - text.clientHeight) / 2)
|
||||||
|
+ 'px';
|
||||||
|
break;
|
||||||
|
case 'bottom':
|
||||||
|
text.style.top = (window.innerHeight - text.clientHeight)
|
||||||
|
+ 'px';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function show_image(src){
|
||||||
|
var img = document.getElementById('image');
|
||||||
|
img.src = src;
|
||||||
|
if(src == '')
|
||||||
|
img.style.display = 'none';
|
||||||
|
else
|
||||||
|
img.style.display = 'block';
|
||||||
|
}
|
||||||
|
|
||||||
|
function show_blank(state){
|
||||||
|
var black = 'none';
|
||||||
|
var lyrics = '';
|
||||||
|
switch(state){
|
||||||
|
case 'theme':
|
||||||
|
lyrics = 'hidden';
|
||||||
|
break;
|
||||||
|
case 'black':
|
||||||
|
black = 'block';
|
||||||
|
break;
|
||||||
|
case 'desktop':
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
document.getElementById('black').style.display = black;
|
||||||
|
document.getElementById('lyricsmain').style.visibility = lyrics;
|
||||||
|
document.getElementById('image').style.visibility = lyrics;
|
||||||
|
document.getElementById('footer').style.visibility = lyrics;
|
||||||
|
}
|
||||||
|
|
||||||
|
function show_footer(footertext){
|
||||||
|
document.getElementById('footer').innerHTML = footertext;
|
||||||
|
}
|
||||||
|
|
||||||
|
function show_text(new_text){
|
||||||
|
var match = /-webkit-text-fill-color:[^;"]+/gi;
|
||||||
|
if(timer != null)
|
||||||
|
clearTimeout(timer);
|
||||||
|
/*
|
||||||
|
QtWebkit bug with outlines and justify causing outline alignment
|
||||||
|
problems. (Bug 859950) Surround each word with a <span> to workaround,
|
||||||
|
but only in this scenario.
|
||||||
|
*/
|
||||||
|
var txt = document.getElementById('lyricsmain');
|
||||||
|
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', new_text);
|
||||||
|
}
|
||||||
|
|
||||||
|
function text_fade(id, new_text){
|
||||||
|
/*
|
||||||
|
Show the text.
|
||||||
|
*/
|
||||||
|
var text = document.getElementById(id);
|
||||||
|
if(text == null) return;
|
||||||
|
if(!transition){
|
||||||
|
text.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);
|
||||||
|
}
|
||||||
|
|
||||||
|
function _show_text(text, new_text) {
|
||||||
|
/*
|
||||||
|
Helper function to show the new_text delayed.
|
||||||
|
*/
|
||||||
|
text.innerHTML = new_text;
|
||||||
|
text.style.opacity = '1';
|
||||||
|
// Wait until the text is completely visible. We want to save the timer id, to be able to call
|
||||||
|
// clearTimeout(timer) when the text has changed before finishing fading.
|
||||||
|
timer = window.setTimeout(function(){timer = null;}, 400);
|
||||||
|
}
|
||||||
|
|
||||||
|
function show_text_completed(){
|
||||||
|
return (timer == null);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<img id="bgimage" class="size" style="display:none;" />
|
||||||
|
<img id="image" class="size" style="display:none;" />
|
||||||
|
|
||||||
|
<div id="videobackboard" class="size" style="visibility:hidden"></div>
|
||||||
|
<video id="video" class="size" style="visibility:hidden" autobuffer preload></video>
|
||||||
|
|
||||||
|
<div id="flash" class="size" style="visibility:hidden"></div>
|
||||||
|
|
||||||
|
<div id="alert" style="visibility:hidden"></div>
|
||||||
|
|
||||||
|
<div class="lyricstable"><div id="lyricsmain" style="opacity:1" class="lyricscell lyricsmain"></div></div>
|
||||||
|
<div id="footer" class="footer"></div>
|
||||||
|
<div id="black" class="size"></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
"""
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from PyQt4 import QtWebKit
|
from PyQt4 import QtWebKit
|
||||||
|
@ -114,12 +479,6 @@ sup {
|
||||||
document.getElementById('black').style.display = black;
|
document.getElementById('black').style.display = black;
|
||||||
document.getElementById('lyricsmain').style.visibility = lyrics;
|
document.getElementById('lyricsmain').style.visibility = lyrics;
|
||||||
document.getElementById('image').style.visibility = lyrics;
|
document.getElementById('image').style.visibility = lyrics;
|
||||||
outline = document.getElementById('lyricsoutline')
|
|
||||||
if(outline != null)
|
|
||||||
outline.style.visibility = lyrics;
|
|
||||||
shadow = document.getElementById('lyricsshadow')
|
|
||||||
if(shadow != null)
|
|
||||||
shadow.style.visibility = lyrics;
|
|
||||||
document.getElementById('footer').style.visibility = lyrics;
|
document.getElementById('footer').style.visibility = lyrics;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,9 +497,6 @@ sup {
|
||||||
*/
|
*/
|
||||||
var txt = document.getElementById('lyricsmain');
|
var txt = document.getElementById('lyricsmain');
|
||||||
if(window.getComputedStyle(txt).textAlign == 'justify'){
|
if(window.getComputedStyle(txt).textAlign == 'justify'){
|
||||||
var outline = document.getElementById('lyricsoutline');
|
|
||||||
if(outline != null)
|
|
||||||
txt = outline;
|
|
||||||
if(window.getComputedStyle(txt).webkitTextStrokeWidth != '0px'){
|
if(window.getComputedStyle(txt).webkitTextStrokeWidth != '0px'){
|
||||||
new_text = new_text.replace(/(\s| )+(?![^<]*>)/g,
|
new_text = new_text.replace(/(\s| )+(?![^<]*>)/g,
|
||||||
function(match) {
|
function(match) {
|
||||||
|
@ -150,8 +506,6 @@ sup {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
text_fade('lyricsmain', new_text);
|
text_fade('lyricsmain', new_text);
|
||||||
text_fade('lyricsoutline', new_text);
|
|
||||||
text_fade('lyricsshadow', new_text.replace(match, ''));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function text_fade(id, new_text){
|
function text_fade(id, new_text){
|
||||||
|
@ -190,7 +544,7 @@ sup {
|
||||||
<img id="bgimage" class="size" %s />
|
<img id="bgimage" class="size" %s />
|
||||||
<img id="image" class="size" %s />
|
<img id="image" class="size" %s />
|
||||||
%s
|
%s
|
||||||
%s
|
<div class="lyricstable"><div id="lyricsmain" style="opacity:1" class="lyricscell lyricsmain"></div></div>
|
||||||
<div id="footer" class="footer"></div>
|
<div id="footer" class="footer"></div>
|
||||||
<div id="black" class="size"></div>
|
<div id="black" class="size"></div>
|
||||||
</body>
|
</body>
|
||||||
|
@ -222,8 +576,7 @@ def build_html(item, screen, is_live, background, image=None, plugins=None):
|
||||||
"""
|
"""
|
||||||
width = screen['size'].width()
|
width = screen['size'].width()
|
||||||
height = screen['size'].height()
|
height = screen['size'].height()
|
||||||
theme = item.themedata
|
theme_data = item.themedata
|
||||||
webkit_ver = webkit_version()
|
|
||||||
# Image generated and poked in
|
# Image generated and poked in
|
||||||
if background:
|
if background:
|
||||||
bgimage_src = 'src="data:image/png;base64,%s"' % background
|
bgimage_src = 'src="data:image/png;base64,%s"' % background
|
||||||
|
@ -247,12 +600,12 @@ def build_html(item, screen, is_live, background, image=None, plugins=None):
|
||||||
build_background_css(item, width),
|
build_background_css(item, width),
|
||||||
css_additions,
|
css_additions,
|
||||||
build_footer_css(item, height),
|
build_footer_css(item, height),
|
||||||
build_lyrics_css(item, webkit_ver),
|
build_lyrics_css(item),
|
||||||
'true' if theme and theme.display_slide_transition and is_live else 'false',
|
'true' if theme_data and theme_data.display_slide_transition and is_live else 'false',
|
||||||
js_additions,
|
js_additions,
|
||||||
bgimage_src, image_src,
|
bgimage_src,
|
||||||
html_additions,
|
image_src,
|
||||||
build_lyrics_html(item, webkit_ver)
|
html_additions
|
||||||
)
|
)
|
||||||
return html
|
return html
|
||||||
|
|
||||||
|
@ -303,16 +656,13 @@ def build_background_css(item, width):
|
||||||
return background
|
return background
|
||||||
|
|
||||||
|
|
||||||
def build_lyrics_css(item, webkit_ver):
|
def build_lyrics_css(item):
|
||||||
"""
|
"""
|
||||||
Build the lyrics display css
|
Build the lyrics display css
|
||||||
|
|
||||||
``item``
|
``item``
|
||||||
Service Item containing theme and location information
|
Service Item containing theme and location information
|
||||||
|
|
||||||
``webkitvers``
|
|
||||||
The version of qtwebkit we're using
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
style = """
|
style = """
|
||||||
.lyricstable {
|
.lyricstable {
|
||||||
|
@ -329,80 +679,43 @@ def build_lyrics_css(item, webkit_ver):
|
||||||
}
|
}
|
||||||
.lyricsmain {
|
.lyricsmain {
|
||||||
%s
|
%s
|
||||||
}
|
|
||||||
.lyricsoutline {
|
|
||||||
%s
|
|
||||||
}
|
|
||||||
.lyricsshadow {
|
|
||||||
%s
|
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
theme = item.themedata
|
theme_data = item.themedata
|
||||||
lyricstable = ''
|
lyricstable = ''
|
||||||
lyrics = ''
|
lyrics = ''
|
||||||
lyricsmain = ''
|
lyricsmain = ''
|
||||||
outline = ''
|
if theme_data and item.main:
|
||||||
shadow = ''
|
|
||||||
if theme and item.main:
|
|
||||||
lyricstable = 'left: %spx; top: %spx;' % (item.main.x(), item.main.y())
|
lyricstable = 'left: %spx; top: %spx;' % (item.main.x(), item.main.y())
|
||||||
lyrics = build_lyrics_format_css(theme, item.main.width(), item.main.height())
|
lyrics = build_lyrics_format_css(theme_data, item.main.width(), item.main.height())
|
||||||
# For performance reasons we want to show as few DIV's as possible, especially when animating/transitions.
|
lyricsmain += build_lyrics_outline_css(theme_data)
|
||||||
# However some bugs in older versions of qtwebkit mean we need to perform workarounds and add extra divs. Only
|
if theme_data.font_main_shadow:
|
||||||
# do these when needed.
|
|
||||||
#
|
|
||||||
# Before 533.3 the webkit-text-fill colour wasn't displayed, only the stroke (outline) color. So put stroke
|
|
||||||
# layer underneath the main text.
|
|
||||||
#
|
|
||||||
# Up to 534.3 the webkit-text-stroke was sometimes out of alignment with the fill, or normal text.
|
|
||||||
# letter-spacing=1 is workaround https://bugs.webkit.org/show_bug.cgi?id=44403
|
|
||||||
#
|
|
||||||
# Up to 534.3 the text-shadow didn't get displayed when webkit-text-stroke was used. So use an offset text
|
|
||||||
# layer underneath. https://bugs.webkit.org/show_bug.cgi?id=19728
|
|
||||||
if webkit_ver >= 533.3:
|
|
||||||
lyricsmain += build_lyrics_outline_css(theme)
|
|
||||||
else:
|
|
||||||
outline = build_lyrics_outline_css(theme)
|
|
||||||
if theme.font_main_shadow:
|
|
||||||
if theme.font_main_outline and webkit_ver <= 534.3:
|
|
||||||
shadow = 'padding-left: %spx; padding-top: %spx;' % \
|
|
||||||
(int(theme.font_main_shadow_size) + (int(theme.font_main_outline_size) * 2),
|
|
||||||
theme.font_main_shadow_size)
|
|
||||||
shadow += build_lyrics_outline_css(theme, True)
|
|
||||||
else:
|
|
||||||
lyricsmain += ' text-shadow: %s %spx %spx;' % \
|
lyricsmain += ' text-shadow: %s %spx %spx;' % \
|
||||||
(theme.font_main_shadow_color, theme.font_main_shadow_size, theme.font_main_shadow_size)
|
(theme_data.font_main_shadow_color, theme_data.font_main_shadow_size, theme_data.font_main_shadow_size)
|
||||||
lyrics_css = style % (lyricstable, lyrics, lyricsmain, outline, shadow)
|
lyrics_css = style % (lyricstable, lyrics, lyricsmain)
|
||||||
return lyrics_css
|
return lyrics_css
|
||||||
|
|
||||||
|
|
||||||
def build_lyrics_outline_css(theme, is_shadow=False):
|
def build_lyrics_outline_css(theme_data):
|
||||||
"""
|
"""
|
||||||
Build the css which controls the theme outline. Also used by renderer for splitting verses
|
Build the css which controls the theme outline. Also used by renderer for splitting verses
|
||||||
|
|
||||||
``theme``
|
``theme_data``
|
||||||
Object containing theme information
|
Object containing theme information
|
||||||
|
|
||||||
``is_shadow``
|
|
||||||
If true, use the shadow colors instead
|
|
||||||
"""
|
"""
|
||||||
if theme.font_main_outline:
|
if theme_data.font_main_outline:
|
||||||
size = float(theme.font_main_outline_size) / 16
|
size = float(theme_data.font_main_outline_size) / 16
|
||||||
if is_shadow:
|
fill_color = theme_data.font_main_color
|
||||||
fill_color = theme.font_main_shadow_color
|
outline_color = theme_data.font_main_outline_color
|
||||||
outline_color = theme.font_main_shadow_color
|
|
||||||
else:
|
|
||||||
fill_color = theme.font_main_color
|
|
||||||
outline_color = theme.font_main_outline_color
|
|
||||||
return ' -webkit-text-stroke: %sem %s; -webkit-text-fill-color: %s; ' % (size, outline_color, fill_color)
|
return ' -webkit-text-stroke: %sem %s; -webkit-text-fill-color: %s; ' % (size, outline_color, fill_color)
|
||||||
else:
|
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
|
|
||||||
def build_lyrics_format_css(theme, width, height):
|
def build_lyrics_format_css(theme_data, width, height):
|
||||||
"""
|
"""
|
||||||
Build the css which controls the theme format. Also used by renderer for splitting verses
|
Build the css which controls the theme format. Also used by renderer for splitting verses
|
||||||
|
|
||||||
``theme``
|
``theme_data``
|
||||||
Object containing theme information
|
Object containing theme information
|
||||||
|
|
||||||
``width``
|
``width``
|
||||||
|
@ -411,17 +724,17 @@ def build_lyrics_format_css(theme, width, height):
|
||||||
``height``
|
``height``
|
||||||
Height of the lyrics block
|
Height of the lyrics block
|
||||||
"""
|
"""
|
||||||
align = HorizontalType.Names[theme.display_horizontal_align]
|
align = HorizontalType.Names[theme_data.display_horizontal_align]
|
||||||
valign = VerticalType.Names[theme.display_vertical_align]
|
valign = VerticalType.Names[theme_data.display_vertical_align]
|
||||||
if theme.font_main_outline:
|
if theme_data.font_main_outline:
|
||||||
left_margin = int(theme.font_main_outline_size) * 2
|
left_margin = int(theme_data.font_main_outline_size) * 2
|
||||||
else:
|
else:
|
||||||
left_margin = 0
|
left_margin = 0
|
||||||
justify = 'white-space:pre-wrap;'
|
justify = 'white-space:pre-wrap;'
|
||||||
# fix tag incompatibilities
|
# fix tag incompatibilities
|
||||||
if theme.display_horizontal_align == HorizontalType.Justify:
|
if theme_data.display_horizontal_align == HorizontalType.Justify:
|
||||||
justify = ''
|
justify = ''
|
||||||
if theme.display_vertical_align == VerticalType.Bottom:
|
if theme_data.display_vertical_align == VerticalType.Bottom:
|
||||||
padding_bottom = '0.5em'
|
padding_bottom = '0.5em'
|
||||||
else:
|
else:
|
||||||
padding_bottom = '0'
|
padding_bottom = '0'
|
||||||
|
@ -429,44 +742,16 @@ def build_lyrics_format_css(theme, width, height):
|
||||||
'text-align: %s; vertical-align: %s; font-family: %s; ' \
|
'text-align: %s; vertical-align: %s; font-family: %s; ' \
|
||||||
'font-size: %spt; color: %s; line-height: %d%%; margin: 0;' \
|
'font-size: %spt; color: %s; line-height: %d%%; margin: 0;' \
|
||||||
'padding: 0; padding-bottom: %s; padding-left: %spx; width: %spx; height: %spx; ' % \
|
'padding: 0; padding-bottom: %s; padding-left: %spx; width: %spx; height: %spx; ' % \
|
||||||
(justify, align, valign, theme.font_main_name, theme.font_main_size,
|
(justify, align, valign, theme_data.font_main_name, theme_data.font_main_size,
|
||||||
theme.font_main_color, 100 + int(theme.font_main_line_adjustment), padding_bottom, left_margin, width, height)
|
theme_data.font_main_color, 100 + int(theme_data.font_main_line_adjustment), padding_bottom,
|
||||||
if theme.font_main_outline:
|
left_margin, width, height)
|
||||||
if webkit_version() <= 534.3:
|
if theme_data.font_main_italics:
|
||||||
lyrics += ' letter-spacing: 1px;'
|
|
||||||
if theme.font_main_italics:
|
|
||||||
lyrics += 'font-style:italic; '
|
lyrics += 'font-style:italic; '
|
||||||
if theme.font_main_bold:
|
if theme_data.font_main_bold:
|
||||||
lyrics += 'font-weight:bold; '
|
lyrics += 'font-weight:bold; '
|
||||||
return lyrics
|
return lyrics
|
||||||
|
|
||||||
|
|
||||||
def build_lyrics_html(item, webkitvers):
|
|
||||||
"""
|
|
||||||
Build the HTML required to show the lyrics
|
|
||||||
|
|
||||||
``item``
|
|
||||||
Service Item containing theme and location information
|
|
||||||
|
|
||||||
``webkitvers``
|
|
||||||
The version of qtwebkit we're using
|
|
||||||
"""
|
|
||||||
# Bugs in some versions of QtWebKit mean we sometimes need additional divs for outline and shadow, since the CSS
|
|
||||||
# doesn't work. To support vertical alignment middle and bottom, nested div's using display:table/display:table-cell
|
|
||||||
# are required for each lyric block.
|
|
||||||
lyrics = ''
|
|
||||||
theme = item.themedata
|
|
||||||
if webkitvers <= 534.3 and theme and theme.font_main_outline:
|
|
||||||
lyrics += '<div class="lyricstable"><div id="lyricsshadow" style="opacity:1" ' \
|
|
||||||
'class="lyricscell lyricsshadow"></div></div>'
|
|
||||||
if webkitvers < 533.3:
|
|
||||||
lyrics += '<div class="lyricstable"><div id="lyricsoutline" style="opacity:1" ' \
|
|
||||||
'class="lyricscell lyricsoutline"></div></div>'
|
|
||||||
lyrics += '<div class="lyricstable"><div id="lyricsmain" style="opacity:1" ' \
|
|
||||||
'class="lyricscell lyricsmain"></div></div>'
|
|
||||||
return lyrics
|
|
||||||
|
|
||||||
|
|
||||||
def build_footer_css(item, height):
|
def build_footer_css(item, height):
|
||||||
"""
|
"""
|
||||||
Build the display of the item footer
|
Build the display of the item footer
|
||||||
|
|
|
@ -243,8 +243,6 @@ class MainDisplay(Display):
|
||||||
# Windows if there are many items in the service to re-render.
|
# Windows if there are many items in the service to re-render.
|
||||||
# Setting the div elements direct seems to solve the issue
|
# Setting the div elements direct seems to solve the issue
|
||||||
self.frame.findFirstElement("#lyricsmain").setInnerXml(slide)
|
self.frame.findFirstElement("#lyricsmain").setInnerXml(slide)
|
||||||
self.frame.findFirstElement("#lyricsoutline").setInnerXml(slide)
|
|
||||||
self.frame.findFirstElement("#lyricsshadow").setInnerXml(slide)
|
|
||||||
|
|
||||||
def alert(self, text, location):
|
def alert(self, text, location):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -60,22 +60,8 @@ ADDITIONAL_EXT = {
|
||||||
'video/x-wmv': ['.wmv'],
|
'video/x-wmv': ['.wmv'],
|
||||||
'video/x-mpg': ['.mpg'],
|
'video/x-mpg': ['.mpg'],
|
||||||
'video/mpeg': ['.mp4', '.mts', '.mov'],
|
'video/mpeg': ['.mp4', '.mts', '.mov'],
|
||||||
'video/x-ms-wmv': ['.wmv']}
|
'video/x-ms-wmv': ['.wmv']
|
||||||
|
|
||||||
VIDEO_CSS = """
|
|
||||||
#videobackboard {
|
|
||||||
z-index:3;
|
|
||||||
background-color: %(bgcolor)s;
|
|
||||||
}
|
}
|
||||||
#video1 {
|
|
||||||
background-color: %(bgcolor)s;
|
|
||||||
z-index:4;
|
|
||||||
}
|
|
||||||
#video2 {
|
|
||||||
background-color: %(bgcolor)s;
|
|
||||||
z-index:4;
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
class PhononPlayer(MediaPlayer):
|
class PhononPlayer(MediaPlayer):
|
||||||
|
@ -269,8 +255,7 @@ class PhononPlayer(MediaPlayer):
|
||||||
"""
|
"""
|
||||||
Add css style sheets to htmlbuilder
|
Add css style sheets to htmlbuilder
|
||||||
"""
|
"""
|
||||||
background = QtGui.QColor(Settings().value('players/background color')).name()
|
return ''
|
||||||
return VIDEO_CSS % {'bgcolor': background}
|
|
||||||
|
|
||||||
def get_info(self):
|
def get_info(self):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -30,9 +30,9 @@
|
||||||
Package to test the openlp.core.lib.settings package.
|
Package to test the openlp.core.lib.settings package.
|
||||||
"""
|
"""
|
||||||
import os
|
import os
|
||||||
from unittest import TestCase
|
|
||||||
from tempfile import mkstemp
|
from tempfile import mkstemp
|
||||||
|
|
||||||
|
from unittest import TestCase
|
||||||
from PyQt4 import QtGui
|
from PyQt4 import QtGui
|
||||||
|
|
||||||
from openlp.core.common import Settings
|
from openlp.core.common import Settings
|
||||||
|
|
|
@ -0,0 +1,324 @@
|
||||||
|
"""
|
||||||
|
Package to test the openlp.core.lib.htmlbuilder module.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from unittest import TestCase
|
||||||
|
from mock import MagicMock, patch
|
||||||
|
|
||||||
|
from PyQt4 import QtCore
|
||||||
|
|
||||||
|
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
|
||||||
|
from openlp.core.lib.theme import HorizontalType, VerticalType
|
||||||
|
|
||||||
|
|
||||||
|
HTML = """
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>OpenLP Display</title>
|
||||||
|
<style>
|
||||||
|
*{
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
border: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
;
|
||||||
|
}
|
||||||
|
.size {
|
||||||
|
position: absolute;
|
||||||
|
left: 0px;
|
||||||
|
top: 0px;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
#black {
|
||||||
|
z-index: 8;
|
||||||
|
background-color: black;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
#bgimage {
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
#image {
|
||||||
|
z-index: 2;
|
||||||
|
}
|
||||||
|
plugin CSS
|
||||||
|
#footer {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 6;
|
||||||
|
dummy: dummy;
|
||||||
|
}
|
||||||
|
/* lyric css */
|
||||||
|
|
||||||
|
sup {
|
||||||
|
font-size: 0.6em;
|
||||||
|
vertical-align: top;
|
||||||
|
position: relative;
|
||||||
|
top: -0.3em;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<script>
|
||||||
|
var timer = null;
|
||||||
|
var transition = false;
|
||||||
|
plugin JS
|
||||||
|
|
||||||
|
function show_image(src){
|
||||||
|
var img = document.getElementById('image');
|
||||||
|
img.src = src;
|
||||||
|
if(src == '')
|
||||||
|
img.style.display = 'none';
|
||||||
|
else
|
||||||
|
img.style.display = 'block';
|
||||||
|
}
|
||||||
|
|
||||||
|
function show_blank(state){
|
||||||
|
var black = 'none';
|
||||||
|
var lyrics = '';
|
||||||
|
switch(state){
|
||||||
|
case 'theme':
|
||||||
|
lyrics = 'hidden';
|
||||||
|
break;
|
||||||
|
case 'black':
|
||||||
|
black = 'block';
|
||||||
|
break;
|
||||||
|
case 'desktop':
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
document.getElementById('black').style.display = black;
|
||||||
|
document.getElementById('lyricsmain').style.visibility = lyrics;
|
||||||
|
document.getElementById('image').style.visibility = lyrics;
|
||||||
|
document.getElementById('footer').style.visibility = lyrics;
|
||||||
|
}
|
||||||
|
|
||||||
|
function show_footer(footertext){
|
||||||
|
document.getElementById('footer').innerHTML = footertext;
|
||||||
|
}
|
||||||
|
|
||||||
|
function show_text(new_text){
|
||||||
|
var match = /-webkit-text-fill-color:[^;"]+/gi;
|
||||||
|
if(timer != null)
|
||||||
|
clearTimeout(timer);
|
||||||
|
/*
|
||||||
|
QtWebkit bug with outlines and justify causing outline alignment
|
||||||
|
problems. (Bug 859950) Surround each word with a <span> to workaround,
|
||||||
|
but only in this scenario.
|
||||||
|
*/
|
||||||
|
var txt = document.getElementById('lyricsmain');
|
||||||
|
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', new_text);
|
||||||
|
}
|
||||||
|
|
||||||
|
function text_fade(id, new_text){
|
||||||
|
/*
|
||||||
|
Show the text.
|
||||||
|
*/
|
||||||
|
var text = document.getElementById(id);
|
||||||
|
if(text == null) return;
|
||||||
|
if(!transition){
|
||||||
|
text.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);
|
||||||
|
}
|
||||||
|
|
||||||
|
function _show_text(text, new_text) {
|
||||||
|
/*
|
||||||
|
Helper function to show the new_text delayed.
|
||||||
|
*/
|
||||||
|
text.innerHTML = new_text;
|
||||||
|
text.style.opacity = '1';
|
||||||
|
// Wait until the text is completely visible. We want to save the timer id, to be able to call
|
||||||
|
// clearTimeout(timer) when the text has changed before finishing fading.
|
||||||
|
timer = window.setTimeout(function(){timer = null;}, 400);
|
||||||
|
}
|
||||||
|
|
||||||
|
function show_text_completed(){
|
||||||
|
return (timer == null);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<img id="bgimage" class="size" style="display:none;" />
|
||||||
|
<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 id="footer" class="footer"></div>
|
||||||
|
<div id="black" class="size"></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
"""
|
||||||
|
BACKGROUND_CSS_RADIAL = 'background: -webkit-gradient(radial, 5 50%, 100, 5 50%, 5, from(#000000), to(#FFFFFF)) fixed'
|
||||||
|
LYRICS_CSS = """
|
||||||
|
.lyricstable {
|
||||||
|
z-index: 5;
|
||||||
|
position: absolute;
|
||||||
|
display: table;
|
||||||
|
left: 10px; top: 20px;
|
||||||
|
}
|
||||||
|
.lyricscell {
|
||||||
|
display: table-cell;
|
||||||
|
word-wrap: break-word;
|
||||||
|
-webkit-transition: opacity 0.4s ease;
|
||||||
|
lyrics_format_css
|
||||||
|
}
|
||||||
|
.lyricsmain {
|
||||||
|
text-shadow: #000000 5px 5px;
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
LYRICS_OUTLINE_CSS = ' -webkit-text-stroke: 0.125em #000000; -webkit-text-fill-color: #FFFFFF; '
|
||||||
|
LYRICS_FORMAT_CSS = ' word-wrap: break-word; text-align: justify; vertical-align: bottom; ' + \
|
||||||
|
'font-family: Arial; font-size: 40pt; color: #FFFFFF; line-height: 108%; margin: 0;padding: 0; ' + \
|
||||||
|
'padding-bottom: 0.5em; padding-left: 2px; width: 1580px; height: 810px; font-style:italic; font-weight:bold; '
|
||||||
|
FOOTER_CSS = """
|
||||||
|
left: 10px;
|
||||||
|
bottom: 0px;
|
||||||
|
width: 1260px;
|
||||||
|
font-family: Arial;
|
||||||
|
font-size: 12pt;
|
||||||
|
color: #FFFFFF;
|
||||||
|
text-align: left;
|
||||||
|
white-space: nowrap;
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class Htmbuilder(TestCase):
|
||||||
|
def build_html_test(self):
|
||||||
|
"""
|
||||||
|
Test the build_html() function
|
||||||
|
"""
|
||||||
|
# GIVEN: Mocked arguments and function.
|
||||||
|
with patch('openlp.core.lib.htmlbuilder.build_background_css') as mocked_build_background_css, \
|
||||||
|
patch('openlp.core.lib.htmlbuilder.build_footer_css') as mocked_build_footer_css, \
|
||||||
|
patch('openlp.core.lib.htmlbuilder.build_lyrics_css') as mocked_build_lyrics_css:
|
||||||
|
# Mocked function.
|
||||||
|
mocked_build_background_css.return_value = ''
|
||||||
|
mocked_build_footer_css.return_value = 'dummy: dummy;'
|
||||||
|
mocked_build_lyrics_css.return_value = ''
|
||||||
|
# Mocked arguments.
|
||||||
|
item = MagicMock()
|
||||||
|
item.bg_image_bytes = None
|
||||||
|
screen = MagicMock()
|
||||||
|
is_live = False
|
||||||
|
background = None
|
||||||
|
plugin = MagicMock()
|
||||||
|
plugin.get_display_css = MagicMock(return_value='plugin CSS')
|
||||||
|
plugin.get_display_javascript = MagicMock(return_value='plugin JS')
|
||||||
|
plugin.get_display_html = MagicMock(return_value='plugin HTML')
|
||||||
|
plugins = [plugin]
|
||||||
|
|
||||||
|
# WHEN: Create the html.
|
||||||
|
html = build_html(item, screen, is_live, background, plugins=plugins)
|
||||||
|
|
||||||
|
# THEN: The returned html should match.
|
||||||
|
assert html == HTML
|
||||||
|
|
||||||
|
def build_background_css_radial_test(self):
|
||||||
|
"""
|
||||||
|
Test the build_background_css() function with a radial background
|
||||||
|
"""
|
||||||
|
# GIVEN: Mocked arguments.
|
||||||
|
item = MagicMock()
|
||||||
|
item.themedata.background_start_color = '#000000'
|
||||||
|
item.themedata.background_end_color = '#FFFFFF'
|
||||||
|
width = 10
|
||||||
|
|
||||||
|
# WHEN: Create the css.
|
||||||
|
css = build_background_css(item, width)
|
||||||
|
|
||||||
|
# THEN: The returned css should match.
|
||||||
|
assert BACKGROUND_CSS_RADIAL == css, 'The background css should be equal.'
|
||||||
|
|
||||||
|
def build_lyrics_css_test(self):
|
||||||
|
"""
|
||||||
|
Test the build_lyrics_css() function
|
||||||
|
"""
|
||||||
|
# GIVEN: Mocked method and arguments.
|
||||||
|
with patch('openlp.core.lib.htmlbuilder.build_lyrics_format_css') as mocked_build_lyrics_format_css, \
|
||||||
|
patch('openlp.core.lib.htmlbuilder.build_lyrics_outline_css') as mocked_build_lyrics_outline_css:
|
||||||
|
mocked_build_lyrics_format_css.return_value = 'lyrics_format_css'
|
||||||
|
mocked_build_lyrics_outline_css.return_value = ''
|
||||||
|
item = MagicMock()
|
||||||
|
item.main = QtCore.QRect(10, 20, 10, 20)
|
||||||
|
item.themedata.font_main_shadow = True
|
||||||
|
item.themedata.font_main_shadow_color = '#000000'
|
||||||
|
item.themedata.font_main_shadow_size = 5
|
||||||
|
|
||||||
|
# WHEN: Create the css.
|
||||||
|
css = build_lyrics_css(item)
|
||||||
|
|
||||||
|
# THEN: The css should be equal.
|
||||||
|
assert LYRICS_CSS == css, 'The lyrics css should be equal.'
|
||||||
|
|
||||||
|
def build_lyrics_outline_css_test(self):
|
||||||
|
"""
|
||||||
|
Test the build_lyrics_outline_css() function
|
||||||
|
"""
|
||||||
|
# GIVEN: The mocked theme data.
|
||||||
|
theme_data = MagicMock()
|
||||||
|
theme_data.font_main_outline = True
|
||||||
|
theme_data.font_main_outline_size = 2
|
||||||
|
theme_data.font_main_color = '#FFFFFF'
|
||||||
|
theme_data.font_main_outline_color = '#000000'
|
||||||
|
|
||||||
|
# WHEN: Create the css.
|
||||||
|
css = build_lyrics_outline_css(theme_data)
|
||||||
|
|
||||||
|
# THEN: The css should be equal.
|
||||||
|
assert LYRICS_OUTLINE_CSS == css, 'The outline css should be equal.'
|
||||||
|
|
||||||
|
def build_lyrics_format_css_test(self):
|
||||||
|
"""
|
||||||
|
Test the build_lyrics_format_css() function
|
||||||
|
"""
|
||||||
|
# GIVEN: Mocked arguments.
|
||||||
|
theme_data = MagicMock()
|
||||||
|
theme_data.display_horizontal_align = HorizontalType.Justify
|
||||||
|
theme_data.display_vertical_align = VerticalType.Bottom
|
||||||
|
theme_data.font_main_name = 'Arial'
|
||||||
|
theme_data.font_main_size = 40
|
||||||
|
theme_data.font_main_color = '#FFFFFF'
|
||||||
|
theme_data.font_main_italics = True
|
||||||
|
theme_data.font_main_bold = True
|
||||||
|
theme_data.font_main_line_adjustment = 8
|
||||||
|
width = 1580
|
||||||
|
height = 810
|
||||||
|
|
||||||
|
# WHEN: Get the css.
|
||||||
|
css = build_lyrics_format_css(theme_data, width, height)
|
||||||
|
|
||||||
|
# THEN: They should be equal.
|
||||||
|
assert LYRICS_FORMAT_CSS == css, 'The lyrics format css should be equal.'
|
||||||
|
|
||||||
|
def build_footer_css_test(self):
|
||||||
|
"""
|
||||||
|
Test the build_footer_css() function
|
||||||
|
"""
|
||||||
|
# GIVEN: Create a theme.
|
||||||
|
item = MagicMock()
|
||||||
|
item.footer = QtCore.QRect(10, 921, 1260, 103)
|
||||||
|
item.themedata.font_footer_name = 'Arial'
|
||||||
|
item.themedata.font_footer_size = 12
|
||||||
|
item.themedata.font_footer_color = '#FFFFFF'
|
||||||
|
height = 1024
|
||||||
|
|
||||||
|
# WHEN: create the css.
|
||||||
|
css = build_footer_css(item, height)
|
||||||
|
|
||||||
|
# THEN: THE css should be the same.
|
||||||
|
assert FOOTER_CSS == css, 'The footer strings should be equal.'
|
||||||
|
|
|
@ -30,8 +30,8 @@
|
||||||
Package to test the openlp.core.ui package.
|
Package to test the openlp.core.ui package.
|
||||||
"""
|
"""
|
||||||
import os
|
import os
|
||||||
from unittest import TestCase
|
|
||||||
|
|
||||||
|
from unittest import TestCase
|
||||||
from PyQt4 import QtGui
|
from PyQt4 import QtGui
|
||||||
|
|
||||||
from openlp.core.lib import Registry, ImageManager, ScreenList
|
from openlp.core.lib import Registry, ImageManager, ScreenList
|
||||||
|
|
|
@ -32,10 +32,13 @@ Package to test the openlp.core.lib package.
|
||||||
import os
|
import os
|
||||||
from unittest import TestCase
|
from unittest import TestCase
|
||||||
|
|
||||||
from openlp.core.lib import ItemCapabilities, ServiceItem, Registry
|
|
||||||
from tests.functional import MagicMock, patch
|
from tests.functional import MagicMock, patch
|
||||||
from tests.utils import assert_length, convert_file_service_item
|
from tests.utils import assert_length, convert_file_service_item
|
||||||
|
|
||||||
|
from openlp.core.lib import ItemCapabilities, ServiceItem, Registry
|
||||||
|
|
||||||
|
|
||||||
VERSE = 'The Lord said to {r}Noah{/r}: \n'\
|
VERSE = 'The Lord said to {r}Noah{/r}: \n'\
|
||||||
'There\'s gonna be a {su}floody{/su}, {sb}floody{/sb}\n'\
|
'There\'s gonna be a {su}floody{/su}, {sb}floody{/sb}\n'\
|
||||||
'The Lord said to {g}Noah{/g}:\n'\
|
'The Lord said to {g}Noah{/g}:\n'\
|
||||||
|
|
Loading…
Reference in New Issue