openlp/openlp/core/lib/rendermanager.py

263 lines
10 KiB
Python
Raw Normal View History

# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
2009-12-31 12:52:01 +00:00
# Copyright (c) 2008-2010 Raoul Snyman #
# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael #
2010-07-24 22:10:47 +00:00
# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian #
# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, #
# Carsten Tinggaard, 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
2010-01-24 23:16:15 +00:00
from PyQt4 import QtCore
from openlp.core.lib import Renderer, ThemeLevel, ServiceItem, ImageManager
2010-07-23 05:05:34 +00:00
from openlp.core.ui import MainDisplay
2010-04-03 07:10:31 +00:00
2010-02-27 15:31:23 +00:00
log = logging.getLogger(__name__)
2009-07-10 13:16:15 +00:00
class RenderManager(object):
"""
2009-07-10 13:16:15 +00:00
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.
2009-09-04 22:50:19 +00:00
``theme_manager``
The ThemeManager instance, used to get the current theme details.
``screens``
Contains information about the Screens.
2009-09-04 22:50:19 +00:00
``screen_number``
Defaults to *0*. The index of the output/display screen.
"""
log.info(u'RenderManager Loaded')
2010-04-02 18:12:54 +00:00
def __init__(self, theme_manager, screens):
2009-07-10 13:16:15 +00:00
"""
Initialise the render manager.
"""
log.debug(u'Initilisation started')
self.screens = screens
self.image_manager = ImageManager()
2010-07-26 15:51:18 +00:00
self.display = MainDisplay(self, screens, False)
2010-10-23 17:37:10 +00:00
self.display.imageManager = self.image_manager
2010-07-23 05:05:34 +00:00
self.display.setup()
self.theme_manager = theme_manager
self.renderer = Renderer()
self.calculate_default(self.screens.current[u'size'])
self.theme = u''
2009-05-20 20:17:20 +00:00
self.service_theme = u''
self.theme_level = u''
self.override_background = None
self.theme_data = None
2010-08-05 19:01:24 +00:00
self.alertTab = None
2010-11-23 20:48:55 +00:00
self.force_page = False
2010-04-02 18:12:54 +00:00
def update_display(self):
"""
Updates the render manager's information about the current screen.
"""
2009-06-10 15:54:46 +00:00
log.debug(u'Update Display')
self.calculate_default(self.screens.current[u'size'])
2010-08-05 20:26:39 +00:00
self.display = MainDisplay(self, self.screens, False)
2010-10-23 17:37:10 +00:00
self.display.imageManager = self.image_manager
2010-08-05 20:26:39 +00:00
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):
2009-07-10 13:16:15 +00:00
"""
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``.
2009-07-10 13:16:15 +00:00
"""
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):
2009-07-10 13:16:15 +00:00
"""
Set the service-level theme.
``service_theme``
The service-level theme to be set.
"""
self.service_theme = service_theme
self.theme_data = None
2010-08-07 08:50:58 +00:00
def set_override_theme(self, theme, overrideLevels=False):
2009-07-10 13:16:15 +00:00
"""
Set the appropriate theme depending on the theme level.
2010-07-12 16:49:38 +00:00
Called by the service item when building a display frame
2009-07-10 13:16:15 +00:00
``theme``
2010-07-12 16:49:38 +00:00
The name of the song-level theme. None means the service
item wants to use the given value.
2010-08-31 17:51:48 +00:00
``overrideLevels``
Used to force the theme data passed in to be used.
2009-07-10 13:16:15 +00:00
"""
log.debug(u'set override theme to %s', theme)
2010-08-07 08:50:58 +00:00
theme_level = self.theme_level
if overrideLevels:
theme_level = ThemeLevel.Song
if theme_level == ThemeLevel.Global:
self.theme = self.global_theme
2010-08-07 08:50:58 +00:00
elif theme_level == ThemeLevel.Service:
if self.service_theme == u'':
self.theme = self.global_theme
else:
self.theme = self.service_theme
else:
2009-11-03 18:14:25 +00:00
if theme:
self.theme = theme
2010-08-07 08:50:58 +00:00
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 \
2010-08-07 08:50:58 +00:00
or overrideLevels:
2009-09-21 17:56:36 +00:00
log.debug(u'theme is now %s', self.theme)
2010-08-31 17:51:48 +00:00
# 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)
2010-07-17 08:59:15 +00:00
return self.renderer._rect, self.renderer._rect_footer
def build_text_rectangle(self, theme):
2009-07-10 13:16:15 +00:00
"""
Builds a text block using the settings in ``theme``
and the size of the display screen.height.
2009-07-10 13:16:15 +00:00
``theme``
The theme to build a text block for.
"""
log.debug(u'build_text_rectangle')
main_rect = None
footer_rect = None
2009-11-03 15:13:52 +00:00
if not theme.font_main_override:
main_rect = QtCore.QRect(10, 0,
2010-03-13 20:50:52 +00:00
self.width - 20, self.footer_start)
else:
2009-11-04 01:16:15 +00:00
main_rect = QtCore.QRect(theme.font_main_x, theme.font_main_y,
theme.font_main_width - 1, theme.font_main_height - 1)
2009-11-03 15:13:52 +00:00
if not theme.font_footer_override:
footer_rect = QtCore.QRect(10, self.footer_start,
2010-03-13 20:50:52 +00:00
self.width - 20, self.height - self.footer_start)
else:
2009-11-04 01:16:15 +00:00
footer_rect = QtCore.QRect(theme.font_footer_x,
theme.font_footer_y, theme.font_footer_width - 1,
theme.font_footer_height - 1)
2009-08-31 06:53:55 +00:00
self.renderer.set_text_rectangle(main_rect, footer_rect)
def generate_preview(self, theme_data, force_page=False):
2009-07-10 13:16:15 +00:00
"""
Generate a preview of a theme.
``theme_data``
2009-07-10 13:16:15 +00:00
The theme to generated a preview for.
``force_page``
Flag to tell message lines per page need to be generated.
2009-07-10 13:16:15 +00:00
"""
log.debug(u'generate preview')
# save value for use in format_slide
self.force_page = force_page
2010-08-05 19:01:24 +00:00
# set the default image size for previews
self.calculate_default(self.screens.preview[u'size'])
2010-09-25 16:14:14 +00:00
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' \
2010-09-25 16:16:36 +00:00
'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}' \
2010-09-25 16:14:14 +00:00
'r{/pk}{o}e{/o}{pp}n{/pp} of the Lord\n'
2010-11-23 20:48:55 +00:00
# make big page for theme edit dialog to get line count
if self.force_page:
verse = verse + verse + verse
2009-07-10 13:16:15 +00:00
footer = []
2010-09-25 16:14:14 +00:00
footer.append(u'Arky Arky (Unknown)' )
2009-07-10 13:16:15 +00:00
footer.append(u'Public Domain')
footer.append(u'CCLI 123456')
2010-07-25 08:58:08 +00:00
# build a service item to generate preview
2010-07-23 05:05:34 +00:00
serviceItem = ServiceItem()
serviceItem.theme = theme_data
2010-07-26 16:42:19 +00:00
serviceItem.add_from_text(u'', verse, footer)
2010-07-23 05:05:34 +00:00
serviceItem.render_manager = self
serviceItem.raw_footer = footer
2010-08-21 10:07:59 +00:00
serviceItem.render(True)
2010-11-24 19:41:14 +00:00
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
2010-08-03 19:23:05 +00:00
def format_slide(self, words, line_break):
2009-07-10 13:16:15 +00:00
"""
2009-08-31 06:53:55 +00:00
Calculate how much text can fit on a slide.
2009-07-10 13:16:15 +00:00
``words``
The words to go on the slides.
2010-11-23 20:48:55 +00:00
``line_break``
Add line endings after each line of text used for bibles.
2009-07-10 13:16:15 +00:00
"""
log.debug(u'format slide')
2010-11-23 20:48:55 +00:00
return self.renderer.format_slide(words, line_break, self.force_page)
def calculate_default(self, screen):
2009-07-10 13:16:15 +00:00
"""
Calculate the default dimentions of the screen.
``screen``
The QSize of the screen.
2009-07-10 13:16:15 +00:00
"""
log.debug(u'calculate default %s', screen)
self.width = screen.width()
self.height = screen.height()
2009-09-20 07:12:47 +00:00
self.screen_ratio = float(self.height) / float(self.width)
2009-09-21 17:56:36 +00:00
log.debug(u'calculate default %d, %d, %f',
self.width, self.height, self.screen_ratio )
# 90% is start of footer
2010-07-26 15:51:18 +00:00
self.footer_start = int(self.height * 0.90)