← Back to team overview

openlp-core team mailing list archive

[Merge] lp:~trb143/openlp/beta1 into lp:openlp

 

Tim Bentley has proposed merging lp:~trb143/openlp/beta1 into lp:openlp.

Requested reviews:
  OpenLP Core (openlp-core)

For more details, see:
https://code.launchpad.net/~trb143/openlp/beta1/+merge/55369

Refactored RenderManager and Renderer into one class and cleaned up the tree.

Added a 2nd pass for Songs and Custom if one screen does not fit and split at [###.
Added a 2nd pass for bibles which splits by words.  Tested on Esther 8:7-10 at 46 and 83pt.

UI changes to come.
-- 
https://code.launchpad.net/~trb143/openlp/beta1/+merge/55369
Your team OpenLP Core is requested to review the proposed merge of lp:~trb143/openlp/beta1 into lp:openlp.
=== modified file 'openlp/core/lib/__init__.py'
--- openlp/core/lib/__init__.py	2011-03-28 20:18:55 +0000
+++ openlp/core/lib/__init__.py	2011-03-29 16:08:36 +0000
@@ -339,5 +339,4 @@
 from toolbar import OpenLPToolbar
 from dockwidget import OpenLPDockWidget
 from renderer import Renderer
-from rendermanager import RenderManager
 from mediamanageritem import MediaManagerItem

=== modified file 'openlp/core/lib/plugin.py'
--- openlp/core/lib/plugin.py	2011-03-24 21:19:17 +0000
+++ openlp/core/lib/plugin.py	2011-03-29 16:08:36 +0000
@@ -160,7 +160,7 @@
         self.log = logging.getLogger(self.name)
         self.previewController = pluginHelpers[u'preview']
         self.liveController = pluginHelpers[u'live']
-        self.renderManager = pluginHelpers[u'render']
+        self.renderer = pluginHelpers[u'renderer']
         self.serviceManager = pluginHelpers[u'service']
         self.settingsForm = pluginHelpers[u'settings form']
         self.mediadock = pluginHelpers[u'toolbox']

=== removed file 'openlp/core/lib/renderer.py'
--- openlp/core/lib/renderer.py	2011-03-24 19:04:02 +0000
+++ openlp/core/lib/renderer.py	1970-01-01 00:00:00 +0000
@@ -1,147 +0,0 @@
-# -*- coding: utf-8 -*-
-# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
-
-###############################################################################
-# OpenLP - Open Source Lyrics Projection                                      #
-# --------------------------------------------------------------------------- #
-# Copyright (c) 2008-2011 Raoul Snyman                                        #
-# Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael      #
-# Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, Armin Köhler,        #
-# Andreas Preikschat, Mattias Põldaru, Christian Richter, Philip Ridout,      #
-# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Frode Woldsund             #
-# --------------------------------------------------------------------------- #
-# This program is free software; you can redistribute it and/or modify it     #
-# under the terms of the GNU General Public License as published by the Free  #
-# Software Foundation; version 2 of the License.                              #
-#                                                                             #
-# This program is distributed in the hope that it will be useful, but WITHOUT #
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       #
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for    #
-# more details.                                                               #
-#                                                                             #
-# You should have received a copy of the GNU General Public License along     #
-# with this program; if not, write to the Free Software Foundation, Inc., 59  #
-# Temple Place, Suite 330, Boston, MA 02111-1307 USA                          #
-###############################################################################
-"""
-The :mod:`renderer` module enables OpenLP to take the input from plugins and
-format it for the output display.
-"""
-import logging
-
-from PyQt4 import QtWebKit
-
-from openlp.core.lib import expand_tags, build_lyrics_format_css, \
-    build_lyrics_outline_css, Receiver
-
-log = logging.getLogger(__name__)
-
-class Renderer(object):
-    """
-    Genarates a pixmap image of a array of text. The Text is formatted to
-    make sure it fits on the screen and if not extra frames are generated.
-    """
-    log.info(u'Renderer Loaded')
-
-    def __init__(self):
-        """
-        Initialise the renderer.
-        """
-        self._rect = None
-        self.theme_name = None
-        self._theme = None
-
-    def set_theme(self, theme):
-        """
-        Set the theme to be used.
-
-        ``theme``
-            The theme to be used.
-        """
-        log.debug(u'set theme')
-        self._theme = theme
-        self.theme_name = theme.theme_name
-
-    def set_text_rectangle(self, rect_main, rect_footer):
-        """
-        Sets the rectangle within which text should be rendered.
-
-        ``rect_main``
-            The main text block.
-
-        ``rect_footer``
-            The footer text block.
-        """
-        log.debug(u'set_text_rectangle %s , %s' % (rect_main, rect_footer))
-        self._rect = rect_main
-        self._rect_footer = rect_footer
-        self.page_width = self._rect.width()
-        self.page_height = self._rect.height()
-        if self._theme.font_main_shadow:
-            self.page_width -= int(self._theme.font_main_shadow_size)
-            self.page_height -= int(self._theme.font_main_shadow_size)
-        self.web = QtWebKit.QWebView()
-        self.web.setVisible(False)
-        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'<html><head><style>' \
-            u'*{margin: 0; padding: 0; border: 0;} '\
-            u'#main {position:absolute; top:0px; %s %s}</style><body>' \
-            u'<div id="main">' % \
-            (build_lyrics_format_css(self._theme, self.page_width,
-            self.page_height), build_lyrics_outline_css(self._theme))
-
-    def format_slide(self, words, line_break, force_page=False):
-        """
-        Figure out how much text can appear on a slide, using the current
-        theme settings.
-
-        ``words``
-            The words to be fitted on the slide.
-
-        ``line_break``
-            Add line endings after each line of text used for bibles.
-
-        ``force_page``
-            Flag to tell message lines in page.
-
-        """
-        log.debug(u'format_slide - Start')
-        line_end = u''
-        if line_break:
-            line_end = u'<br>'
-        words = words.replace(u'\r\n', u'\n')
-        verses_text = words.split(u'\n')
-        text = []
-        for verse in verses_text:
-            lines = verse.split(u'\n')
-            for line in lines:
-                text.append(line)
-        formatted = []
-        html_text = u''
-        styled_text = u''
-        line_count = 0
-        for line in text:
-            if line_count != -1:
-                line_count += 1
-            styled_line = expand_tags(line) + line_end
-            styled_text += styled_line
-            html = self.page_shell + styled_text + u'</div></body></html>'
-            self.web.setHtml(html)
-            # Text too long so go to next page
-            if self.web_frame.contentsSize().height() > self.page_height:
-                if force_page and line_count > 0:
-                    Receiver.send_message(u'theme_line_count', line_count)
-                line_count = -1
-                if html_text.endswith(u'<br>'):
-                    html_text = html_text[:len(html_text)-4]
-                formatted.append(html_text)
-                html_text = u''
-                styled_text = styled_line
-            html_text += line + line_end
-        if html_text.endswith(u'<br>'):
-            html_text = html_text[:len(html_text)-4]
-        formatted.append(html_text)
-        log.debug(u'format_slide - End')
-        return formatted

=== renamed file 'openlp/core/lib/rendermanager.py' => 'openlp/core/lib/renderer.py'
--- openlp/core/lib/rendermanager.py	2011-03-27 16:39:04 +0000
+++ openlp/core/lib/renderer.py	2011-03-29 16:08:36 +0000
@@ -26,9 +26,11 @@
 
 import logging
 
-from PyQt4 import QtCore
+from PyQt4 import QtCore, QtWebKit
 
-from openlp.core.lib import Renderer, ServiceItem, ImageManager
+from openlp.core.lib import ServiceItem, ImageManager, expand_tags, \
+    build_lyrics_format_css, build_lyrics_outline_css, Receiver, \
+    ItemCapabilities
 from openlp.core.lib.theme import ThemeLevel
 from openlp.core.ui import MainDisplay
 
@@ -43,7 +45,7 @@
     'r{/pk}{o}e{/o}{pp}n{/pp} of the Lord\n'
 FOOTER = [u'Arky Arky (Unknown)', u'Public Domain', u'CCLI 123456']
 
-class RenderManager(object):
+class Renderer(object):
     """
     Class to pull all Renderer interactions into one place. The plugins will
     call helper methods to do the rendering but this class will provide
@@ -58,7 +60,7 @@
     ``screen_number``
         Defaults to *0*. The index of the output/display screen.
     """
-    log.info(u'RenderManager Loaded')
+    log.info(u'Renderer Loaded')
 
     def __init__(self, theme_manager, screens):
         """
@@ -70,8 +72,6 @@
         self.display = MainDisplay(self, screens, False)
         self.display.imageManager = self.image_manager
         self.theme_manager = theme_manager
-        self.renderer = Renderer()
-        self.calculate_default(self.screens.current[u'size'])
         self.theme = u''
         self.service_theme = u''
         self.theme_level = u''
@@ -84,11 +84,11 @@
         Updates the render manager's information about the current screen.
         """
         log.debug(u'Update Display')
-        self.calculate_default(self.screens.current[u'size'])
+        self._calculate_default(self.screens.current[u'size'])
         self.display = MainDisplay(self, self.screens, False)
         self.display.imageManager = self.image_manager
         self.display.setup()
-        self.renderer.bg_frame = None
+        self.bg_frame = None
         self.theme_data = None
         self.image_manager.update_display(self.width, self.height)
 
@@ -156,45 +156,17 @@
                     self.theme = self.service_theme
             else:
                 self.theme = self.global_theme
-        if self.theme != self.renderer.theme_name or self.theme_data is None \
-            or overrideLevels:
-            log.debug(u'theme is now %s', self.theme)
-            # Force the theme to be the one passed in.
-            if overrideLevels:
-                self.theme_data = theme
-            else:
-                self.theme_data = self.theme_manager.getThemeData(self.theme)
-            self.calculate_default(self.screens.current[u'size'])
-            self.renderer.set_theme(self.theme_data)
-            self.build_text_rectangle(self.theme_data)
-            self.image_manager.add_image(self.theme_data.theme_name,
-                self.theme_data.background_filename)
-        return self.renderer._rect, self.renderer._rect_footer
-
-    def build_text_rectangle(self, theme):
-        """
-        Builds a text block using the settings in ``theme``
-        and the size of the display screen.height.
-
-        ``theme``
-            The theme to build a text block for.
-        """
-        log.debug(u'build_text_rectangle')
-        main_rect = None
-        footer_rect = None
-        if not theme.font_main_override:
-            main_rect = QtCore.QRect(10, 0, self.width - 20, self.footer_start)
-        else:
-            main_rect = QtCore.QRect(theme.font_main_x, theme.font_main_y,
-                theme.font_main_width - 1, theme.font_main_height - 1)
-        if not theme.font_footer_override:
-            footer_rect = QtCore.QRect(10, self.footer_start, self.width - 20,
-                self.height - self.footer_start)
-        else:
-            footer_rect = QtCore.QRect(theme.font_footer_x,
-                theme.font_footer_y, theme.font_footer_width - 1,
-                theme.font_footer_height - 1)
-        self.renderer.set_text_rectangle(main_rect, footer_rect)
+        log.debug(u'theme is now %s', self.theme)
+        # Force the theme to be the one passed in.
+        if overrideLevels:
+            self.theme_data = theme
+        else:
+            self.theme_data = self.theme_manager.getThemeData(self.theme)
+        self._calculate_default(self.screens.current[u'size'])
+        self._build_text_rectangle(self.theme_data)
+        self.image_manager.add_image(self.theme_data.theme_name,
+            self.theme_data.background_filename)
+        return self._rect, self._rect_footer
 
     def generate_preview(self, theme_data, force_page=False):
         """
@@ -228,23 +200,41 @@
             raw_html = serviceItem.get_rendered_frame(0)
             preview = self.display.text(raw_html)
             # Reset the real screen size for subsequent render requests
-            self.calculate_default(self.screens.current[u'size'])
+            self._calculate_default(self.screens.current[u'size'])
             return preview
 
-    def format_slide(self, words, line_break):
+    def format_slide(self, slide, line_break, item):
         """
         Calculate how much text can fit on a slide.
 
-        ``words``
+        ``slide``
             The words to go on the slides.
 
         ``line_break``
             Add line endings after each line of text used for bibles.
         """
         log.debug(u'format slide')
-        return self.renderer.format_slide(words, line_break, self.force_page)
+        # clean up line endings
+        slide = slide.replace(u'\r\n', u'\n')
+        lines = self._lines(slide)
+        pages = self._paginate_slide(lines, line_break, self.force_page)
+        if len(pages) > 1:
+            if item.is_capable(ItemCapabilities.AllowsVirtualSplit):
+                # do not forget the line breaks !
+                slides = slide.split(u'\n[###]\n')
+                pages = []
+                for slide in slides:
+                    lines = self._lines(slide)
+                    new_pages = self._paginate_slide(lines, line_break,
+                        self.force_page)
+                    for page in new_pages:
+                        pages.append(page)
+            elif item.is_capable(ItemCapabilities.AllowsWordSplit):
+                lines = self._words(slide)
+                pages = self._paginate_slide(lines, False, self.force_page)
+        return pages
 
-    def calculate_default(self, screen):
+    def _calculate_default(self, screen):
         """
         Calculate the default dimentions of the screen.
 
@@ -259,3 +249,134 @@
             self.width, self.height, self.screen_ratio)
         # 90% is start of footer
         self.footer_start = int(self.height * 0.90)
