← Back to team overview

openlp-core team mailing list archive

[Merge] lp:~googol/openlp/render into lp:openlp

 

Andreas Preikschat has proposed merging lp:~googol/openlp/render into lp:openlp.

Requested reviews:
  OpenLP Core (openlp-core)

For more details, see:
https://code.launchpad.net/~googol/openlp/render/+merge/70526

Hello,

The renderer now uses JS to change the slide's text instead of loading the whole page again. (I changed this, because I hoped to improve performance, but the improvement is very small (maybe none at all), neglectable.) However, it still improves readability because you do not have to build up the html each time (self.page_shell + my_html + HTML_END).

Furthermore, I updated the docstrings.
-- 
https://code.launchpad.net/~googol/openlp/render/+merge/70526
Your team OpenLP Core is requested to review the proposed merge of lp:~googol/openlp/render into lp:openlp.
=== modified file 'openlp/core/lib/renderer.py'
--- openlp/core/lib/renderer.py	2011-07-30 07:19:16 +0000
+++ openlp/core/lib/renderer.py	2011-08-05 08:23:24 +0000
@@ -46,8 +46,6 @@
     'r{/pk}{o}e{/o}{pp}n{/pp} of the Lord\n'
 FOOTER = [u'Arky Arky (Unknown)', u'Public Domain', u'CCLI 123456']
 
-HTML_END = u'</div></body></html>'
-
 class Renderer(object):
     """
     Class to pull all Renderer interactions into one place. The plugins will
@@ -224,7 +222,7 @@
             line_end = u' '
         # Bibles
         if item.is_capable(ItemCapabilities.AllowsWordSplit):
-            pages = self._paginate_slide_words(text, line_end)
+            pages = self._paginate_slide_words(text.split(u'\n'), line_end)
         else:
             # Clean up line endings.
             lines = self._lines_split(text)
@@ -245,19 +243,17 @@
             new_pages.append(page)
         return new_pages
 
-    def _calculate_default(self, screen):
+    def _calculate_default(self, size):
         """
         Calculate the default dimentions of the screen.
 
-        ``screen``
-            The screen to calculate the default of.
+        ``size``
+            The screen's size to calculate the default of (``QtCore.QRect``).
         """
-        log.debug(u'_calculate default %s', screen)
-        self.width = screen.width()
-        self.height = screen.height()
+        self.width = size.width()
+        self.height = size.height()
         self.screen_ratio = float(self.height) / float(self.width)
-        log.debug(u'calculate default %d, %d, %f',
-            self.width, self.height, self.screen_ratio)
+        log.debug(u'_calculate default %s, %f' % (size, self.screen_ratio))
         # 90% is start of footer
         self.footer_start = int(self.height * 0.90)
 
@@ -310,17 +306,28 @@
         self.web.resize(self.page_width, self.page_height)
         self.web_frame = self.web.page().mainFrame()
         # Adjust width and height to account for shadow. outline done in css
-        self.page_shell = u'<!DOCTYPE html><html><head><style>' \
-            u'*{margin:0; padding:0; border:0;} '\
-            u'#main {position:absolute; top:0px; %s %s}</style></head><body>' \
-            u'<div id="main">' % \
+        html = u"""<!DOCTYPE html><html><head><script>
+            function show_text(newtext) {
+                var main = document.getElementById('main');
+                main.innerHTML = newtext;
+                // We need to be sure that the page is loaded, that is why we
+                // return the element's height (even though we do not use the
+                // returned value).
+                return main.offsetHeight;
+            }
+            </script><style>*{margin: 0; padding: 0; border: 0;}
+            #main {position: absolute; top: 0px; %s %s}</style></head><body>
+            <div id="main"></div></body></html>""" % \
             (build_lyrics_format_css(self.theme_data, self.page_width,
             self.page_height), build_lyrics_outline_css(self.theme_data))
+        self.web.setHtml(html)
 
     def _paginate_slide(self, lines, line_end):
         """
         Figure out how much text can appear on a slide, using the current
         theme settings.
+        **Note:** The smallest possible "unit" of text for a slide is one line.
+        If the line is too long it will be cut off when displayed.
 
         ``lines``
             The text to be fitted on the slide split into lines.
@@ -334,10 +341,8 @@
         previous_raw = u''
         separator = u'<br>'
         html_lines = map(expand_tags, lines)
-        html = self.page_shell + separator.join(html_lines) + HTML_END
-        self.web.setHtml(html)
         # Text too long so go to next page.
-        if self.web_frame.contentsSize().height() > self.page_height:
+        if self._text_fits_on_slide(separator.join(html_lines)):
             html_text, previous_raw = self._binary_chop(formatted,
                 previous_html, previous_raw, html_lines, lines, separator, u'')
         else:
@@ -347,48 +352,41 @@
         log.debug(u'_paginate_slide - End')
         return formatted
 
-    def _paginate_slide_words(self, text, line_end):
+    def _paginate_slide_words(self, lines, line_end):
         """
         Figure out how much text can appear on a slide, using the current
-        theme settings. This version is to handle text which needs to be split
-        into words to get it to fit.
+        theme settings.
+        **Note:** The smallest possible "unit" of text for a slide is one word.
+        If one line is too long it will be processed word by word. This is
+        sometimes need for **bible** verses.
 
-        ``text``
-            The words to be fitted on the slide split into lines.
+        ``lines``
+            The text to be fitted on the slide split into lines.
 
         ``line_end``
             The text added after each line. Either ``u' '`` or ``u'<br>``.
-            This is needed for bibles.
+            This is needed for **bibles**.
         """
         log.debug(u'_paginate_slide_words - Start')
         formatted = []
         previous_html = u''
         previous_raw = u''
-        lines = text.split(u'\n')
         for line in lines:
             line = line.strip()
             html_line = expand_tags(line)
-            html = self.page_shell + previous_html + html_line + HTML_END
-            self.web.setHtml(html)
             # Text too long so go to next page.
-            if self.web_frame.contentsSize().height() > self.page_height:
+            if self._text_fits_on_slide(previous_html + html_line):
                 # Check if there was a verse before the current one and append
                 # it, when it fits on the page.
                 if previous_html:
-                    html = self.page_shell + previous_html + HTML_END
-                    self.web.setHtml(html)
-                    if self.web_frame.contentsSize().height() <= \
-                        self.page_height:
+                    if not self._text_fits_on_slide(previous_html):
                         formatted.append(previous_raw)
                         previous_html = u''
                         previous_raw = u''
-                        html = self.page_shell + html_line + HTML_END
-                        self.web.setHtml(html)
                         # Now check if the current verse will fit, if it does
                         # not we have to start to process the verse word by
                         # word.
-                        if self.web_frame.contentsSize().height() <= \
-                            self.page_height:
+                        if not self._text_fits_on_slide(html_line):
                             previous_html = html_line + line_end
                             previous_raw = line + line_end
                             continue
@@ -445,10 +443,8 @@
         highest_index = len(html_list) - 1
         index = int(highest_index / 2)
         while True:
-            html = self.page_shell + previous_html + \
-                separator.join(html_list[:index + 1]).strip() + HTML_END
-            self.web.setHtml(html)
-            if self.web_frame.contentsSize().height() > self.page_height:
+            if self._text_fits_on_slide(
+                previous_html + separator.join(html_list[:index + 1]).strip()):
                 # We know that it does not fit, so change/calculate the
                 # new index and highest_index accordingly.
                 highest_index = index
@@ -470,10 +466,8 @@
             else:
                 continue
             # Check if the remaining elements fit on the slide.
-            html = self.page_shell + \
-                separator.join(html_list[index + 1:]).strip() + HTML_END
-            self.web.setHtml(html)
-            if self.web_frame.contentsSize().height() <= self.page_height:
+            if not self._text_fits_on_slide(
+                separator.join(html_list[index + 1:]).strip()):
                 previous_html = separator.join(
                     html_list[index + 1:]).strip() + line_end
                 previous_raw = separator.join(
@@ -489,6 +483,18 @@
                 index = int(highest_index / 2)
         return previous_html, previous_raw
 
+    def _text_fits_on_slide(self, text):
+        """
+        Checks if the given ``text`` fits on a slide. If it does ``True`` is
+        returned, otherwise ``False``.
+
+        ``text``
+            The text to check. It can contain HTML tags.
+        """
+        self.web_frame.evaluateJavaScript(u'show_text("%s")' %
+            text.replace(u'\\', u'\\\\').replace(u'\"', u'\\\"'))
+        return self.web_frame.contentsSize().height() > self.page_height
+
     def _words_split(self, line):
         """
         Split the slide up by word so can wrap better

=== modified file 'openlp/core/ui/maindisplay.py'
--- openlp/core/ui/maindisplay.py	2011-07-18 16:20:40 +0000
+++ openlp/core/ui/maindisplay.py	2011-08-05 08:23:24 +0000
@@ -188,7 +188,7 @@
         while not self.webLoaded:
             Receiver.send_message(u'openlp_process_events')
         self.setGeometry(self.screen[u'size'])
-        self.frame.evaluateJavaScript(u'show_text("%s")' % \
+        self.frame.evaluateJavaScript(u'show_text("%s")' %
             slide.replace(u'\\', u'\\\\').replace(u'\"', u'\\\"'))
         return self.preview()