Merge lp:~alisonken1/openlp/strings-templates2 into lp:openlp

Proposed by Ken Roberts
Status: Merged
Approved by: Tim Bentley
Approved revision: 2680
Merged at revision: 2675
Proposed branch: lp:~alisonken1/openlp/strings-templates2
Merge into: lp:openlp
Diff against target: 923 lines (+409/-398)
5 files modified
openlp/core/lib/htmlbuilder.py (+224/-226)
openlp/core/ui/firsttimeform.py (+3/-3)
openlp/plugins/bibles/forms/editbibledialog.py (+1/-1)
openlp/plugins/songs/lib/mediaitem.py (+1/-1)
tests/functional/openlp_core_lib/test_htmlbuilder.py (+180/-167)
To merge this branch: bzr merge lp:~alisonken1/openlp/strings-templates2
Reviewer Review Type Date Requested Status
Tim Bentley Approve
Tomas Groth Approve
Review via email: mp+296870@code.launchpad.net

This proposal supersedes a proposal from 2016-06-08.

Commit message

Convert htmlbuilder.py to use Template() strings for css

Description of the change

Convert htmlbuilder.py to use Template() strings for css

- Changed strings to use Template() instead of format() for css building
- Fix htmlbuilder strings tests
- Cleanup template variables and fix tests to match
- bug 1590386 - string format error in editbibledialog.py
- bug 1590475 - string format error in mediaitem.py
- Function call error in firsttimeform.py (missed label text variable)

--------------------------------
lp:~alisonken1/openlp/strings-templates2 (revision 2679)
[SUCCESS] https://ci.openlp.io/job/Branch-01-Pull/1609/
[SUCCESS] https://ci.openlp.io/job/Branch-02-Functional-Tests/1520/
[SUCCESS] https://ci.openlp.io/job/Branch-03-Interface-Tests/1458/
[SUCCESS] https://ci.openlp.io/job/Branch-04a-Windows_Functional_Tests/1230/
[SUCCESS] https://ci.openlp.io/job/Branch-04b-Windows_Interface_Tests/820/
[SUCCESS] https://ci.openlp.io/job/Branch-05a-Code_Analysis/888/
[SUCCESS] https://ci.openlp.io/job/Branch-05b-Test_Coverage/756/

To post a comment you must log in.
Revision history for this message
Tim Bentley (trb143) wrote : Posted in a previous version of this proposal

Looks good but one comment which is general across all the code.

review: Needs Fixing
Revision history for this message
Ken Roberts (alisonken1) wrote : Posted in a previous version of this proposal

Since this is HTML/css source and not just any text variable I followed the
formatting the original HTML SRC. Has something changed since the original
was put in?
On Jun 6, 2016 9:12 AM, "Tim Bentley" <email address hidden> wrote:

> Review: Needs Fixing
>
> Looks good but one comment which is general across all the code.
>
> Diff comments:
>
> > === modified file 'openlp/core/lib/htmlbuilder.py'
> > --- openlp/core/lib/htmlbuilder.py 2016-05-17 13:21:29 +0000
> > +++ openlp/core/lib/htmlbuilder.py 2016-06-06 15:26:06 +0000
> > @@ -538,15 +538,60 @@
> > </script>
> > </head>
> > <body>
> > -<img id="bgimage" class="size" %s />
> > -<img id="image" class="size" %s />
> > -%s
> > +<img id="bgimage" class="size" ${bg_image} />
> > +<img id="image" class="size" ${image} />
> > +${html_additions}
> > <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>
> > -"""
> > +""")
> > +
> > +LYRICS_SRC = Template("""
> > +.lyricstable {
> > + z-index: 5;
> > + position: absolute;
> > + display: table;
> > + ${stable}
> > +}
> > +.lyricscell {
> > + display: table-cell;
> > + word-wrap: break-word;
> > + -webkit-transition: opacity 0.4s ease;
> > + ${lyrics}
> > +}
> > +.lyricsmain {
> > + ${main}
> > +}
> > +""")
> > +
> > +FOOTER_SRC = Template("""
>
> Indent please.
> No real rule about indentation but Lyrics_src looks better!
>
> > +left: ${left}px;
> > +bottom: ${bottom}px;
> > +width: ${width}px;
> > +font-family: ${family};
> > +font-size: ${size}pt;
> > +color: ${color};
> > +text-align: left;
> > +white-space: ${space};
> > +""")
> > +
> > +LYRICS_FORMAT_SRC = Template("""
> > +${justify}word-wrap: break-word;
> > +text-align: ${align};
> > +vertical-align: ${valign};
> > +font-family: ${font};
> > +font-size: ${size}pt;
> > +color: ${color};
> > +line-height: ${line}%;
> > +margin: 0;
> > +padding: 0;
> > +padding-bottom: ${bottom};
> > +padding-left: ${left}px;
> > +width: ${width}px;
> > +height: ${height}px;${font_style}${font_weight}
> > +""")
> >
> >
> > def build_html(item, screen, is_live, background, image=None,
> plugins=None):
>
>
> --
>
> https://code.launchpad.net/~alisonken1/openlp/strings-templates2/+merge/296567
> You are the owner of lp:~alisonken1/openlp/strings-templates2.
>