+
+    def _build_text_rectangle(self, theme):
+        """
+        Builds a text block using the settings in ``theme``
+        and the size of the display screen.height.
+
+        ``theme``
+            The theme to build a text block for.
+        """
+        log.debug(u'_build_text_rectangle')
+        main_rect = None
+        footer_rect = None
+        if not theme.font_main_override:
+            main_rect = QtCore.QRect(10, 0, self.width - 20, self.footer_start)
+        else:
+            main_rect = QtCore.QRect(theme.font_main_x, theme.font_main_y,
+                theme.font_main_width - 1, theme.font_main_height - 1)
+        if not theme.font_footer_override:
+            footer_rect = QtCore.QRect(10, self.footer_start, self.width - 20,
+                self.height - self.footer_start)
+        else:
+            footer_rect = QtCore.QRect(theme.font_footer_x,
+                theme.font_footer_y, theme.font_footer_width - 1,
+                theme.font_footer_height - 1)
+        self._set_text_rectangle(main_rect, footer_rect)
+
+    def _set_text_rectangle(self, rect_main, rect_footer):
+        """
+        Sets the rectangle within which text should be rendered.
+
+        ``rect_main``
+            The main text block.
+
+        ``rect_footer``
+            The footer text block.
+        """
+        log.debug(u'set_text_rectangle %s , %s' % (rect_main, rect_footer))
+        self._rect = rect_main
+        self._rect_footer = rect_footer
+        self.page_width = self._rect.width()
+        self.page_height = self._rect.height()
+        if self.theme_data.font_main_shadow:
+            self.page_width -= int(self.theme_data.font_main_shadow_size)
+            self.page_height -= int(self.theme_data.font_main_shadow_size)
+        self.web = QtWebKit.QWebView()
+        self.web.setVisible(False)
+        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'<html><head><style>' \
+            u'*{margin: 0; padding: 0; border: 0;} '\
+            u'#main {position:absolute; top:0px; %s %s}</style><body>' \
+            u'<div id="main">' % \
+            (build_lyrics_format_css(self.theme_data, self.page_width,
+            self.page_height), build_lyrics_outline_css(self.theme_data))
+
+    def _paginate_slide(self, lines, line_break, force_page=False):
+        """
+        Figure out how much text can appear on a slide, using the current
+        theme settings.
+
+        ``lines``
+            The words to be fitted on the slide split into lines.
+
+        ``line_break``
+            Add line endings after each line of text used for bibles.
+
+        ``force_page``
+            Flag to tell message lines in page.
+
+        """
+        log.debug(u'format_slide - Start')
+        line_end = u''
+        if line_break:
+            line_end = u'<br>'
+        formatted = []
+        html_text = u''
+        styled_text = u''
+        line_count = 0
+        for line in lines:
+            if line_count != -1:
+                line_count += 1
+            styled_line = expand_tags(line) + line_end
+            styled_text += styled_line
+            html = self.page_shell + styled_text + u'</div></body></html>'
+            self.web.setHtml(html)
+            # Text too long so go to next page
+            if self.web_frame.contentsSize().height() > self.page_height:
+                if force_page and line_count > 0:
+                    Receiver.send_message(u'theme_line_count', line_count)
+                line_count = -1
+                if html_text.endswith(u'<br>'):
+                    html_text = html_text[:len(html_text)-4]
+                formatted.append(html_text)
+                html_text = u''
+                styled_text = styled_line
+            html_text += line + line_end
+        if html_text.endswith(u'<br>'):
+            html_text = html_text[:len(html_text)-4]
+        formatted.append(html_text)
+        log.debug(u'format_slide - End')
+        return formatted
+
+    def _lines(self, words):
+        """
+        Split the slide up by physical line
+        """
+        # this parse we do not want to use this so remove it
+        words = words.replace(u'[---]', u'')
+        verses_text = words.split(u'\n')
+        text = []
+        for verse in verses_text:
+            lines = verse.split(u'\n')
+            for line in lines:
+                text.append(line)
+        return text
+
+    def _words(self, words):
+        """
+        Split the slide up by word so can wrap better
+        """
+        # this parse we are wordy
+        words = words.replace(u'\n', u' ')
+        verses_text = words.split(u' ')
+        text = []
+        for verse in verses_text:
+            lines = verse.split(u' ')
+            for line in lines:
+                text.append(line + u' ')
+        return text
+

