Alerts over presentations + tidyups

This commit is contained in:
Jonathan Corwin 2010-08-09 22:21:04 +01:00
parent 6c3f21dfb0
commit 51f35dc9ce
2 changed files with 178 additions and 208 deletions

View File

@ -33,33 +33,60 @@ HTMLSRC = u"""
<style> <style>
*{ *{
margin: 0; margin: 0;
padding:0 padding: 0;
border: 0;
} }
body { body {
background-color: black; background-color: black;
} }
.dim {
position: absolute;
left: 0px;
top: 0px;
width: %spx;
height: %spx;
}
#black {
z-index:8;
background-color: black;
display: none;
}
#video {
z-index:2;
}
#alert {
position: absolute;
left: 0px;
top: 0px;
z-index:10;
%s
}
#footer {
position: absolute;
z-index:5;
%s
}
/* lyric css */
%s %s
%s
%s
%s
%s
%s
%s
</style> </style>
<script language="javascript"> <script language="javascript">
var t = null; var timer = null;
var transition = %s; var transition = %s;
function video(state, path, volume, loop){ function show_video(state, path, volume, loop){
var vid = document.getElementById('video'); var vid = document.getElementById('video');
if(path!=null) if(path != null)
vid.src = path; vid.src = path;
if(loop!=null){ if(loop != null){
if(loop) if(loop)
vid.loop = 'loop'; vid.loop = 'loop';
else else
vid.loop = ''; vid.loop = '';
} }
if(volume != null){
vid.volume = volume;
}
switch(state){ switch(state){
case 'play': case 'play':
vid.play(); vid.play();
@ -76,22 +103,20 @@ body {
case 'close': case 'close':
vid.pause(); vid.pause();
vid.style.display = 'none'; vid.style.display = 'none';
vid.setAttribute('src', ''); vid.src = '';
break; break;
if(volume!=null)
vid.volume = volume;
} }
} }
function setImage(src){ function show_image(src){
var img = document.getElementById('image'); var img = document.getElementById('image');
img.src = src; img.src = src;
if(src=='') if(src == '')
img.style.display = 'none'; img.style.display = 'none';
else else
img.style.display = 'block'; img.style.display = 'block';
} }
function blankState(state){ function show_blank(state){
var black = 'none'; var black = 'none';
var lyrics = ''; var lyrics = '';
var pause = false; var pause = false;
@ -122,36 +147,39 @@ body {
} }
} }
function displayAlert(alerttext, shrink){ function show_alert(alerttext, position){
var text = document.getElementById('alert'); var text = document.getElementById('alert');
text.innerHTML = alerttext; text.innerHTML = alerttext;
if(alerttext=='') { if(alerttext == '') {
text.style.visibility = 'hidden'; text.style.visibility = 'hidden';
return 0; return 0;
} }
if(shrink){ if(position == ''){
text.style.top = '0px'; position = window.getComputedStyle(text, '').verticalAlign;
} }
else switch(position)
{ {
switch(window.getComputedStyle(text, '').verticalAlign) case 'top':
{ text.style.top = '0px';
case 'top': break;
text.style.top = '0px'; case 'middle':
break; text.style.top = ((window.innerHeight - text.clientHeight) / 2)
case 'middle': + 'px';
text.style.top = ((window.innerHeight - text.clientHeight) / 2) + 'px'; break;
break; case 'bottom':
case 'bottom': text.style.top = (window.innerHeight - text.clientHeight)
text.style.top = (window.innerHeight - text.clientHeight) + 'px'; + 'px';
break; break;
}
} }
text.style.visibility = 'visible'; text.style.visibility = 'visible';
return text.clientHeight; return text.clientHeight;
} }
function startfade(newtext){ function show_footer(text){
document.getElementById('footer').innerHTML(text);
}
function show_text(newtext){
var text1 = document.getElementById('lyricsmain'); var text1 = document.getElementById('lyricsmain');
var texto1 = document.getElementById('lyricsoutline'); var texto1 = document.getElementById('lyricsoutline');
var texts1 = document.getElementById('lyricsshadow'); var texts1 = document.getElementById('lyricsshadow');
@ -164,7 +192,8 @@ body {
var text2 = document.getElementById('lyricsmain2'); var text2 = document.getElementById('lyricsmain2');
var texto2 = document.getElementById('lyricsoutline2'); var texto2 = document.getElementById('lyricsoutline2');
var texts2 = document.getElementById('lyricsshadow2'); var texts2 = document.getElementById('lyricsshadow2');
if(text2.style.opacity==''||parseFloat(text2.style.opacity) < 0.5){ if((text2.style.opacity == '')||(parseFloat(text2.style.opacity) < 0.5))
{
text2.innerHTML = text1.innerHTML; text2.innerHTML = text1.innerHTML;
text2.style.opacity = text1.style.opacity; text2.style.opacity = text1.style.opacity;
texto2.innerHTML = text1.innerHTML; texto2.innerHTML = text1.innerHTML;
@ -178,15 +207,14 @@ body {
texto1.innerHTML = newtext; texto1.innerHTML = newtext;
texts1.style.opacity = 0; texts1.style.opacity = 0;
texts1.innerHTML = newtext; texts1.innerHTML = newtext;
// temp: // For performance reasons, we'll not animate the shadow for now
texts2.style.opacity = 0; texts2.style.opacity = 0;
// end temp if(timer != null)
if(t!=null) clearTimeout(timer);
clearTimeout(t); timer = setTimeout('text_fade()', 50);
t = setTimeout('fade()', 50);
} }
function fade(){ function text_fade(){
var text1 = document.getElementById('lyricsmain'); var text1 = document.getElementById('lyricsmain');
var texto1 = document.getElementById('lyricsoutline'); var texto1 = document.getElementById('lyricsoutline');
var texts1 = document.getElementById('lyricsshadow'); var texts1 = document.getElementById('lyricsshadow');
@ -196,16 +224,19 @@ body {
if(parseFloat(text1.style.opacity) < 1){ if(parseFloat(text1.style.opacity) < 1){
text1.style.opacity = parseFloat(text1.style.opacity) + 0.1; text1.style.opacity = parseFloat(text1.style.opacity) + 0.1;
texto1.style.opacity = parseFloat(texto1.style.opacity) + 0.1; texto1.style.opacity = parseFloat(texto1.style.opacity) + 0.1;
// Don't animate shadow (performance)
//texts1.style.opacity = parseFloat(texts1.style.opacity) + 0.1; //texts1.style.opacity = parseFloat(texts1.style.opacity) + 0.1;
} }
if(parseFloat(text2.style.opacity) > 0){ if(parseFloat(text2.style.opacity) > 0){
text2.style.opacity = parseFloat(text2.style.opacity) - 0.1; text2.style.opacity = parseFloat(text2.style.opacity) - 0.1;
texto2.style.opacity = parseFloat(texto2.style.opacity) - 0.1; texto2.style.opacity = parseFloat(texto2.style.opacity) - 0.1;
// Don't animate shadow (performance)
//texts2.style.opacity = parseFloat(texts2.style.opacity) - 0.1; //texts2.style.opacity = parseFloat(texts2.style.opacity) - 0.1;
} }
if((parseFloat(text1.style.opacity) < 1)||(parseFloat(text2.style.opacity) > 0)) if((parseFloat(text1.style.opacity) < 1) ||
t = setTimeout('fade()', 50); (parseFloat(text2.style.opacity) > 0)){
else{ t = setTimeout('text_fade()', 50);
} else {
text1.style.opacity = 1; text1.style.opacity = 1;
texto1.style.opacity = 1; texto1.style.opacity = 1;
texts1.style.opacity = 1; texts1.style.opacity = 1;
@ -215,12 +246,22 @@ body {
} }
} }
function fadeFinished(){ function show_text_complete(){
return (document.getElementById('lyricsmain').style.opacity==1); return (document.getElementById('lyricsmain').style.opacity == 1);
} }
</script> </script>
</head> </head>
<body> <body>
<!--
Using tables, rather than div's to make use of the vertical-align style that
doesn't work on div's. This avoids the need to do positioning manually which
could get messy when changing verses esp. with transitions
Would prefer to use a single table and make use of -webkit-text-fill-color
-webkit-text-stroke and text-shadow styles, but they have problems working/
co-operating in qwebkit. https://bugs.webkit.org/show_bug.cgi?id=43187
Therefore one table for text, one for outline and one for shadow.
-->
<table class="lyricstable lyricscommon"> <table class="lyricstable lyricscommon">
<tr><td id="lyricsmain" class="lyrics"></td></tr> <tr><td id="lyricsmain" class="lyrics"></td></tr>
</table> </table>
@ -239,18 +280,11 @@ body {
<table class="lyricsshadowtable lyricscommon"> <table class="lyricsshadowtable lyricscommon">
<tr><td id="lyricsshadow2" class="lyricsshadow lyrics"></td></tr> <tr><td id="lyricsshadow2" class="lyricsshadow lyrics"></td></tr>
</table> </table>
<!--
<table class="alerttable">
<tr><td class="alertcell">
<div class="alert" id="alertmain"></div>
</td></tr>
</table>
-->
<div id="alert" style="visibility:hidden;"></div> <div id="alert" style="visibility:hidden;"></div>
<div id="footer" class="footer"></div> <div id="footer" class="footer"></div>
<video id="video"></video> <video class="dim" id="video"></video>
<div id="black"></div> <div class="dim" id="black"></div>
%s <img class="dim" id="image" src="%s" />
</body> </body>
</html> </html>
""" """
@ -269,79 +303,17 @@ def build_html(item, screen, alert):
width = screen[u'size'].width() width = screen[u'size'].width()
height = screen[u'size'].height() height = screen[u'size'].height()
theme = item.themedata theme = item.themedata
html = HTMLSRC % (build_video(width, height), if item.bg_frame:
build_image(width, height), image = u'data:image/png;base64,%s' % image_to_byte(item.bg_frame)
build_lyrics(item),
build_footer(item),
build_alert(width, height, alert),
build_image(width, height),
build_black(width, height),
"true" if theme and
theme.display_slideTransition else "false",
build_image_src(item.bg_frame))
return html
def build_video(width, height):
"""
Build the video display div
`width`
Screen width
`height`
Screen height
"""
video = """
#video { position: absolute; left: 0px; top: 0px;
width: %spx; height: %spx; z-index:2; }
"""
return video % (width, height)
def build_black(width, height):
"""
Build the black display div
`width`
Screen width
`height`
Screen height
"""
black = """
#black { position: absolute; left: 0px; top: 0px;
width: %spx; height: %spx; z-index:8;
background-color: black; display: none;
}
"""
return black % (width, height)
def build_image(width, height):
"""
Build the image display div
`width`
Screen width
`height`
Screen height
"""
image = """
#image { position: absolute; left: 0px; top: 0px;
width: %spx; height: %spx; z-index:1;
}
"""
return image % (width, height)
def build_image_src(image):
"""
Build display for the backgroung image
`image`
Image to be displayed
"""
if image:
return '<img id="image" src="data:image/png;base64,%s" />' % \
image_to_byte(image)
else: else:
return '<img id="image" />' image = u''
html = HTMLSRC % (width, height,
build_alert(alert, width),
build_footer(item),
build_lyrics(item),
u'true' if theme and theme.display_slideTransition else u'false',
image)
return html
def build_lyrics(item): def build_lyrics(item):
""" """
@ -358,7 +330,6 @@ def build_lyrics(item):
.lyrics { %s } .lyrics { %s }
.lyricsoutline { %s } .lyricsoutline { %s }
.lyricsshadow { %s } .lyricsshadow { %s }
table {border=0; margin=0; padding=0; }
""" """
theme = item.themedata theme = item.themedata
lyricscommon = u'' lyricscommon = u''
@ -408,7 +379,6 @@ def build_lyrics(item):
shadow = u'color: %s;' % (theme.display_shadow_color) shadow = u'color: %s;' % (theme.display_shadow_color)
lyrics_html = style % (lyricscommon, lyricstable, outlinetable, lyrics_html = style % (lyricscommon, lyricstable, outlinetable,
shadowtable, lyrics, outline, shadow) shadowtable, lyrics, outline, shadow)
print lyrics_html
return lyrics_html return lyrics_html
def build_footer(item): def build_footer(item):
@ -418,64 +388,54 @@ def build_footer(item):
`item` `item`
Service Item to be processed. Service Item to be processed.
""" """
lyrics = """ style = """
#footer {position: absolute; %s z-index:5; %s; %s } left: %spx;
top: %spx;
width: %spx;
height: %spx;
font-family: %s;
font-size: %spx;
color: %s;
align: %s;
""" """
theme = item.themedata theme = item.themedata
lyrics_html = u'' if not theme:
position = u'' return u''
font = u'' if theme.display_horizontalAlign == 2:
text = u'' align = u'center'
if theme: elif theme.display_horizontalAlign == 1:
position = u' left: %spx; top: %spx; width: %spx; height: %spx; ' % \ align = u'right'
(item.footer.x(), item.footer.y(), item.footer.width(), else:
item.footer.height()) align = u'left'
font = u' font-family %s; font-size: %spx;' % \ lyrics_html = style % (item.footer.x(), item.footer.y(),
(theme.font_footer_name, theme.font_footer_proportion) item.footer.width(), item.footer.height(), theme.font_footer_name,
align = u'' theme.font_footer_proportion, theme.font_footer_color, align)
if theme.display_horizontalAlign == 2:
align = u'align:center;'
elif theme.display_horizontalAlign == 1:
align = u'align:right;'
text = u'color:%s; %s ' % (theme.font_footer_color, align)
lyrics_html = lyrics % (position, font, text)
return lyrics_html return lyrics_html
def build_alert(width, height, alertTab): def build_alert(alertTab, width):
""" """
Build the display of the footer Build the display of the footer
`width`
Screen Width
`height`
Screen height
`alertTab` `alertTab`
Details from the Alert tab for fonts etc Details from the Alert tab for fonts etc
""" """
style = """ style = """
.alerttable { position: absolute; z-index:10; left 0px; top 0px; %s } width: %s;
.alertcell { %s } vertical-align: %s;
.alert { %s } font-family %s;
""" font-size: %spx;
style2 = """ color: %s;
#alert {position: absolute; z-index:10; left 0px; top 0px; width: %spx; %s %s} background-color: %s;
""" """
alerttable = u'' if not alertTab:
alertcell = u'' return u''
alert = u'' align = u''
if alertTab: if alertTab.location == 2:
if alertTab.location == 2: align = u'bottom'
alertcell = u'vertical-align:bottom;' elif alertTab.location == 1:
elif alertTab.location == 1: align = u'middle'
alertcell = u'vertical-align:middle;' else:
else: align = u'top'
alertcell = u'vertical-align:top;' alert = style % (width, align, alertTab.font_face, alertTab.font_size,
alerttable = u'width: %spx; height: %spx; ' % (width, height) alertTab.font_color, alertTab.bg_color)
alert = u'font-family %s; font-size: %spx; color: %s; ' \ return alert
u'background-color: %s' % \
(alertTab.font_face, alertTab.font_size, alertTab.font_color,
alertTab.bg_color)
#alert_html = style % (alerttable, alertcell, alert)
alert_html = style2 % (width, alertcell, alert)
print alert_html
return alert_html

View File

@ -113,7 +113,7 @@ class MainDisplay(DisplayWidget):
self.page = self.webView.page() self.page = self.webView.page()
self.frame = self.page.mainFrame() self.frame = self.page.mainFrame()
QtCore.QObject.connect(self.webView, QtCore.QObject.connect(self.webView,
QtCore.SIGNAL(u'loadFinished(bool)'), self.loaded) QtCore.SIGNAL(u'loadFinished(bool)'), self.isLoaded)
self.frame.setScrollBarPolicy(QtCore.Qt.Vertical, self.frame.setScrollBarPolicy(QtCore.Qt.Vertical,
QtCore.Qt.ScrollBarAlwaysOff) QtCore.Qt.ScrollBarAlwaysOff)
self.frame.setScrollBarPolicy(QtCore.Qt.Horizontal, self.frame.setScrollBarPolicy(QtCore.Qt.Horizontal,
@ -162,11 +162,11 @@ class MainDisplay(DisplayWidget):
The slide text to be displayed The slide text to be displayed
""" """
log.debug(u'text') log.debug(u'text')
self.frame.evaluateJavaScript("startfade('" + self.frame.evaluateJavaScript(u'show_text("%s")' % \
slide.replace("\\", "\\\\").replace("\'", "\\\'") + "')") slide.replace(u'\\', u'\\\\').replace(u'\"', u'\\\"'))
return self.preview() return self.preview()
def alert(self, text, shrink=False): def alert(self, text):
""" """
Add the alert text Add the alert text
@ -174,15 +174,22 @@ class MainDisplay(DisplayWidget):
The slide text to be displayed The slide text to be displayed
""" """
log.debug(u'alert') log.debug(u'alert')
js = "displayAlert('" + \ if self.height() != self.screen[u'size'].height() \
text.replace("\\", "\\\\").replace("\'", "\\\'") + "', %s)" % \ or not self.isVisible():
('true' if shrink else 'false') shrink = True
else:
shrink = False
js = u'show_alert("%s", "%s")' % (
text.replace(u'\\', u'\\\\').replace(u'\"', u'\\\"'),
u'top' if shrink else u'')
height = self.frame.evaluateJavaScript(js) height = self.frame.evaluateJavaScript(js)
if shrink: if shrink:
if text: if text:
self.resize(self.width(), int(height.toString())) self.resize(self.width(), int(height.toString()))
self.setVisible(True)
else: else:
self.setGeometry(self.screen[u'size']) self.setGeometry(self.screen[u'size'])
self.setVisible(False)
def image(self, image): def image(self, image):
""" """
@ -203,10 +210,10 @@ class MainDisplay(DisplayWidget):
Display an image, as is. Display an image, as is.
""" """
if image: if image:
js = "setImage('" + \ js = u'show_image("data:image/png;base64,%s");' % \
u'data:image/png;base64,%s' % image_to_byte(image) + "');" image_to_byte(image)
else: else:
js = "setImage('');" js = u'show_image("");'
self.frame.evaluateJavaScript(js) self.frame.evaluateJavaScript(js)
def resetImage(self): def resetImage(self):
@ -222,35 +229,35 @@ class MainDisplay(DisplayWidget):
Used after Video plugin has changed the background Used after Video plugin has changed the background
""" """
log.debug(u'resetVideo') log.debug(u'resetVideo')
self.frame.evaluateJavaScript('video("close");') self.frame.evaluateJavaScript(u'show_video("close");')
def videoPlay(self): def videoPlay(self):
""" """
Responds to the request to play a loaded video Responds to the request to play a loaded video
""" """
log.debug(u'videoPlay') log.debug(u'videoPlay')
self.frame.evaluateJavaScript('video("play");') self.frame.evaluateJavaScript(u'show_video("play");')
def videoPause(self): def videoPause(self):
""" """
Responds to the request to pause a loaded video Responds to the request to pause a loaded video
""" """
log.debug(u'videoPause') log.debug(u'videoPause')
self.frame.evaluateJavaScript('video("pause");') self.frame.evaluateJavaScript(u'show_video("pause");')
def videoStop(self): def videoStop(self):
""" """
Responds to the request to stop a loaded video Responds to the request to stop a loaded video
""" """
log.debug(u'videoStop') log.debug(u'videoStop')
self.frame.evaluateJavaScript('video("stop");') self.frame.evaluateJavaScript(u'show_video("stop");')
def videoVolume(self, volume): def videoVolume(self, volume):
""" """
Changes the volume of a running video Changes the volume of a running video
""" """
log.debug(u'videoVolume %d' % volume) log.debug(u'videoVolume %d' % volume)
self.frame.evaluateJavaScript('video(null,null,%s);' % self.frame.evaluateJavaScript(u'show_video(null, null, %s);' %
str(float(volume)/float(10))) str(float(volume)/float(10)))
def video(self, videoPath, volume): def video(self, videoPath, volume):
@ -259,13 +266,12 @@ class MainDisplay(DisplayWidget):
""" """
log.debug(u'video') log.debug(u'video')
self.loaded = True self.loaded = True
js = 'video("play","%s",%s,true);' % \ js = u'show_video("play", "%s", %s, true);' % \
(videoPath.replace("\\", "\\\\"), str(float(volume)/float(10))) (videoPath.replace(u'\\', u'\\\\'), str(float(volume)/float(10)))
self.frame.evaluateJavaScript(js) self.frame.evaluateJavaScript(js)
print js
return self.preview() return self.preview()
def loaded(self): def isLoaded(self):
""" """
Called by webView event to show display is fully loaded Called by webView event to show display is fully loaded
""" """
@ -280,7 +286,7 @@ class MainDisplay(DisplayWidget):
# Wait for the fade to finish before geting the preview. # Wait for the fade to finish before geting the preview.
# Important otherwise preview will have incorrect text if at all ! # Important otherwise preview will have incorrect text if at all !
if self.serviceItem.themedata.display_slideTransition: if self.serviceItem.themedata.display_slideTransition:
while self.frame.evaluateJavaScript("fadeFinished()").toString() == u'false': while self.frame.evaluateJavaScript(u'show_text_complete()').toString() == u'false':
Receiver.send_message(u'openlp_process_events') Receiver.send_message(u'openlp_process_events')
# Wait for the webview to update before geting the preview. # Wait for the webview to update before geting the preview.
# Important otherwise first preview will miss the background ! # Important otherwise first preview will miss the background !
@ -295,7 +301,7 @@ class MainDisplay(DisplayWidget):
painter.end() painter.end()
# save preview for debugging # save preview for debugging
if log.isEnabledFor(logging.DEBUG): if log.isEnabledFor(logging.DEBUG):
preview.save("temp.png", "png") preview.save(u'temp.png', u'png')
return preview return preview
def buildHtml(self, serviceItem): def buildHtml(self, serviceItem):
@ -310,7 +316,13 @@ class MainDisplay(DisplayWidget):
html = build_html(self.serviceItem, self.screen, self.parent.alertTab) html = build_html(self.serviceItem, self.screen, self.parent.alertTab)
self.webView.setHtml(html) self.webView.setHtml(html)
if serviceItem.footer and serviceItem.foot_text: if serviceItem.footer and serviceItem.foot_text:
self.frame.findFirstElement('div#footer').setInnerXml(serviceItem.foot_text) self.footer(serviceItem.foot_text)
def footer(self, text):
log.debug(u'footer')
js = "show_footer('" + \
text.replace("\\", "\\\\").replace("\'", "\\\'") + "')"
self.frame.evaluateJavaScript(js)
def hideDisplay(self, mode=HideMode.Screen): def hideDisplay(self, mode=HideMode.Screen):
""" """
@ -318,15 +330,13 @@ class MainDisplay(DisplayWidget):
Store the images so they can be replaced when required Store the images so they can be replaced when required
""" """
log.debug(u'hideDisplay mode = %d', mode) log.debug(u'hideDisplay mode = %d', mode)
self.frame.evaluateJavaScript(
"document.getElementById('blank').style.visibility = 'visible'")
if mode == HideMode.Screen: if mode == HideMode.Screen:
self.frame.evaluateJavaScript('blankState("desktop");') self.frame.evaluateJavaScript(u'show_blank("desktop");')
self.setVisible(False) self.setVisible(False)
elif mode == HideMode.Blank or self.initialFrame: elif mode == HideMode.Blank or self.initialFrame:
self.frame.evaluateJavaScript('blankState("black");') self.frame.evaluateJavaScript(u'show_blank("black");')
else: else:
self.frame.evaluateJavaScript('blankState("theme");') self.frame.evaluateJavaScript(u'show_blank("theme");')
if mode != HideMode.Screen and self.isHidden(): if mode != HideMode.Screen and self.isHidden():
self.setVisible(True) self.setVisible(True)
@ -337,7 +347,7 @@ class MainDisplay(DisplayWidget):
Make the stored images None to release memory. Make the stored images None to release memory.
""" """
log.debug(u'showDisplay') log.debug(u'showDisplay')
self.frame.evaluateJavaScript('blankState("show");') self.frame.evaluateJavaScript('show_blank("show");')
if self.isHidden(): if self.isHidden():
self.setVisible(True) self.setVisible(True)
# Trigger actions when display is active again # Trigger actions when display is active again