Revision history for this message
Tim Bentley (trb143) wrote : Posted in a previous version of this proposal

No it just looks a bit cramped and could do with a visit to a beauty spar😁
On 7 Jun 2016 1:42 a.m., "Ken Roberts" <email address hidden> wrote:

> Since this is HTML/css source and not just any text variable I followed the
> formatting the original HTML SRC. Has something changed since the original
> was put in?
> On Jun 6, 2016 9:12 AM, "Tim Bentley" <email address hidden> wrote:
>
> > Review: Needs Fixing
> >
> > Looks good but one comment which is general across all the code.
> >
> > Diff comments:
> >
> > > === modified file 'openlp/core/lib/htmlbuilder.py'
> > > --- openlp/core/lib/htmlbuilder.py 2016-05-17 13:21:29 +0000
> > > +++ openlp/core/lib/htmlbuilder.py 2016-06-06 15:26:06 +0000
> > > @@ -538,15 +538,60 @@
> > > </script>
> > > </head>
> > > <body>
> > > -<img id="bgimage" class="size" %s />
> > > -<img id="image" class="size" %s />
> > > -%s
> > > +<img id="bgimage" class="size" ${bg_image} />
> > > +<img id="image" class="size" ${image} />
> > > +${html_additions}
> > > <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>
> > > -"""
> > > +""")
> > > +
> > > +LYRICS_SRC = Template("""
> > > +.lyricstable {
> > > + z-index: 5;
> > > + position: absolute;
> > > + display: table;
> > > + ${stable}
> > > +}
> > > +.lyricscell {
> > > + display: table-cell;
> > > + word-wrap: break-word;
> > > + -webkit-transition: opacity 0.4s ease;
> > > + ${lyrics}
> > > +}
> > > +.lyricsmain {
> > > + ${main}
> > > +}
> > > +""")
> > > +
> > > +FOOTER_SRC = Template("""
> >
> > Indent please.
> > No real rule about indentation but Lyrics_src looks better!
> >
> > > +left: ${left}px;
> > > +bottom: ${bottom}px;
> > > +width: ${width}px;
> > > +font-family: ${family};
> > > +font-size: ${size}pt;
> > > +color: ${color};
> > > +text-align: left;
> > > +white-space: ${space};
> > > +""")
> > > +
> > > +LYRICS_FORMAT_SRC = Template("""
> > > +${justify}word-wrap: break-word;
> > > +text-align: ${align};
> > > +vertical-align: ${valign};
> > > +font-family: ${font};
> > > +font-size: ${size}pt;
> > > +color: ${color};
> > > +line-height: ${line}%;
> > > +margin: 0;
> > > +padding: 0;
> > > +padding-bottom: ${bottom};
> > > +padding-left: ${left}px;
> > > +width: ${width}px;
> > > +height: ${height}px;${font_style}${font_weight}
> > > +""")
> > >
> > >
> > > def build_html(item, screen, is_live, background, image=None,
> > plugins=None):
> >
> >
> > --
> >
> >
> https://code.launchpad.net/~alisonken1/openlp/strings-templates2/+merge/296567
> > You are the owner of lp:~alisonken1/openlp/strings-templates2.
> >
>
> --
>
> https://code.launchpad.net/~alisonken1/openlp/strings-templates2/+merge/296567
> You are reviewing the proposed merge of
> lp:~alisonken1/openlp/strings-templates2 into lp:openlp.
>

Revision history for this message
Tim Bentley (trb143) : Posted in a previous version of this proposal
review: Approve
2680. By Ken Roberts

String format oops

Revision history for this message
Ken Roberts (alisonken1) wrote :

Ignore last commit (2680) - fixed in strings_template and reverted in this branch

Revision history for this message
Tomas Groth (tomasgroth) wrote :

Looks ok to me