=== modified file 'openlp/core/lib/serviceitem.py'
--- openlp/core/lib/serviceitem.py	2011-03-25 17:49:53 +0000
+++ openlp/core/lib/serviceitem.py	2011-03-29 16:08:36 +0000
@@ -63,6 +63,8 @@
     ProvidesOwnDisplay = 10
     AllowsDetailedTitleDisplay = 11
     AllowsVariableStartTime = 12
+    AllowsVirtualSplit = 13
+    AllowsWordSplit = 14
 
 
 class ServiceItem(object):
@@ -81,7 +83,7 @@
             The plugin that this service item belongs to.
         """
         if plugin:
-            self.render_manager = plugin.renderManager
+            self.renderer = plugin.renderer
             self.name = plugin.name
         self.title = u''
         self.shortname = u''
@@ -166,13 +168,13 @@
             line_break = False
         theme = self.theme if self.theme else None
         self.main, self.footer = \
-            self.render_manager.set_override_theme(theme, useOverride)
-        self.themedata = self.render_manager.renderer._theme
+            self.renderer.set_override_theme(theme, useOverride)
+        self.themedata = self.renderer.theme_data
         if self.service_item_type == ServiceItemType.Text:
             log.debug(u'Formatting slides')
             for slide in self._raw_frames:
-                formatted = self.render_manager \
-                    .format_slide(slide[u'raw_slide'], line_break)
+                formatted = self.renderer \
+                    .format_slide(slide[u'raw_slide'], line_break, self)
                 for page in formatted:
                     self._display_frames.append(
                         {u'title': clean_tags(page),
@@ -205,7 +207,7 @@
         """
         self.service_item_type = ServiceItemType.Image
         self._raw_frames.append({u'title': title, u'path': path})
