diff --git a/openlp/core/lib/__init__.py b/openlp/core/lib/__init__.py index 89eeb6ad4..687c49094 100644 --- a/openlp/core/lib/__init__.py +++ b/openlp/core/lib/__init__.py @@ -289,6 +289,5 @@ from htmlbuilder import build_html, build_lyrics_format_css, \ from toolbar import OpenLPToolbar from dockwidget import OpenLPDockWidget from renderer import Renderer -from rendermanager import RenderManager from mediamanageritem import MediaManagerItem from openlp.core.utils.actions import ActionList diff --git a/openlp/core/lib/plugin.py b/openlp/core/lib/plugin.py index 08be86541..48a54f8ca 100644 --- a/openlp/core/lib/plugin.py +++ b/openlp/core/lib/plugin.py @@ -159,14 +159,14 @@ class Plugin(QtCore.QObject): self.status = PluginStatus.Inactive # Set up logging self.log = logging.getLogger(self.name) - self.previewController = plugin_helpers[u'preview'] - self.liveController = plugin_helpers[u'live'] - self.renderManager = plugin_helpers[u'render'] - self.serviceManager = plugin_helpers[u'service'] - self.settingsForm = plugin_helpers[u'settings form'] - self.mediadock = plugin_helpers[u'toolbox'] - self.pluginManager = plugin_helpers[u'pluginmanager'] - self.formparent = plugin_helpers[u'formparent'] + self.previewController = pluginHelpers[u'preview'] + self.liveController = pluginHelpers[u'live'] + self.renderer = pluginHelpers[u'renderer'] + self.serviceManager = pluginHelpers[u'service'] + self.settingsForm = pluginHelpers[u'settings form'] + self.mediadock = pluginHelpers[u'toolbox'] + self.pluginManager = pluginHelpers[u'pluginmanager'] + self.formparent = pluginHelpers[u'formparent'] QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'%s_add_service_item' % self.name), self.processAddServiceEvent) @@ -359,4 +359,4 @@ class Plugin(QtCore.QObject): use of the singular name of the plugin object so must only be called after this has been set. """ - self.textStrings[name] = {u'title': title, u'tooltip': tooltip} \ No newline at end of file + self.textStrings[name] = {u'title': title, u'tooltip': tooltip} diff --git a/openlp/core/lib/renderer.py b/openlp/core/lib/renderer.py index 0eeae6abd..ac8e26191 100644 --- a/openlp/core/lib/renderer.py +++ b/openlp/core/lib/renderer.py @@ -23,46 +23,261 @@ # 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 PyQt4 import QtCore, QtWebKit -from openlp.core.lib import expand_tags, build_lyrics_format_css, \ - build_lyrics_outline_css, Receiver +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 log = logging.getLogger(__name__) +VERSE = u'The Lord said to {r}Noah{/r}: \n' \ + 'There\'s gonna be a {su}floody{/su}, {sb}floody{/sb}\n' \ + 'The Lord said to {g}Noah{/g}:\n' \ + 'There\'s gonna be a {st}floody{/st}, {it}floody{/it}\n' \ + 'Get those children out of the muddy, muddy \n' \ + '{r}C{/r}{b}h{/b}{bl}i{/bl}{y}l{/y}{g}d{/g}{pk}' \ + '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'' + 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. + Class to pull all Renderer interactions into one place. The plugins will + call helper methods to do the rendering but this class will provide + display defense code. + + ``theme_manager`` + The ThemeManager instance, used to get the current theme details. + + ``screens`` + Contains information about the Screens. + + ``screen_number`` + Defaults to *0*. The index of the output/display screen. """ log.info(u'Renderer Loaded') - def __init__(self): + def __init__(self, theme_manager, screens): """ - Initialise the renderer. + Initialise the render manager. """ - self._rect = None - self.theme_name = None - self._theme = None + log.debug(u'Initilisation started') + self.screens = screens + self.image_manager = ImageManager() + self.display = MainDisplay(self, screens, False) + self.display.imageManager = self.image_manager + self.theme_manager = theme_manager + self.service_theme = u'' + self.theme_level = u'' + self.override_background = None + self.theme_data = None + self.force_page = False - def set_theme(self, theme): + def update_display(self): """ - Set the theme to be used. + Updates the render manager's information about the current screen. + """ + log.debug(u'Update Display') + 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.bg_frame = None + self.theme_data = None + self.image_manager.update_display(self.width, self.height) + + def set_global_theme(self, global_theme, theme_level=ThemeLevel.Global): + """ + Set the global-level theme and the theme level. + + ``global_theme`` + The global-level theme to be set. + + ``theme_level`` + Defaults to *``ThemeLevel.Global``*. The theme level, can be + ``ThemeLevel.Global``, ``ThemeLevel.Service`` or + ``ThemeLevel.Song``. + """ + self.global_theme = global_theme + self.theme_level = theme_level + self.global_theme_data = \ + self.theme_manager.getThemeData(self.global_theme) + self.theme_data = None + + def set_service_theme(self, service_theme): + """ + Set the service-level theme. + + ``service_theme`` + The service-level theme to be set. + """ + self.service_theme = service_theme + self.theme_data = None + + def set_override_theme(self, override_theme, override_levels=False): + """ + Set the appropriate theme depending on the theme level. + Called by the service item when building a display frame ``theme`` - The theme to be used. - """ - log.debug(u'set theme') - self._theme = theme - self.theme_name = theme.theme_name + The name of the song-level theme. None means the service + item wants to use the given value. - def set_text_rectangle(self, rect_main, rect_footer): + ``override_levels`` + Used to force the theme data passed in to be used. + + """ + log.debug(u'set override theme to %s', override_theme) + theme_level = self.theme_level + if override_levels: + theme_level = ThemeLevel.Song + if theme_level == ThemeLevel.Global: + theme = self.global_theme + elif theme_level == ThemeLevel.Service: + if self.service_theme == u'': + theme = self.global_theme + else: + theme = self.service_theme + else: + # Images have a theme of -1 + if override_theme and override_theme != -1: + theme = override_theme + elif theme_level == ThemeLevel.Song or \ + theme_level == ThemeLevel.Service: + if self.service_theme == u'': + theme = self.global_theme + else: + theme = self.service_theme + else: + theme = self.global_theme + log.debug(u'theme is now %s', theme) + # Force the theme to be the one passed in. + if override_levels: + self.theme_data = override_theme + else: + self.theme_data = self.theme_manager.getThemeData(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): + """ + Generate a preview of a theme. + + ``theme_data`` + The theme to generated a preview for. + + ``force_page`` + Flag to tell message lines per page need to be generated. + """ + log.debug(u'generate preview') + # save value for use in format_slide + self.force_page = force_page + # set the default image size for previews + self._calculate_default(self.screens.preview[u'size']) + # build a service item to generate preview + serviceItem = ServiceItem() + serviceItem.theme = theme_data + if self.force_page: + # make big page for theme edit dialog to get line count + serviceItem.add_from_text(u'', VERSE + VERSE + VERSE, FOOTER) + else: + self.image_manager.del_image(theme_data.theme_name) + serviceItem.add_from_text(u'', VERSE, FOOTER) + serviceItem.renderer = self + serviceItem.raw_footer = FOOTER + serviceItem.render(True) + if not self.force_page: + self.display.buildHtml(serviceItem) + 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']) + return preview + + def format_slide(self, text, line_break, item): + """ + Calculate how much text can fit on a slide. + + ``text`` + The words to go on the slides. + + ``line_break`` + Add line endings after each line of text used for bibles. + """ + print [text] + log.debug(u'format slide') + # clean up line endings + lines = self._lines_split(text) + pages = self._paginate_slide(lines, line_break, self.force_page) + if len(pages) > 1: + # Songs and Custom + if item.is_capable(ItemCapabilities.AllowsVirtualSplit): + # do not forget the line breaks ! + slides = text.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) +# # Bibles + elif item.is_capable(ItemCapabilities.AllowsWordSplit): + pages = self._paginate_slide_words(text, line_break) + return pages + + def _calculate_default(self, screen): + """ + Calculate the default dimentions of the screen. + + ``screen`` + The QSize of the screen. + """ + log.debug(u'calculate default %s', screen) + self.width = screen.width() + self.height = screen.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) + # 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. @@ -77,9 +292,9 @@ class Renderer(object): 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) + 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) @@ -89,16 +304,16 @@ class Renderer(object): u'*{margin: 0; padding: 0; border: 0;} '\ u'#main {position:absolute; top:0px; %s %s}' \ u'
' % \ - (build_lyrics_format_css(self._theme, self.page_width, - self.page_height), build_lyrics_outline_css(self._theme)) + (build_lyrics_format_css(self.theme_data, self.page_width, + self.page_height), build_lyrics_outline_css(self.theme_data)) - def format_slide(self, words, line_break, force_page=False): + 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. - ``words`` - The words to be fitted on the slide. + ``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. @@ -111,23 +326,16 @@ class Renderer(object): line_end = u'' if line_break: line_end = u'
' - 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: + 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'
' + html = self.page_shell + styled_text + HTML_END self.web.setHtml(html) # Text too long so go to next page if self.web_frame.contentsSize().height() > self.page_height: @@ -145,3 +353,125 @@ class Renderer(object): formatted.append(html_text) log.debug(u'format_slide - End') return formatted + + def _paginate_slide_words(self, text, line_break): + """ + 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. + + ``text`` + The words to be fitted on the slide split into lines. + + ``line_break`` + Add line endings after each line of text used for bibles. + + """ + print [text] + log.debug(u'format_slide - Start') + line_end = u'' + if line_break: + line_end = u'
' + formatted = [] + html_text = u'' + styled_text = u'' + line_count = 0 + force_current = False + lines = self._lines(text, u'[---]') + previous_line = u'' + # Loop through the lines + for line in lines: + line_count += 1 + styled_line = expand_tags(line) + styled_line = line_end + styled_line + previous_line = line + previous_styled = styled_line + styled_text += styled_line + html = self.page_shell + styled_text + HTML_END + self.web.setHtml(html) + # Text too long so go to next page + print self.web_frame.contentsSize().height() , self.page_height, [line] + if self.web_frame.contentsSize().height() > self.page_height: + # we have more than 1 verse on the slide + print "A", line_count + print "AA", [previous_line] + print "AAA", [styled_text] + if line_count > 1: + if html_text.endswith(u'
'): + html_text = html_text[:len(html_text)-4] + formatted.append(html_text + line_end) + line = previous_line + line_count = 1 + html_text = u'' + print "c", [html_text] + if line_count == 1: + line_count = 0 + words = self._words_split(line) + styled_text = u'' + styled_line = u'' + for word in words: + styled_word = expand_tags(word) + styled_text += styled_word + html = self.page_shell + styled_text + HTML_END + self.web.setHtml(html) + # Text too long so go to next page + print self.web_frame.contentsSize().height() , self.page_height, [line] + if self.web_frame.contentsSize().height() > self.page_height: + if html_text.endswith(u'
'): + html_text = html_text[:len(html_text)-4] + formatted.append(html_text + line_break) + html_text = u'' + styled_text = u'' + html_text += word + a=1 + else: + styled_text = styled_line + html_text += line + line_end + previous_line = line + if html_text.endswith(u'
'): + 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=u'n[---]n'): + """ + Split the slide up by physical line + """ + # this parse we do not want to use this so remove it + #words = words.replace(split, 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_split(self, words): + """ + Split the slide up by word so can wrap better + """ + # this parse we are to be 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 + + def _lines_split(self, text): + """ + Split the slide up by physical line + """ + # this parse we do not want to use this so remove it + lines = text.split(u'\n') + real_lines = [] + for line in lines: + line = line.replace(u' [---]', u'[---]') + sub_lines = line.split(u'\n') + for sub_line in sub_lines: + real_lines.append(sub_line) + return real_lines diff --git a/openlp/core/lib/rendermanager.py b/openlp/core/lib/rendermanager.py deleted file mode 100644 index 65f2b355c..000000000 --- a/openlp/core/lib/rendermanager.py +++ /dev/null @@ -1,261 +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 # -############################################################################### - -import logging - -from PyQt4 import QtCore - -from openlp.core.lib import Renderer, ServiceItem, ImageManager -from openlp.core.lib.theme import ThemeLevel -from openlp.core.ui import MainDisplay - -log = logging.getLogger(__name__) - -VERSE = u'The Lord said to {r}Noah{/r}: \n' \ - 'There\'s gonna be a {su}floody{/su}, {sb}floody{/sb}\n' \ - 'The Lord said to {g}Noah{/g}:\n' \ - 'There\'s gonna be a {st}floody{/st}, {it}floody{/it}\n' \ - 'Get those children out of the muddy, muddy \n' \ - '{r}C{/r}{b}h{/b}{bl}i{/bl}{y}l{/y}{g}d{/g}{pk}' \ - '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 to pull all Renderer interactions into one place. The plugins will - call helper methods to do the rendering but this class will provide - display defense code. - - ``theme_manager`` - The ThemeManager instance, used to get the current theme details. - - ``screens`` - Contains information about the Screens. - - ``screen_number`` - Defaults to *0*. The index of the output/display screen. - """ - log.info(u'RenderManager Loaded') - - def __init__(self, theme_manager, screens): - """ - Initialise the render manager. - """ - log.debug(u'Initilisation started') - self.screens = screens - self.image_manager = ImageManager() - 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'' - self.override_background = None - self.theme_data = None - self.force_page = False - - def update_display(self): - """ - Updates the render manager's information about the current screen. - """ - log.debug(u'Update Display') - 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.theme_data = None - self.image_manager.update_display(self.width, self.height) - - def set_global_theme(self, global_theme, theme_level=ThemeLevel.Global): - """ - Set the global-level theme and the theme level. - - ``global_theme`` - The global-level theme to be set. - - ``theme_level`` - Defaults to *``ThemeLevel.Global``*. The theme level, can be - ``ThemeLevel.Global``, ``ThemeLevel.Service`` or - ``ThemeLevel.Song``. - """ - self.global_theme = global_theme - self.theme_level = theme_level - self.global_theme_data = \ - self.theme_manager.getThemeData(self.global_theme) - self.theme_data = None - - def set_service_theme(self, service_theme): - """ - Set the service-level theme. - - ``service_theme`` - The service-level theme to be set. - """ - self.service_theme = service_theme - self.theme_data = None - - def set_override_theme(self, theme, overrideLevels=False): - """ - Set the appropriate theme depending on the theme level. - Called by the service item when building a display frame - - ``theme`` - The name of the song-level theme. None means the service - item wants to use the given value. - - ``overrideLevels`` - Used to force the theme data passed in to be used. - - """ - log.debug(u'set override theme to %s', theme) - theme_level = self.theme_level - if overrideLevels: - theme_level = ThemeLevel.Song - if theme_level == ThemeLevel.Global: - self.theme = self.global_theme - elif theme_level == ThemeLevel.Service: - if self.service_theme == u'': - self.theme = self.global_theme - else: - self.theme = self.service_theme - else: - # Images have a theme of -1 - if theme and theme != -1: - self.theme = theme - elif theme_level == ThemeLevel.Song or \ - theme_level == ThemeLevel.Service: - if self.service_theme == u'': - self.theme = self.global_theme - else: - 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) - - def generate_preview(self, theme_data, force_page=False): - """ - Generate a preview of a theme. - - ``theme_data`` - The theme to generated a preview for. - - ``force_page`` - Flag to tell message lines per page need to be generated. - """ - log.debug(u'generate preview') - # save value for use in format_slide - self.force_page = force_page - # set the default image size for previews - self.calculate_default(self.screens.preview[u'size']) - # build a service item to generate preview - serviceItem = ServiceItem() - serviceItem.theme = theme_data - if self.force_page: - # make big page for theme edit dialog to get line count - serviceItem.add_from_text(u'', VERSE + VERSE + VERSE, FOOTER) - else: - self.image_manager.del_image(theme_data.theme_name) - serviceItem.add_from_text(u'', VERSE, FOOTER) - serviceItem.render_manager = self - serviceItem.raw_footer = FOOTER - serviceItem.render(True) - if not self.force_page: - self.display.buildHtml(serviceItem) - 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']) - return preview - - def format_slide(self, words, line_break): - """ - Calculate how much text can fit on a slide. - - ``words`` - 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) - - def calculate_default(self, screen): - """ - Calculate the default dimentions of the screen. - - ``screen`` - The QSize of the screen. - """ - log.debug(u'calculate default %s', screen) - self.width = screen.width() - self.height = screen.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) - # 90% is start of footer - self.footer_start = int(self.height * 0.90) diff --git a/openlp/core/lib/serviceitem.py b/openlp/core/lib/serviceitem.py index 5de25f6aa..3810a7bb2 100644 --- a/openlp/core/lib/serviceitem.py +++ b/openlp/core/lib/serviceitem.py @@ -63,6 +63,8 @@ class ItemCapabilities(object): ProvidesOwnDisplay = 10 AllowsDetailedTitleDisplay = 11 AllowsVariableStartTime = 12 + AllowsVirtualSplit = 13 + AllowsWordSplit = 14 class ServiceItem(object): @@ -81,7 +83,7 @@ class ServiceItem(object): 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'' @@ -151,7 +153,7 @@ class ServiceItem(object): self.icon = icon self.iconic_representation = build_icon(icon) - def render(self, useOverride=False): + def render(self, use_override=False): """ The render method is what generates the frames for the screen and obtains the display information from the renderemanager. @@ -166,13 +168,13 @@ class ServiceItem(object): 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, use_override) + 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 @@ class ServiceItem(object): """ 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): diff --git a/openlp/core/ui/mainwindow.py b/openlp/core/ui/mainwindow.py index cb01e37a1..0cb22880a 100644 --- a/openlp/core/ui/mainwindow.py +++ b/openlp/core/ui/mainwindow.py @@ -30,7 +30,7 @@ from tempfile import gettempdir 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, shortcut_action @@ -545,9 +545,9 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): 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) @@ -555,7 +555,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): # 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 @@ -781,7 +781,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): their locations """ log.debug(u'screenChanged') - self.renderManager.update_display() + self.renderer.update_display() self.setFocus() self.activateWindow() diff --git a/openlp/core/ui/servicemanager.py b/openlp/core/ui/servicemanager.py index a2260cce9..58b10a381 100644 --- a/openlp/core/ui/servicemanager.py +++ b/openlp/core/ui/servicemanager.py @@ -579,7 +579,7 @@ class ServiceManager(QtGui.QWidget): 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) @@ -989,7 +989,7 @@ class ServiceManager(QtGui.QWidget): """ 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)) @@ -1001,7 +1001,7 @@ class ServiceManager(QtGui.QWidget): 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: @@ -1016,7 +1016,7 @@ class ServiceManager(QtGui.QWidget): 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() @@ -1278,7 +1278,7 @@ class ServiceManager(QtGui.QWidget): self.onThemeChangeAction, context=QtCore.Qt.WidgetShortcut) self.themeMenu.addAction(action) find_and_set_in_combo_box(self.themeComboBox, self.service_theme) - self.mainwindow.renderManager.set_service_theme(self.service_theme) + self.mainwindow.renderer.set_service_theme(self.service_theme) self.regenerateServiceItems() def onThemeChangeAction(self): diff --git a/openlp/core/ui/slidecontroller.py b/openlp/core/ui/slidecontroller.py index 5f2c63c23..2556cb004 100644 --- a/openlp/core/ui/slidecontroller.py +++ b/openlp/core/ui/slidecontroller.py @@ -412,7 +412,7 @@ class SlideController(QtGui.QWidget): """ # 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: @@ -614,19 +614,19 @@ class SlideController(QtGui.QWidget): 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) @@ -1150,4 +1150,4 @@ class SlideController(QtGui.QWidget): elif self.desktopScreen.isChecked(): return HideMode.Screen else: - return None \ No newline at end of file + return None diff --git a/openlp/core/ui/thememanager.py b/openlp/core/ui/thememanager.py index 335b9b174..741576938 100644 --- a/openlp/core/ui/thememanager.py +++ b/openlp/core/ui/thememanager.py @@ -660,7 +660,7 @@ class ThemeManager(QtGui.QWidget): 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. @@ -669,7 +669,7 @@ class ThemeManager(QtGui.QWidget): 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): diff --git a/openlp/core/ui/themestab.py b/openlp/core/ui/themestab.py index fccef1244..20f24d9fe 100644 --- a/openlp/core/ui/themestab.py +++ b/openlp/core/ui/themestab.py @@ -149,7 +149,7 @@ class ThemesTab(SettingsTab): settings.setValue(u'global theme', QtCore.QVariant(self.global_theme)) settings.endGroup() - self.mainwindow.renderManager.set_global_theme( + self.mainwindow.renderer.set_global_theme( self.global_theme, self.theme_level) Receiver.send_message(u'theme_update_global', self.global_theme) @@ -167,7 +167,7 @@ class ThemesTab(SettingsTab): def onDefaultComboBoxChanged(self, value): self.global_theme = unicode(self.DefaultComboBox.currentText()) - self.mainwindow.renderManager.set_global_theme( + self.mainwindow.renderer.set_global_theme( self.global_theme, self.theme_level) self.__previewGlobalTheme() @@ -188,7 +188,7 @@ class ThemesTab(SettingsTab): for theme in theme_list: self.DefaultComboBox.addItem(theme) find_and_set_in_combo_box(self.DefaultComboBox, self.global_theme) - self.mainwindow.renderManager.set_global_theme( + self.mainwindow.renderer.set_global_theme( self.global_theme, self.theme_level) if self.global_theme is not u'': self.__previewGlobalTheme() @@ -203,4 +203,4 @@ class ThemesTab(SettingsTab): if not preview.isNull(): preview = preview.scaled(300, 255, QtCore.Qt.KeepAspectRatio, QtCore.Qt.SmoothTransformation) - self.DefaultListView.setPixmap(preview) \ No newline at end of file + self.DefaultListView.setPixmap(preview) diff --git a/openlp/plugins/bibles/lib/mediaitem.py b/openlp/plugins/bibles/lib/mediaitem.py index e0e06b02f..b9a0833f1 100644 --- a/openlp/plugins/bibles/lib/mediaitem.py +++ b/openlp/plugins/bibles/lib/mediaitem.py @@ -723,6 +723,7 @@ class BibleMediaItem(MediaManagerItem): 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 diff --git a/openlp/plugins/custom/forms/editcustomform.py b/openlp/plugins/custom/forms/editcustomform.py index 9312b5ddd..7b8a15c21 100644 --- a/openlp/plugins/custom/forms/editcustomform.py +++ b/openlp/plugins/custom/forms/editcustomform.py @@ -169,7 +169,7 @@ class EditCustomForm(QtGui.QDialog, Ui_CustomEditDialog): item = self.slideListView.item(row) slide_list += item.text() if row != self.slideListView.count() - 1: - slide_list += u'\n[---]\n' + slide_list += u'\n[===]\n' self.editSlideForm.setText(slide_list) if self.editSlideForm.exec_(): self.updateSlideList(self.editSlideForm.getText(), True) diff --git a/openlp/plugins/custom/forms/editcustomslideform.py b/openlp/plugins/custom/forms/editcustomslideform.py index 7d4e32968..bf775a1f2 100644 --- a/openlp/plugins/custom/forms/editcustomslideform.py +++ b/openlp/plugins/custom/forms/editcustomslideform.py @@ -63,7 +63,7 @@ class EditCustomSlideForm(QtGui.QDialog, Ui_CustomSlideEditDialog): """ Returns a list with all slides. """ - return self.slideTextEdit.toPlainText().split(u'\n[---]\n') + return self.slideTextEdit.toPlainText().split(u'\n[===]\n') def onSplitButtonPressed(self): """ @@ -71,5 +71,5 @@ class EditCustomSlideForm(QtGui.QDialog, Ui_CustomSlideEditDialog): """ if self.slideTextEdit.textCursor().columnNumber() != 0: self.slideTextEdit.insertPlainText(u'\n') - self.slideTextEdit.insertPlainText(u'[---]\n') + self.slideTextEdit.insertPlainText(u'[===]\n') self.slideTextEdit.setFocus() diff --git a/openlp/plugins/custom/lib/mediaitem.py b/openlp/plugins/custom/lib/mediaitem.py index b508104c4..4bd3a8d4b 100644 --- a/openlp/plugins/custom/lib/mediaitem.py +++ b/openlp/plugins/custom/lib/mediaitem.py @@ -140,6 +140,7 @@ class CustomMediaItem(MediaManagerItem): 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 diff --git a/openlp/plugins/presentations/lib/impresscontroller.py b/openlp/plugins/presentations/lib/impresscontroller.py index 8166a2258..c84f0ff1e 100644 --- a/openlp/plugins/presentations/lib/impresscontroller.py +++ b/openlp/plugins/presentations/lib/impresscontroller.py @@ -244,7 +244,7 @@ class ImpressDocument(PresentationDocument): 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 @@ class ImpressDocument(PresentationDocument): 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 diff --git a/openlp/plugins/presentations/lib/powerpointcontroller.py b/openlp/plugins/presentations/lib/powerpointcontroller.py index a02bc841a..12e0d2746 100644 --- a/openlp/plugins/presentations/lib/powerpointcontroller.py +++ b/openlp/plugins/presentations/lib/powerpointcontroller.py @@ -251,14 +251,15 @@ class PowerpointDocument(PresentationDocument): win32ui.GetForegroundWindow().GetDC().GetDeviceCaps(88) except win32ui.error: dpi = 96 - rendermanager = self.controller.plugin.renderManager - rect = rendermanager.screens.current[u'size'] + renderer = self.controller.plugin.renderer + rect = renderer.screens.current[u'size'] ppt_window = self.presentation.SlideShowSettings.Run() ppt_window.Top = rect.y() * 72 / dpi ppt_window.Height = rect.height() * 72 / dpi ppt_window.Left = rect.x() * 72 / dpi ppt_window.Width = rect.width() * 72 / dpi + def get_slide_number(self): """ Returns the current slide number. diff --git a/openlp/plugins/presentations/lib/pptviewcontroller.py b/openlp/plugins/presentations/lib/pptviewcontroller.py index 94fd05f31..354c33361 100644 --- a/openlp/plugins/presentations/lib/pptviewcontroller.py +++ b/openlp/plugins/presentations/lib/pptviewcontroller.py @@ -121,8 +121,8 @@ class PptviewDocument(PresentationDocument): 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 @@ class PptviewDocument(PresentationDocument): """ 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 diff --git a/openlp/plugins/songs/forms/editsongform.py b/openlp/plugins/songs/forms/editsongform.py index 0b9c9316f..f6b8d96ab 100644 --- a/openlp/plugins/songs/forms/editsongform.py +++ b/openlp/plugins/songs/forms/editsongform.py @@ -89,7 +89,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): 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(), diff --git a/openlp/plugins/songs/lib/mediaitem.py b/openlp/plugins/songs/lib/mediaitem.py index 8245adfbc..d731d8ef8 100644 --- a/openlp/plugins/songs/lib/mediaitem.py +++ b/openlp/plugins/songs/lib/mediaitem.py @@ -347,6 +347,7 @@ class SongMediaItem(MediaManagerItem): 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