review: Approve
Revision history for this message
Tim Bentley (trb143) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'openlp/core/lib/htmlbuilder.py'
--- openlp/core/lib/htmlbuilder.py 2016-05-17 13:21:29 +0000
+++ openlp/core/lib/htmlbuilder.py 2016-06-09 02:57:58 +0000
@@ -390,163 +390,207 @@
390import logging390import logging
391391
392from PyQt5 import QtWebKit392from PyQt5 import QtWebKit
393from string import Template
393394
394from openlp.core.common import Settings395from openlp.core.common import Settings
395from openlp.core.lib.theme import BackgroundType, BackgroundGradientType, VerticalType, HorizontalType396from openlp.core.lib.theme import BackgroundType, BackgroundGradientType, VerticalType, HorizontalType
396397
397log = logging.getLogger(__name__)398log = logging.getLogger(__name__)
398399
399# TODO: Verify where this is used before converting to python3400HTML_SRC = Template("""
400HTMLSRC = """401 <!DOCTYPE html>
401<!DOCTYPE html>402 <html>
402<html>403 <head>
403<head>404 <title>OpenLP Display</title>
404<title>OpenLP Display</title>405 <style>
405<style>406 *{
406*{407 margin: 0;
408 padding: 0;
409 border: 0;
410 overflow: hidden;
411 -webkit-user-select: none;
412 }
413 body {
414 ${bg_css};
415 }
416 .size {
417 position: absolute;
418 left: 0px;
419 top: 0px;
420 width: 100%;
421 height: 100%;
422 }
423 #black {
424 z-index: 8;
425 background-color: black;
426 display: none;
427 }
428 #bgimage {
429 z-index: 1;
430 }
431 #image {
432 z-index: 2;
433 }
434 ${css_additions}
435 #footer {
436 position: absolute;
437 z-index: 6;
438 ${footer_css}
439 }
440 /* lyric css */${lyrics_css}
441 sup {
442 font-size: 0.6em;
443 vertical-align: top;
444 position: relative;
445 top: -0.3em;
446 }
447 </style>
448 <script>
449 var timer = null;
450 var transition = ${transitions};
451 ${js_additions}
452
453 function show_image(src){
454 var img = document.getElementById('image');
455 img.src = src;
456 if(src == '')
457 img.style.display = 'none';
458 else
459 img.style.display = 'block';
460 }
461
462 function show_blank(state){
463 var black = 'none';
464 var lyrics = '';
465 switch(state){
466 case 'theme':
467 lyrics = 'hidden';
468 break;
469 case 'black':
470 black = 'block';
471 break;
472 case 'desktop':
473 break;
474 }
475 document.getElementById('black').style.display = black;
476 document.getElementById('lyricsmain').style.visibility = lyrics;
477 document.getElementById('image').style.visibility = lyrics;
478 document.getElementById('footer').style.visibility = lyrics;
479 }
480
481 function show_footer(footertext){
482 document.getElementById('footer').innerHTML = footertext;
483 }
484
485 function show_text(new_text){
486 var match = /-webkit-text-fill-color:[^;\"]+/gi;
487 if(timer != null)
488 clearTimeout(timer);
489 /*
490 QtWebkit bug with outlines and justify causing outline alignment
491 problems. (Bug 859950) Surround each word with a <span> to workaround,
492 but only in this scenario.
493 */
494 var txt = document.getElementById('lyricsmain');
495 if(window.getComputedStyle(txt).textAlign == 'justify'){
496 if(window.getComputedStyle(txt).webkitTextStrokeWidth != '0px'){
497 new_text = new_text.replace(/(\s|&nbsp;)+(?![^<]*>)/g,
498 function(match) {
499 return '</span>' + match + '<span>';
500 });
501 new_text = '<span>' + new_text + '</span>';
502 }
503 }
504 text_fade('lyricsmain', new_text);
505 }
506
507 function text_fade(id, new_text){
508 /*
509 Show the text.
510 */
511 var text = document.getElementById(id);
512 if(text == null) return;
513 if(!transition){
514 text.innerHTML = new_text;
515 return;
516 }
517 // Fade text out. 0.1 to minimize the time "nothing" is shown on the screen.
518 text.style.opacity = '0.1';
519 // Fade new text in after the old text has finished fading out.
520 timer = window.setTimeout(function(){_show_text(text, new_text)}, 400);
521 }
522
523 function _show_text(text, new_text) {
524 /*
525 Helper function to show the new_text delayed.
526 */
527 text.innerHTML = new_text;
528 text.style.opacity = '1';
529 // Wait until the text is completely visible. We want to save the timer id, to be able to call
530 // clearTimeout(timer) when the text has changed before finishing fading.
531 timer = window.setTimeout(function(){timer = null;}, 400);
532 }
533
534 function show_text_completed(){
535 return (timer == null);
536 }
537 </script>
538 </head>
539 <body>
540 <img id="bgimage" class="size" ${bg_image} />
541 <img id="image" class="size" ${image} />
542 ${html_additions}
543 <div class="lyricstable"><div id="lyricsmain" style="opacity:1" class="lyricscell lyricsmain"></div></div>
544 <div id="footer" class="footer"></div>
545 <div id="black" class="size"></div>
546 </body>
547 </html>
548 """)
549
550LYRICS_SRC = Template("""
551 .lyricstable {
552 z-index: 5;
553 position: absolute;
554 display: table;
555 ${stable}
556 }
557 .lyricscell {
558 display: table-cell;
559 word-wrap: break-word;
560 -webkit-transition: opacity 0.4s ease;
561 ${lyrics}
562 }
563 .lyricsmain {
564 ${main}
565 }
566 """)
567
568FOOTER_SRC = Template("""
569 left: ${left}px;
570 bottom: ${bottom}px;
571 width: ${width}px;
572 font-family: ${family};
573 font-size: ${size}pt;
574 color: ${color};
575 text-align: left;
576 white-space: ${space};
577 """)
578
579LYRICS_FORMAT_SRC = Template("""
580 ${justify}word-wrap: break-word;
581 text-align: ${align};
582 vertical-align: ${valign};
583 font-family: ${font};
584 font-size: ${size}pt;
585 color: ${color};
586 line-height: ${line}%;
407 margin: 0;587 margin: 0;
408 padding: 0;588 padding: 0;
409 border: 0;589 padding-bottom: ${bottom};
410 overflow: hidden;590 padding-left: ${left}px;
411 -webkit-user-select: none;591 width: ${width}px;
412}592 height: ${height}px;${font_style}${font_weight}
413body {593 """)
414 %s;
415}
416.size {
417 position: absolute;
418 left: 0px;
419 top: 0px;
420 width: 100%%;
421 height: 100%%;
422}
423#black {
424 z-index: 8;
425 background-color: black;
426 display: none;
427}
428#bgimage {
429 z-index: 1;
430}
431#image {
432 z-index: 2;
433}
434%s
435#footer {
436 position: absolute;
437 z-index: 6;
438 %s
439}
440/* lyric css */
441%s
442sup {
443 font-size: 0.6em;
444 vertical-align: top;
445 position: relative;
446 top: -0.3em;
447}
448</style>
449<script>
450 var timer = null;
451 var transition = %s;
452 %s
453
454 function show_image(src){
455 var img = document.getElementById('image');
456 img.src = src;
457 if(src == '')
458 img.style.display = 'none';
459 else
460 img.style.display = 'block';
461 }
462
463 function show_blank(state){
464 var black = 'none';
465 var lyrics = '';
466 switch(state){
467 case 'theme':
468 lyrics = 'hidden';
469 break;
470 case 'black':
471 black = 'block';
472 break;
473 case 'desktop':
474 break;
475 }
476 document.getElementById('black').style.display = black;
477 document.getElementById('lyricsmain').style.visibility = lyrics;
478 document.getElementById('image').style.visibility = lyrics;
479 document.getElementById('footer').style.visibility = lyrics;
480 }
481
482 function show_footer(footertext){
483 document.getElementById('footer').innerHTML = footertext;
484 }
485
486 function show_text(new_text){
487 var match = /-webkit-text-fill-color:[^;\"]+/gi;
488 if(timer != null)
489 clearTimeout(timer);
490 /*
491 QtWebkit bug with outlines and justify causing outline alignment
492 problems. (Bug 859950) Surround each word with a <span> to workaround,
493 but only in this scenario.
494 */
495 var txt = document.getElementById('lyricsmain');
496 if(window.getComputedStyle(txt).textAlign == 'justify'){
497 if(window.getComputedStyle(txt).webkitTextStrokeWidth != '0px'){
498 new_text = new_text.replace(/(\s|&nbsp;)+(?![^<]*>)/g,
499 function(match) {
500 return '</span>' + match + '<span>';
501 });
502 new_text = '<span>' + new_text + '</span>';
503 }
504 }
505 text_fade('lyricsmain', new_text);
506 }
507
508 function text_fade(id, new_text){
509 /*
510 Show the text.
511 */
512 var text = document.getElementById(id);
513 if(text == null) return;
514 if(!transition){
515 text.innerHTML = new_text;
516 return;
517 }
518 // Fade text out. 0.1 to minimize the time "nothing" is shown on the screen.
519 text.style.opacity = '0.1';
520 // Fade new text in after the old text has finished fading out.
521 timer = window.setTimeout(function(){_show_text(text, new_text)}, 400);
522 }
523
524 function _show_text(text, new_text) {
525 /*
526 Helper function to show the new_text delayed.
527 */
528 text.innerHTML = new_text;
529 text.style.opacity = '1';
530 // Wait until the text is completely visible. We want to save the timer id, to be able to call
531 // clearTimeout(timer) when the text has changed before finishing fading.
532 timer = window.setTimeout(function(){timer = null;}, 400);
533 }
534
535 function show_text_completed(){
536 return (timer == null);
537 }
538</script>
539</head>
540<body>
541<img id="bgimage" class="size" %s />
542<img id="image" class="size" %s />
543%s
544<div class="lyricstable"><div id="lyricsmain" style="opacity:1" class="lyricscell lyricsmain"></div></div>
545<div id="footer" class="footer"></div>
546<div id="black" class="size"></div>
547</body>
548</html>
549"""
550594
551595
552def build_html(item, screen, is_live, background, image=None, plugins=None):596def build_html(item, screen, is_live, background, image=None, plugins=None):
@@ -582,18 +626,17 @@
582 css_additions += plugin.get_display_css()626 css_additions += plugin.get_display_css()
583 js_additions += plugin.get_display_javascript()627 js_additions += plugin.get_display_javascript()
584 html_additions += plugin.get_display_html()628 html_additions += plugin.get_display_html()
585 html = HTMLSRC % (629 return HTML_SRC.substitute(bg_css=build_background_css(item, width),
586 build_background_css(item, width),630 css_additions=css_additions,
587 css_additions,631 footer_css=build_footer_css(item, height),
588 build_footer_css(item, height),632 lyrics_css=build_lyrics_css(item),
589 build_lyrics_css(item),633 transitions='true' if (theme_data and
590 'true' if theme_data and theme_data.display_slide_transition and is_live else 'false',634 theme_data.display_slide_transition and
591 js_additions,635 is_live) else 'false',
592 bgimage_src,636 js_additions=js_additions,
593 image_src,637 bg_image=bgimage_src,
594 html_additions638 image=image_src,
595 )639 html_additions=html_additions)
596 return html
597640
598641
599def webkit_version():642def webkit_version():
@@ -650,24 +693,6 @@
650693
651 :param item: Service Item containing theme and location information694 :param item: Service Item containing theme and location information
652 """695 """
653 # TODO: Verify this before converting to python3
654 style = """
655.lyricstable {
656 z-index: 5;
657 position: absolute;
658 display: table;
659 %s
660}
661.lyricscell {
662 display: table-cell;
663 word-wrap: break-word;
664 -webkit-transition: opacity 0.4s ease;
665 %s
666}
667.lyricsmain {
668 %s
669}
670"""
671 theme_data = item.theme_data696 theme_data = item.theme_data
672 lyricstable = ''697 lyricstable = ''
673 lyrics = ''698 lyrics = ''
@@ -680,8 +705,7 @@
680 lyricsmain += ' text-shadow: {theme} {shadow}px ' \705 lyricsmain += ' text-shadow: {theme} {shadow}px ' \
681 '{shadow}px;'.format(theme=theme_data.font_main_shadow_color,706 '{shadow}px;'.format(theme=theme_data.font_main_shadow_color,
682 shadow=theme_data.font_main_shadow_size)707 shadow=theme_data.font_main_shadow_size)
683 lyrics_css = style % (lyricstable, lyrics, lyricsmain)708 return LYRICS_SRC.substitute(stable=lyricstable, lyrics=lyrics, main=lyricsmain)
684 return lyrics_css
685709
686710
687def build_lyrics_outline_css(theme_data):711def build_lyrics_outline_css(theme_data):
@@ -710,38 +734,23 @@
710 """734 """
711 align = HorizontalType.Names[theme_data.display_horizontal_align]735 align = HorizontalType.Names[theme_data.display_horizontal_align]
712 valign = VerticalType.Names[theme_data.display_vertical_align]736 valign = VerticalType.Names[theme_data.display_vertical_align]
713 if theme_data.font_main_outline:737 left_margin = (int(theme_data.font_main_outline_size) * 2) if theme_data.font_main_outline else 0
714 left_margin = int(theme_data.font_main_outline_size) * 2
715 else:
716 left_margin = 0
717 justify = 'white-space:pre-wrap;'
718 # fix tag incompatibilities738 # fix tag incompatibilities
719 if theme_data.display_horizontal_align == HorizontalType.Justify:739 justify = '' if (theme_data.display_horizontal_align == HorizontalType.Justify) else ' white-space: pre-wrap;\n'
720 justify = ''740 padding_bottom = '0.5em' if (theme_data.display_vertical_align == VerticalType.Bottom) else '0'
721 if theme_data.display_vertical_align == VerticalType.Bottom:741 return LYRICS_FORMAT_SRC.substitute(justify=justify,
722 padding_bottom = '0.5em'742 align=align,
723 else:743 valign=valign,
724 padding_bottom = '0'744 font=theme_data.font_main_name,
725 lyrics = '{justify} word-wrap: break-word; ' \745 size=theme_data.font_main_size,
726 'text-align: {align}; vertical-align: {valign}; font-family: {font}; ' \746 color=theme_data.font_main_color,
727 'font-size: {size}pt; color: {color}; line-height: {line:d}%; margin: 0;' \747 line='{line:d}'.format(line=100 + int(theme_data.font_main_line_adjustment)),
728 'padding: 0; padding-bottom: {bottom}; padding-left: {left}px; width: {width}px; ' \748 bottom=padding_bottom,
729 'height: {height}px; '.format(justify=justify,749 left=left_margin,
730 align=align,750 width=width,
731 valign=valign,751 height=height,
732 font=theme_data.font_main_name,752 font_style='\n font-style: italic;' if theme_data.font_main_italics else '',
733 size=theme_data.font_main_size,753 font_weight='\n font-weight: bold;' if theme_data.font_main_bold else '')
734 color=theme_data.font_main_color,
735 line=100 + int(theme_data.font_main_line_adjustment),
736 bottom=padding_bottom,
737 left=left_margin,
738 width=width,
739 height=height)
740 if theme_data.font_main_italics:
741 lyrics += 'font-style:italic; '
742 if theme_data.font_main_bold:
743 lyrics += 'font-weight:bold; '
744 return lyrics
745754
746755
747def build_footer_css(item, height):756def build_footer_css(item, height):
@@ -751,22 +760,11 @@
751 :param item: Service Item to be processed.760 :param item: Service Item to be processed.
752 :param height:761 :param height:
753 """762 """
754 style = """
755 left: {left}px;
756 bottom: {bottom}px;
757 width: {width}px;
758 font-family: {family};
759 font-size: {size}pt;
760 color: {color};
761 text-align: left;
762 white-space: {space};
763 """
764 theme = item.theme_data763 theme = item.theme_data
765 if not theme or not item.footer:764 if not theme or not item.footer:
766 return ''765 return ''
767 bottom = height - int(item.footer.y()) - int(item.footer.height())766 bottom = height - int(item.footer.y()) - int(item.footer.height())
768 whitespace = 'normal' if Settings().value('themes/wrap footer') else 'nowrap'767 whitespace = 'normal' if Settings().value('themes/wrap footer') else 'nowrap'
769 lyrics_html = style.format(left=item.footer.x(), bottom=bottom, width=item.footer.width(),768 return FOOTER_SRC.substitute(left=item.footer.x(), bottom=bottom, width=item.footer.width(),
770 family=theme.font_footer_name, size=theme.font_footer_size,769 family=theme.font_footer_name, size=theme.font_footer_size,
771 color=theme.font_footer_color, space=whitespace)770 color=theme.font_footer_color, space=whitespace)
772 return lyrics_html
773771
=== modified file 'openlp/core/ui/firsttimeform.py'
--- openlp/core/ui/firsttimeform.py 2016-05-20 16:22:06 +0000
+++ openlp/core/ui/firsttimeform.py 2016-06-09 02:57:58 +0000
@@ -565,13 +565,13 @@
565 if self.has_run_wizard:565 if self.has_run_wizard:
566 text = translate('OpenLP.FirstTimeWizard',566 text = translate('OpenLP.FirstTimeWizard',
567 'Download complete. Click the {button} button to return to OpenLP.'567 'Download complete. Click the {button} button to return to OpenLP.'
568 ).format(text=clean_button_text(self.buttonText(QtWidgets.QWizard.FinishButton)))568 ).format(button=clean_button_text(self.buttonText(QtWidgets.QWizard.FinishButton)))
569 self.progress_label.setText(text)569 self.progress_label.setText(text)
570 else:570 else:
571 text = translate('OpenLP.FirstTimeWizard',571 text = translate('OpenLP.FirstTimeWizard',
572 'Download complete. Click the {button} button to start OpenLP.'572 'Download complete. Click the {button} button to start OpenLP.'
573 ).format(button=clean_button_text(self.buttonText(QtWidgets.QWizard.FinishButton)))573 ).format(button=clean_button_text(self.buttonText(QtWidgets.QWizard.FinishButton)))
574 self.progress_label.setText()574 self.progress_label.setText(text)
575 else:575 else:
576 if self.has_run_wizard:576 if self.has_run_wizard:
577 text = translate('OpenLP.FirstTimeWizard',577 text = translate('OpenLP.FirstTimeWizard',
@@ -582,7 +582,7 @@
582 text = translate('OpenLP.FirstTimeWizard',582 text = translate('OpenLP.FirstTimeWizard',
583 'Click the {button} button to start OpenLP.'583 'Click the {button} button to start OpenLP.'
584 ).format(button=clean_button_text(self.buttonText(QtWidgets.QWizard.FinishButton)))584 ).format(button=clean_button_text(self.buttonText(QtWidgets.QWizard.FinishButton)))
585 self.progress_label.setText()585 self.progress_label.setText(text)
586 self.finish_button.setVisible(True)586 self.finish_button.setVisible(True)
587 self.finish_button.setEnabled(True)587 self.finish_button.setEnabled(True)
588 self.cancel_button.setVisible(False)588 self.cancel_button.setVisible(False)
589589
=== modified file 'openlp/plugins/bibles/forms/editbibledialog.py'
--- openlp/plugins/bibles/forms/editbibledialog.py 2016-05-21 08:31:24 +0000
+++ openlp/plugins/bibles/forms/editbibledialog.py 2016-06-09 02:57:58 +0000
@@ -104,7 +104,7 @@
104 for book in BiblesResourcesDB.get_books():104 for book in BiblesResourcesDB.get_books():
105 self.book_name_label[book['abbreviation']] = QtWidgets.QLabel(self.book_name_widget)105 self.book_name_label[book['abbreviation']] = QtWidgets.QLabel(self.book_name_widget)
106 self.book_name_label[book['abbreviation']].setObjectName(106 self.book_name_label[book['abbreviation']].setObjectName(
107 'book_name_label[{name}]'.format(book=book['abbreviation']))107 'book_name_label[{book}]'.format(book=book['abbreviation']))
108 self.book_name_edit[book['abbreviation']] = QtWidgets.QLineEdit(self.book_name_widget)108 self.book_name_edit[book['abbreviation']] = QtWidgets.QLineEdit(self.book_name_widget)
109 self.book_name_edit[book['abbreviation']].setObjectName(109 self.book_name_edit[book['abbreviation']].setObjectName(
110 'book_name_edit[{name}]'.format(name=book['abbreviation']))110 'book_name_edit[{name}]'.format(name=book['abbreviation']))
111111
=== modified file 'openlp/plugins/songs/lib/mediaitem.py'
--- openlp/plugins/songs/lib/mediaitem.py 2016-05-27 08:13:14 +0000
+++ openlp/plugins/songs/lib/mediaitem.py 2016-06-09 02:57:58 +0000
@@ -603,7 +603,7 @@
603 else:603 else:
604 verse_index = VerseType.from_tag(verse[0]['type'])604 verse_index = VerseType.from_tag(verse[0]['type'])
605 verse_tag = VerseType.translated_tags[verse_index]605 verse_tag = VerseType.translated_tags[verse_index]
606 verse_def = '{tag}{label}'.format(tzg=verse_tag, text=verse[0]['label'])606 verse_def = '{tag}{text}'.format(tag=verse_tag, text=verse[0]['label'])
607 service_item.add_from_text(verse[1], verse_def)607 service_item.add_from_text(verse[1], verse_def)
608 service_item.title = song.title608 service_item.title = song.title
609 author_list = self.generate_footer(service_item, song)609 author_list = self.generate_footer(service_item, song)
610610
=== modified file 'tests/functional/openlp_core_lib/test_htmlbuilder.py'
--- tests/functional/openlp_core_lib/test_htmlbuilder.py 2016-05-31 21:40:13 +0000
+++ tests/functional/openlp_core_lib/test_htmlbuilder.py 2016-06-09 02:57:58 +0000
@@ -14,177 +14,190 @@
14from tests.helpers.testmixin import TestMixin14from tests.helpers.testmixin import TestMixin
1515
16HTML = """16HTML = """
17<!DOCTYPE html>17 <!DOCTYPE html>
18<html>18 <html>
19<head>19 <head>
20<title>OpenLP Display</title>20 <title>OpenLP Display</title>
21<style>21 <style>
22*{22 *{
23 margin: 0;23 margin: 0;
24 padding: 0;24 padding: 0;
25 border: 0;25 border: 0;
26 overflow: hidden;26 overflow: hidden;
27 -webkit-user-select: none;27 -webkit-user-select: none;
28}28 }
29body {29 body {
30 ;30 ;
31}31 }
32.size {32 .size {
33 position: absolute;33 position: absolute;
34 left: 0px;34 left: 0px;
35 top: 0px;35 top: 0px;
36 width: 100%;36 width: 100%;
37 height: 100%;37 height: 100%;
38}38 }
39#black {39 #black {
40 z-index: 8;40 z-index: 8;
41 background-color: black;41 background-color: black;
42 display: none;42 display: none;
43}43 }
44#bgimage {44 #bgimage {
45 z-index: 1;45 z-index: 1;
46}46 }
47#image {47 #image {
48 z-index: 2;48 z-index: 2;
49}49 }
50plugin CSS50 plugin CSS
51#footer {51 #footer {
52 position: absolute;52 position: absolute;
53 z-index: 6;53 z-index: 6;
54 dummy: dummy;54 dummy: dummy;
55}55 }
56/* lyric css */56 /* lyric css */
5757 sup {
58sup {58 font-size: 0.6em;
59 font-size: 0.6em;59 vertical-align: top;
60 vertical-align: top;60 position: relative;
61 position: relative;61 top: -0.3em;
62 top: -0.3em;62 }
63}63 </style>
64</style>64 <script>
65<script>65 var timer = null;
66 var timer = null;66 var transition = false;
67 var transition = false;67 plugin JS
68 plugin JS68
6969 function show_image(src){
70 function show_image(src){70 var img = document.getElementById('image');
71 var img = document.getElementById('image');71 img.src = src;
72 img.src = src;72 if(src == '')
73 if(src == '')73 img.style.display = 'none';
74 img.style.display = 'none';74 else
75 else75 img.style.display = 'block';
76 img.style.display = 'block';76 }
77 }77
7878 function show_blank(state){
79 function show_blank(state){79 var black = 'none';
80 var black = 'none';80 var lyrics = '';
81 var lyrics = '';81 switch(state){
82 switch(state){82 case 'theme':
83 case 'theme':83 lyrics = 'hidden';
84 lyrics = 'hidden';84 break;
85 break;85 case 'black':
86 case 'black':86 black = 'block';
87 black = 'block';87 break;
88 break;88 case 'desktop':
89 case 'desktop':89 break;
90 break;90 }
91 }91 document.getElementById('black').style.display = black;
92 document.getElementById('black').style.display = black;92 document.getElementById('lyricsmain').style.visibility = lyrics;
93 document.getElementById('lyricsmain').style.visibility = lyrics;93 document.getElementById('image').style.visibility = lyrics;
94 document.getElementById('image').style.visibility = lyrics;94 document.getElementById('footer').style.visibility = lyrics;
95 document.getElementById('footer').style.visibility = lyrics;95 }
96 }96
9797 function show_footer(footertext){
98 function show_footer(footertext){98 document.getElementById('footer').innerHTML = footertext;
99 document.getElementById('footer').innerHTML = footertext;99 }
100 }100
101101 function show_text(new_text){
102 function show_text(new_text){102 var match = /-webkit-text-fill-color:[^;"]+/gi;
103 var match = /-webkit-text-fill-color:[^;"]+/gi;103 if(timer != null)
104 if(timer != null)104 clearTimeout(timer);
105 clearTimeout(timer);105 /*
106 /*106 QtWebkit bug with outlines and justify causing outline alignment
107 QtWebkit bug with outlines and justify causing outline alignment107 problems. (Bug 859950) Surround each word with a <span> to workaround,
108 problems. (Bug 859950) Surround each word with a <span> to workaround,108 but only in this scenario.
109 but only in this scenario.109 */
110 */110 var txt = document.getElementById('lyricsmain');
111 var txt = document.getElementById('lyricsmain');111 if(window.getComputedStyle(txt).textAlign == 'justify'){
112 if(window.getComputedStyle(txt).textAlign == 'justify'){112 if(window.getComputedStyle(txt).webkitTextStrokeWidth != '0px'){
113 if(window.getComputedStyle(txt).webkitTextStrokeWidth != '0px'){113 new_text = new_text.replace(/(\s|&nbsp;)+(?![^<]*>)/g,
114 new_text = new_text.replace(/(\s|&nbsp;)+(?![^<]*>)/g,114 function(match) {
115 function(match) {115 return '</span>' + match + '<span>';
116 return '</span>' + match + '<span>';116 });
117 });117 new_text = '<span>' + new_text + '</span>';
118 new_text = '<span>' + new_text + '</span>';118 }
119 }119 }
120 }120 text_fade('lyricsmain', new_text);
121 text_fade('lyricsmain', new_text);121 }
122 }122
123123 function text_fade(id, new_text){
124 function text_fade(id, new_text){124 /*
125 /*125 Show the text.
126 Show the text.126 */
127 */127 var text = document.getElementById(id);
128 var text = document.getElementById(id);128 if(text == null) return;
129 if(text == null) return;129 if(!transition){
130 if(!transition){130 text.innerHTML = new_text;
131 return;
132 }
133 // Fade text out. 0.1 to minimize the time "nothing" is shown on the screen.
134 text.style.opacity = '0.1';
135 // Fade new text in after the old text has finished fading out.
136 timer = window.setTimeout(function(){_show_text(text, new_text)}, 400);
137 }
138
139 function _show_text(text, new_text) {
140 /*
141 Helper function to show the new_text delayed.
142 */
131 text.innerHTML = new_text;143 text.innerHTML = new_text;
132 return;144 text.style.opacity = '1';
133 }145 // Wait until the text is completely visible. We want to save the timer id, to be able to call
134 // Fade text out. 0.1 to minimize the time "nothing" is shown on the screen.146 // clearTimeout(timer) when the text has changed before finishing fading.
135 text.style.opacity = '0.1';147 timer = window.setTimeout(function(){timer = null;}, 400);
136 // Fade new text in after the old text has finished fading out.148 }
137 timer = window.setTimeout(function(){_show_text(text, new_text)}, 400);149
138 }150 function show_text_completed(){
139151 return (timer == null);
140 function _show_text(text, new_text) {152 }
141 /*153 </script>
142 Helper function to show the new_text delayed.154 </head>
143 */155 <body>
144 text.innerHTML = new_text;156 <img id="bgimage" class="size" style="display:none;" />
145 text.style.opacity = '1';157 <img id="image" class="size" style="display:none;" />
146 // Wait until the text is completely visible. We want to save the timer id, to be able to call158 plugin HTML
147 // clearTimeout(timer) when the text has changed before finishing fading.159 <div class="lyricstable"><div id="lyricsmain" style="opacity:1" class="lyricscell lyricsmain"></div></div>
148 timer = window.setTimeout(function(){timer = null;}, 400);160 <div id="footer" class="footer"></div>
149 }161 <div id="black" class="size"></div>
150162 </body>
151 function show_text_completed(){163 </html>
152 return (timer == null);164 """
153 }
154</script>
155</head>
156<body>
157<img id="bgimage" class="size" style="display:none;" />
158<img id="image" class="size" style="display:none;" />
159plugin HTML
160<div class="lyricstable"><div id="lyricsmain" style="opacity:1" class="lyricscell lyricsmain"></div></div>
161<div id="footer" class="footer"></div>
162<div id="black" class="size"></div>
163</body>
164</html>
165"""
166BACKGROUND_CSS_RADIAL = 'background: -webkit-gradient(radial, 5 50%, 100, 5 50%, 5, from(#000000), to(#FFFFFF)) fixed'165BACKGROUND_CSS_RADIAL = 'background: -webkit-gradient(radial, 5 50%, 100, 5 50%, 5, from(#000000), to(#FFFFFF)) fixed'
167LYRICS_CSS = """166LYRICS_CSS = """
168.lyricstable {167 .lyricstable {
169 z-index: 5;168 z-index: 5;
170 position: absolute;169 position: absolute;
171 display: table;170 display: table;
172 left: 10px; top: 20px;171 left: 10px; top: 20px;
173}172 }
174.lyricscell {173 .lyricscell {
175 display: table-cell;174 display: table-cell;
175 word-wrap: break-word;
176 -webkit-transition: opacity 0.4s ease;
177 lyrics_format_css
178 }
179 .lyricsmain {
180 text-shadow: #000000 5px 5px;
181 }
182 """
183LYRICS_OUTLINE_CSS = ' -webkit-text-stroke: 0.125em #000000; -webkit-text-fill-color: #FFFFFF; '
184LYRICS_FORMAT_CSS = """
176 word-wrap: break-word;185 word-wrap: break-word;
177 -webkit-transition: opacity 0.4s ease;186 text-align: justify;
178 lyrics_format_css187 vertical-align: bottom;
179}188 font-family: Arial;
180.lyricsmain {189 font-size: 40pt;
181 text-shadow: #000000 5px 5px;190 color: #FFFFFF;
182}191 line-height: 108%;
183"""192 margin: 0;
184LYRICS_OUTLINE_CSS = ' -webkit-text-stroke: 0.125em #000000; -webkit-text-fill-color: #FFFFFF; '193 padding: 0;
185LYRICS_FORMAT_CSS = ' word-wrap: break-word; text-align: justify; vertical-align: bottom; ' + \194 padding-bottom: 0.5em;
186 'font-family: Arial; font-size: 40pt; color: #FFFFFF; line-height: 108%; margin: 0;padding: 0; ' + \195 padding-left: 2px;
187 'padding-bottom: 0.5em; padding-left: 2px; width: 1580px; height: 810px; font-style:italic; font-weight:bold; '196 width: 1580px;
197 height: 810px;
198 font-style: italic;
199 font-weight: bold;
200 """
188FOOTER_CSS_BASE = """201FOOTER_CSS_BASE = """
189 left: 10px;202 left: 10px;
190 bottom: 0px;203 bottom: 0px;