-        self.render_manager.image_manager.add_image(title, path)
+        self.renderer.image_manager.add_image(title, path)
         self._new_item()
 
     def add_from_text(self, title, raw_slide, verse_tag=None):
@@ -453,4 +455,4 @@
         elif not start and end:
             return end
         else:
-            return u'%s : %s' % (start, end)
+            return u'%s : %s' % (start, end)
\ No newline at end of file

=== modified file 'openlp/core/ui/mainwindow.py'
--- openlp/core/ui/mainwindow.py	2011-03-28 20:53:26 +0000
+++ openlp/core/ui/mainwindow.py	2011-03-29 16:08:36 +0000
@@ -30,7 +30,7 @@
 
 from PyQt4 import QtCore, QtGui
 
-from openlp.core.lib import RenderManager, build_icon, OpenLPDockWidget, \
+from openlp.core.lib import Renderer, build_icon, OpenLPDockWidget, \
     SettingsManager, PluginManager, Receiver, translate
 from openlp.core.lib.ui import UiStrings, base_action, checkable_action, \
     icon_action
@@ -587,9 +587,9 @@
             QtCore.SIGNAL(u'openlp_information_message'),
             self.onInformationMessage)
         # warning cyclic dependency
-        # RenderManager needs to call ThemeManager and
-        # ThemeManager needs to call RenderManager
-        self.renderManager = RenderManager(
+        # renderer needs to call ThemeManager and
+        # ThemeManager needs to call Renderer
+        self.renderer = Renderer(
             self.themeManagerContents, self.screens)
         # Define the media Dock Manager
         self.mediaDockManager = MediaDockManager(self.MediaToolBox)
@@ -597,7 +597,7 @@
         # make the controllers available to the plugins
         self.pluginHelpers[u'preview'] = self.previewController
         self.pluginHelpers[u'live'] = self.liveController
-        self.pluginHelpers[u'render'] = self.renderManager
+        self.pluginHelpers[u'renderer'] = self.renderer
         self.pluginHelpers[u'service'] = self.ServiceManagerContents
         self.pluginHelpers[u'settings form'] = self.settingsForm
         self.pluginHelpers[u'toolbox'] = self.mediaDockManager
@@ -822,7 +822,7 @@
         their locations
         """
         log.debug(u'screenChanged')
-        self.renderManager.update_display()
+        self.renderer.update_display()
         self.setFocus()
         self.activateWindow()
 

=== modified file 'openlp/core/ui/servicemanager.py'
--- openlp/core/ui/servicemanager.py	2011-03-26 19:00:47 +0000
+++ openlp/core/ui/servicemanager.py	2011-03-29 16:08:36 +0000
@@ -564,7 +564,7 @@
                 for item in items:
                     serviceItem = ServiceItem()
                     serviceItem.from_service = True
-                    serviceItem.render_manager = self.mainwindow.renderManager
+                    serviceItem.renderer = self.mainwindow.renderer
                     serviceItem.set_from_service(item, self.servicePath)
                     self.validateItem(serviceItem)
                     self.addServiceItem(serviceItem)
@@ -958,7 +958,7 @@
         """
         log.debug(u'onThemeComboBoxSelected')
         self.service_theme = unicode(self.themeComboBox.currentText())
-        self.mainwindow.renderManager.set_service_theme(self.service_theme)
+        self.mainwindow.renderer.set_service_theme(self.service_theme)
         QtCore.QSettings().setValue(
             self.mainwindow.serviceSettingsSection + u'/service theme',
             QtCore.QVariant(self.service_theme))
@@ -970,7 +970,7 @@
         sure the theme combo box is in the correct state.
         """
         log.debug(u'themeChange')
-        if self.mainwindow.renderManager.theme_level == ThemeLevel.Global:
+        if self.mainwindow.renderer.theme_level == ThemeLevel.Global:
             self.toolbar.actions[u'ThemeLabel'].setVisible(False)
             self.toolbar.actions[u'ThemeWidget'].setVisible(False)
         else:
@@ -985,7 +985,7 @@
         Receiver.send_message(u'cursor_busy')
         log.debug(u'regenerateServiceItems')
         # force reset of renderer as theme data has changed
-        self.mainwindow.renderManager.themedata = None
+        self.mainwindow.renderer.themedata = None
         if self.serviceItems:
             tempServiceItems = self.serviceItems
             self.serviceManagerList.clear()
@@ -1250,7 +1250,7 @@
             index = 0
             self.service_theme = u''
         self.themeComboBox.setCurrentIndex(index)
-        self.mainwindow.renderManager.set_service_theme(self.service_theme)
+        self.mainwindow.renderer.set_service_theme(self.service_theme)
         self.regenerateServiceItems()
 
     def onThemeChangeAction(self):

=== modified file 'openlp/core/ui/slidecontroller.py'
--- openlp/core/ui/slidecontroller.py	2011-03-26 19:50:15 +0000
+++ openlp/core/ui/slidecontroller.py	2011-03-29 16:08:36 +0000
@@ -407,7 +407,7 @@
         """
         # rebuild display as screen size changed
         self.display = MainDisplay(self, self.screens, self.isLive)
-        self.display.imageManager = self.parent.renderManager.image_manager
+        self.display.imageManager = self.parent.renderer.image_manager
         self.display.alertTab = self.alertTab
         self.display.setup()
         if self.isLive:
@@ -618,19 +618,19 @@
                 label.setScaledContents(True)
                 if self.serviceItem.is_command():
                     image = resize_image(frame[u'image'],
-                        self.parent.renderManager.width,
-                        self.parent.renderManager.height)
+                        self.parent.renderer.width,
+                        self.parent.renderer.height)
                 else:
                     # If current slide set background to image
                     if framenumber == slideno:
                         self.serviceItem.bg_image_bytes = \
-                            self.parent.renderManager.image_manager. \
+                            self.parent.renderer.image_manager. \
                             get_image_bytes(frame[u'title'])
-                    image = self.parent.renderManager.image_manager. \
+                    image = self.parent.renderer.image_manager. \
                         get_image(frame[u'title'])
                 label.setPixmap(QtGui.QPixmap.fromImage(image))
                 self.previewListWidget.setCellWidget(framenumber, 0, label)
-                slideHeight = width * self.parent.renderManager.screen_ratio
+                slideHeight = width * self.parent.renderer.screen_ratio
                 row += 1
             text.append(unicode(row))
             self.previewListWidget.setItem(framenumber, 0, item)
@@ -1111,4 +1111,4 @@
             blank.setChecked(False)
             self.hideMenu.setDefaultAction(blank)
             QtCore.QSettings().remove(
-                self.parent.generalSettingsSection + u'/screen blank')
+                self.parent.generalSettingsSection + u'/screen blank')
\ No newline at end of file

=== modified file 'openlp/core/ui/thememanager.py'
--- openlp/core/ui/thememanager.py	2011-03-25 17:49:26 +0000
+++ openlp/core/ui/thememanager.py	2011-03-29 16:08:36 +0000
@@ -656,7 +656,7 @@
 
     def generateImage(self, themeData, forcePage=False):
         """
-        Call the RenderManager to build a Sample Image
+        Call the renderer to build a Sample Image
 
         ``themeData``
             The theme to generated a preview for.
@@ -665,7 +665,7 @@
             Flag to tell message lines per page need to be generated.
         """
         log.debug(u'generateImage \n%s ', themeData)
-        return self.mainwindow.renderManager.generate_preview(
+        return self.mainwindow.renderer.generate_preview(
             themeData, forcePage)
 
     def getPreviewImage(self, theme):
@@ -802,4 +802,4 @@
             vAlignCorrection = VerticalType.Bottom
         newtheme.display_horizontal_align = theme.HorizontalAlign
         newtheme.display_vertical_align = vAlignCorrection
-        return newtheme.extract_xml()
+        return newtheme.extract_xml()
\ No newline at end of file

=== modified file 'openlp/core/ui/themestab.py'
--- openlp/core/ui/themestab.py	2011-03-24 19:04:02 +0000
+++ openlp/core/ui/themestab.py	2011-03-29 16:08:36 +0000
@@ -147,7 +147,7 @@
         settings.setValue(u'global theme',
             QtCore.QVariant(self.global_theme))
         settings.endGroup()
-        self.parent.renderManager.set_global_theme(
+        self.parent.renderer.set_global_theme(
             self.global_theme, self.theme_level)
         Receiver.send_message(u'theme_update_global', self.global_theme)
 
@@ -165,7 +165,7 @@
 
     def onDefaultComboBoxChanged(self, value):
         self.global_theme = unicode(self.DefaultComboBox.currentText())
-        self.parent.renderManager.set_global_theme(
+        self.parent.renderer.set_global_theme(
             self.global_theme, self.theme_level)
         self.__previewGlobalTheme()
 
@@ -191,7 +191,7 @@
             id = 0 # Not Found
             self.global_theme = u''
         self.DefaultComboBox.setCurrentIndex(id)
-        self.parent.renderManager.set_global_theme(
+        self.parent.renderer.set_global_theme(
             self.global_theme, self.theme_level)
         if self.global_theme is not u'':
             self.__previewGlobalTheme()
@@ -206,4 +206,4 @@
         if not preview.isNull():
             preview = preview.scaled(300, 255, QtCore.Qt.KeepAspectRatio,
                 QtCore.Qt.SmoothTransformation)
-        self.DefaultListView.setPixmap(preview)
+        self.DefaultListView.setPixmap(preview)
\ No newline at end of file

=== modified file 'openlp/plugins/bibles/lib/mediaitem.py'
--- openlp/plugins/bibles/lib/mediaitem.py	2011-03-26 16:29:21 +0000
+++ openlp/plugins/bibles/lib/mediaitem.py	2011-03-29 16:08:36 +0000
@@ -685,6 +685,7 @@
             service_item.add_capability(ItemCapabilities.NoLineBreaks)
         service_item.add_capability(ItemCapabilities.AllowsPreview)
         service_item.add_capability(ItemCapabilities.AllowsLoop)
+        service_item.add_capability(ItemCapabilities.AllowsWordSplit)
         # Service Item: Title
         service_item.title = u', '.join(raw_title)
         # Service Item: Theme

=== modified file 'openlp/plugins/custom/lib/mediaitem.py'
--- openlp/plugins/custom/lib/mediaitem.py	2011-03-24 19:04:02 +0000
+++ openlp/plugins/custom/lib/mediaitem.py	2011-03-29 16:08:36 +0000
@@ -139,6 +139,7 @@
         service_item.add_capability(ItemCapabilities.AllowsEdit)
         service_item.add_capability(ItemCapabilities.AllowsPreview)
         service_item.add_capability(ItemCapabilities.AllowsLoop)
+        service_item.add_capability(ItemCapabilities.AllowsVirtualSplit)
         customSlide = self.parent.manager.get_object(CustomSlide, item_id)
         title = customSlide.title
         credit = customSlide.credits

=== modified file 'openlp/plugins/presentations/lib/impresscontroller.py'
--- openlp/plugins/presentations/lib/impresscontroller.py	2011-03-24 19:04:02 +0000
+++ openlp/plugins/presentations/lib/impresscontroller.py	2011-03-29 16:08:36 +0000
@@ -244,7 +244,7 @@
             return False
         self.presentation = self.document.getPresentation()
         self.presentation.Display = \
-            self.controller.plugin.renderManager.screens.current_display + 1
+            self.controller.plugin.renderer.screens.current_display + 1
         self.control = None
         self.create_thumbnails()
         return True
@@ -463,4 +463,4 @@
             shape = page.getByIndex(idx)
             if shape.supportsService("com.sun.star.drawing.Text"):
                 text += shape.getString() + '\n'
-        return text
+        return text
\ No newline at end of file

=== modified file 'openlp/plugins/presentations/lib/powerpointcontroller.py'
--- openlp/plugins/presentations/lib/powerpointcontroller.py	2011-03-24 19:04:02 +0000
+++ openlp/plugins/presentations/lib/powerpointcontroller.py	2011-03-29 16:08:36 +0000
@@ -253,8 +253,8 @@
                     dpi = 96
             self.presentation.SlideShowSettings.Run()
             self.presentation.SlideShowWindow.View.GotoSlide(1)
-            rendermanager = self.controller.plugin.renderManager
-            rect = rendermanager.screens.current[u'size']
+            renderer = self.controller.plugin.renderer
+            rect = renderer.screens.current[u'size']
             self.presentation.SlideShowWindow.Top = rect.y() * 72 / dpi
             self.presentation.SlideShowWindow.Height = rect.height() * 72 / dpi
             self.presentation.SlideShowWindow.Left = rect.x() * 72 / dpi
@@ -326,4 +326,4 @@
         shape = shapes(idx + 1)
         if shape.HasTextFrame:
             text += shape.TextFrame.TextRange.Text + '\n'
-    return text
+    return text
\ No newline at end of file

=== modified file 'openlp/plugins/presentations/lib/pptviewcontroller.py'
--- openlp/plugins/presentations/lib/pptviewcontroller.py	2011-03-24 19:04:02 +0000
+++ openlp/plugins/presentations/lib/pptviewcontroller.py	2011-03-29 16:08:36 +0000
@@ -121,8 +121,8 @@
         The file name of the presentations to run.
         """
         log.debug(u'LoadPresentation')
-        rendermanager = self.controller.plugin.renderManager
-        rect = rendermanager.screens.current[u'size']
+        renderer = self.controller.plugin.renderer
+        rect = renderer.screens.current[u'size']
         rect = RECT(rect.x(), rect.y(), rect.right(), rect.bottom())
         filepath = str(self.filepath.replace(u'/', u'\\'))
         if not os.path.isdir(self.get_temp_folder()):
@@ -244,4 +244,4 @@
         """
         Triggers the previous slide on the running presentation
         """
-        self.controller.process.PrevStep(self.pptid)
+        self.controller.process.PrevStep(self.pptid)
\ No newline at end of file

=== modified file 'openlp/plugins/songs/forms/editsongform.py'
--- openlp/plugins/songs/forms/editsongform.py	2011-03-24 19:04:02 +0000
+++ openlp/plugins/songs/forms/editsongform.py	2011-03-29 16:08:36 +0000
@@ -89,7 +89,7 @@
             self.onVerseListViewPressed)
         QtCore.QObject.connect(self.themeAddButton,
             QtCore.SIGNAL(u'clicked()'),
-            self.parent.parent.renderManager.theme_manager.onAddTheme)
+            self.parent.parent.renderer.theme_manager.onAddTheme)
         QtCore.QObject.connect(self.maintenanceButton,
             QtCore.SIGNAL(u'clicked()'), self.onMaintenanceButtonClicked)
         QtCore.QObject.connect(Receiver.get_receiver(),
@@ -788,4 +788,4 @@
                     self.song.verse_order)
         except:
             log.exception(u'Problem processing song Lyrics \n%s',
-                sxml.dump_xml())
+                sxml.dump_xml())
\ No newline at end of file

=== modified file 'openlp/plugins/songs/lib/mediaitem.py'
--- openlp/plugins/songs/lib/mediaitem.py	2011-03-24 19:04:02 +0000
+++ openlp/plugins/songs/lib/mediaitem.py	2011-03-29 16:08:36 +0000
@@ -337,6 +337,7 @@
         service_item.add_capability(ItemCapabilities.AllowsLoop)
         service_item.add_capability(ItemCapabilities.OnLoadUpdate)
         service_item.add_capability(ItemCapabilities.AddIfNewItem)
+        service_item.add_capability(ItemCapabilities.AllowsVirtualSplit)
         song = self.parent.manager.get_object(Song, item_id)
         service_item.theme = song.theme_name
         service_item.edit_id = item_id