forked from openlp/openlp
Changes to Image processing to improve performance.
Moved image storage for Themes and Image plugins to central cache. Moved conversion to byte array on to a thread Built basic thread locking management to cover adding and processing at same time Presentations and Videos work how that always did. Cleaned up lots of image size and type conversions. bzr-revno: 1100 Fixes: https://launchpad.net/bugs/657712
This commit is contained in:
commit
98a5300068
@ -314,6 +314,7 @@ def expand_tags(text):
|
|||||||
|
|
||||||
from spelltextedit import SpellTextEdit
|
from spelltextedit import SpellTextEdit
|
||||||
from eventreceiver import Receiver
|
from eventreceiver import Receiver
|
||||||
|
from imagemanager import ImageManager
|
||||||
from settingsmanager import SettingsManager
|
from settingsmanager import SettingsManager
|
||||||
from plugin import PluginStatus, StringContent, Plugin
|
from plugin import PluginStatus, StringContent, Plugin
|
||||||
from pluginmanager import PluginManager
|
from pluginmanager import PluginManager
|
||||||
|
@ -328,6 +328,7 @@ def build_html(item, screen, alert, islive):
|
|||||||
height = screen[u'size'].height()
|
height = screen[u'size'].height()
|
||||||
theme = item.themedata
|
theme = item.themedata
|
||||||
webkitvers = webkit_version()
|
webkitvers = webkit_version()
|
||||||
|
# Image generated and poked in
|
||||||
if item.bg_image_bytes:
|
if item.bg_image_bytes:
|
||||||
image = u'src="data:image/png;base64,%s"' % item.bg_image_bytes
|
image = u'src="data:image/png;base64,%s"' % item.bg_image_bytes
|
||||||
else:
|
else:
|
||||||
|
158
openlp/core/lib/imagemanager.py
Normal file
158
openlp/core/lib/imagemanager.py
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# OpenLP - Open Source Lyrics Projection #
|
||||||
|
# --------------------------------------------------------------------------- #
|
||||||
|
# Copyright (c) 2008-2010 Raoul Snyman #
|
||||||
|
# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael #
|
||||||
|
# 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 #
|
||||||
|
###############################################################################
|
||||||
|
"""
|
||||||
|
Provides the store and management for Images automatically caching them and
|
||||||
|
resizing them when needed. Only one copy of each image is needed in the system.
|
||||||
|
A Thread is used to convert the image to a byte array so the user does not need
|
||||||
|
to wait for the conversion to happen.
|
||||||
|
"""
|
||||||
|
import logging
|
||||||
|
import os
|
||||||
|
import time
|
||||||
|
|
||||||
|
from PyQt4 import QtCore
|
||||||
|
|
||||||
|
from openlp.core.lib import resize_image, image_to_byte
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
class ImageThread(QtCore.QThread):
|
||||||
|
"""
|
||||||
|
A special Qt thread class to speed up the display of text based frames.
|
||||||
|
This is threaded so it loads the frames in background
|
||||||
|
"""
|
||||||
|
def __init__(self, manager):
|
||||||
|
QtCore.QThread.__init__(self, None)
|
||||||
|
self.image_mamager = manager
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
"""
|
||||||
|
Run the thread.
|
||||||
|
"""
|
||||||
|
self.image_mamager.process()
|
||||||
|
|
||||||
|
|
||||||
|
class Image(object):
|
||||||
|
name = ''
|
||||||
|
path = ''
|
||||||
|
dirty = True
|
||||||
|
image = None
|
||||||
|
image_bytes = None
|
||||||
|
|
||||||
|
class ImageManager(QtCore.QObject):
|
||||||
|
"""
|
||||||
|
Image Manager handles the conversion and sizing of images.
|
||||||
|
|
||||||
|
"""
|
||||||
|
log.info(u'Image Manager loaded')
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self._cache = {}
|
||||||
|
self._thread_running = False
|
||||||
|
self._cache_dirty = False
|
||||||
|
self.image_thread = ImageThread(self)
|
||||||
|
|
||||||
|
def update_display(self, width, height):
|
||||||
|
"""
|
||||||
|
Screen has changed size so rebuild the cache to new size
|
||||||
|
"""
|
||||||
|
log.debug(u'update_display')
|
||||||
|
self.width = width
|
||||||
|
self.height = height
|
||||||
|
# mark the images as dirty for a rebuild
|
||||||
|
for key in self._cache.keys():
|
||||||
|
image = self._cache[key]
|
||||||
|
image.dirty = True
|
||||||
|
fullpath = os.path.join(image.path, image.name)
|
||||||
|
image.image = resize_image(fullpath,
|
||||||
|
self.width, self.height)
|
||||||
|
self._cache_dirty = True
|
||||||
|
# only one thread please
|
||||||
|
if not self._thread_running:
|
||||||
|
self.image_thread.start()
|
||||||
|
|
||||||
|
def get_image(self, name):
|
||||||
|
"""
|
||||||
|
Return the Qimage from the cache
|
||||||
|
"""
|
||||||
|
log.debug(u'get_image %s' % name)
|
||||||
|
return self._cache[name].image
|
||||||
|
|
||||||
|
def get_image_bytes(self, name):
|
||||||
|
"""
|
||||||
|
Returns the byte string for an image
|
||||||
|
If not present wait for the background thread to process it.
|
||||||
|
"""
|
||||||
|
log.debug(u'get_image_bytes %s' % name)
|
||||||
|
if not self._cache[name].image_bytes:
|
||||||
|
while self._cache[name].dirty:
|
||||||
|
log.debug(u'get_image_bytes - waiting')
|
||||||
|
time.sleep(0.1)
|
||||||
|
return self._cache[name].image_bytes
|
||||||
|
|
||||||
|
def add_image(self, name, path):
|
||||||
|
"""
|
||||||
|
Add image to cache if it is not already there
|
||||||
|
"""
|
||||||
|
log.debug(u'add_image %s:%s' % (name, path))
|
||||||
|
if not name in self._cache:
|
||||||
|
image = Image()
|
||||||
|
image.name = name
|
||||||
|
image.path = path
|
||||||
|
image.image = resize_image(path,
|
||||||
|
self.width, self.height)
|
||||||
|
self._cache[name] = image
|
||||||
|
self._cache_dirty = True
|
||||||
|
# only one thread please
|
||||||
|
if not self._thread_running:
|
||||||
|
self.image_thread.start()
|
||||||
|
|
||||||
|
def process(self):
|
||||||
|
"""
|
||||||
|
Controls the processing called from a QThread
|
||||||
|
"""
|
||||||
|
log.debug(u'process - started')
|
||||||
|
self._thread_running = True
|
||||||
|
self.clean_cache()
|
||||||
|
# data loaded since we started ?
|
||||||
|
while self._cache_dirty:
|
||||||
|
log.debug(u'process - recycle')
|
||||||
|
self.clean_cache()
|
||||||
|
self._thread_running = False
|
||||||
|
log.debug(u'process - ended')
|
||||||
|
|
||||||
|
def clean_cache(self):
|
||||||
|
"""
|
||||||
|
Actually does the work.
|
||||||
|
"""
|
||||||
|
log.debug(u'clean_cache')
|
||||||
|
# we will clean the cache now
|
||||||
|
self._cache_dirty = False
|
||||||
|
for key in self._cache.keys():
|
||||||
|
image = self._cache[key]
|
||||||
|
if image.dirty:
|
||||||
|
image.image_bytes = image_to_byte(image.image)
|
||||||
|
image.dirty = False
|
@ -51,11 +51,6 @@ class Renderer(object):
|
|||||||
self._rect = None
|
self._rect = None
|
||||||
self.theme_name = None
|
self.theme_name = None
|
||||||
self._theme = None
|
self._theme = None
|
||||||
self._bg_image_filename = None
|
|
||||||
self.frame = None
|
|
||||||
self.bg_frame = None
|
|
||||||
self.bg_image = None
|
|
||||||
self.bg_image_bytes = None
|
|
||||||
|
|
||||||
def set_theme(self, theme):
|
def set_theme(self, theme):
|
||||||
"""
|
"""
|
||||||
@ -66,14 +61,7 @@ class Renderer(object):
|
|||||||
"""
|
"""
|
||||||
log.debug(u'set theme')
|
log.debug(u'set theme')
|
||||||
self._theme = theme
|
self._theme = theme
|
||||||
self.bg_frame = None
|
|
||||||
self.bg_image = None
|
|
||||||
self.bg_image_bytes = None
|
|
||||||
self._bg_image_filename = None
|
|
||||||
self.theme_name = theme.theme_name
|
self.theme_name = theme.theme_name
|
||||||
if theme.background_type == u'image':
|
|
||||||
if theme.background_filename:
|
|
||||||
self._bg_image_filename = unicode(theme.background_filename)
|
|
||||||
|
|
||||||
def set_text_rectangle(self, rect_main, rect_footer):
|
def set_text_rectangle(self, rect_main, rect_footer):
|
||||||
"""
|
"""
|
||||||
@ -105,39 +93,6 @@ class Renderer(object):
|
|||||||
(build_lyrics_format_css(self._theme, self.page_width,
|
(build_lyrics_format_css(self._theme, self.page_width,
|
||||||
self.page_height), build_lyrics_outline_css(self._theme))
|
self.page_height), build_lyrics_outline_css(self._theme))
|
||||||
|
|
||||||
def set_frame_dest(self, frame_width, frame_height):
|
|
||||||
"""
|
|
||||||
Set the size of the slide.
|
|
||||||
|
|
||||||
``frame_width``
|
|
||||||
The width of the slide.
|
|
||||||
|
|
||||||
``frame_height``
|
|
||||||
The height of the slide.
|
|
||||||
|
|
||||||
"""
|
|
||||||
log.debug(u'set frame dest (frame) w %d h %d', frame_width,
|
|
||||||
frame_height)
|
|
||||||
self.frame = QtGui.QImage(frame_width, frame_height,
|
|
||||||
QtGui.QImage.Format_ARGB32_Premultiplied)
|
|
||||||
if self._bg_image_filename and not self.bg_image:
|
|
||||||
self.bg_image = resize_image(self._bg_image_filename,
|
|
||||||
self.frame.width(), self.frame.height())
|
|
||||||
if self._theme.background_type == u'image':
|
|
||||||
self.bg_frame = QtGui.QImage(self.frame.width(),
|
|
||||||
self.frame.height(),
|
|
||||||
QtGui.QImage.Format_ARGB32_Premultiplied)
|
|
||||||
painter = QtGui.QPainter()
|
|
||||||
painter.begin(self.bg_frame)
|
|
||||||
painter.fillRect(self.frame.rect(), QtCore.Qt.black)
|
|
||||||
if self.bg_image:
|
|
||||||
painter.drawImage(0, 0, self.bg_image)
|
|
||||||
painter.end()
|
|
||||||
self.bg_image_bytes = image_to_byte(self.bg_frame)
|
|
||||||
else:
|
|
||||||
self.bg_frame = None
|
|
||||||
self.bg_image_bytes = None
|
|
||||||
|
|
||||||
def format_slide(self, words, line_break):
|
def format_slide(self, words, line_break):
|
||||||
"""
|
"""
|
||||||
Figure out how much text can appear on a slide, using the current
|
Figure out how much text can appear on a slide, using the current
|
||||||
|
@ -28,7 +28,7 @@ import logging
|
|||||||
|
|
||||||
from PyQt4 import QtCore
|
from PyQt4 import QtCore
|
||||||
|
|
||||||
from openlp.core.lib import Renderer, ThemeLevel, ServiceItem
|
from openlp.core.lib import Renderer, ThemeLevel, ServiceItem, ImageManager
|
||||||
from openlp.core.ui import MainDisplay
|
from openlp.core.ui import MainDisplay
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
@ -56,7 +56,9 @@ class RenderManager(object):
|
|||||||
"""
|
"""
|
||||||
log.debug(u'Initilisation started')
|
log.debug(u'Initilisation started')
|
||||||
self.screens = screens
|
self.screens = screens
|
||||||
|
self.image_manager = ImageManager()
|
||||||
self.display = MainDisplay(self, screens, False)
|
self.display = MainDisplay(self, screens, False)
|
||||||
|
self.display.imageManager = self.image_manager
|
||||||
self.display.setup()
|
self.display.setup()
|
||||||
self.theme_manager = theme_manager
|
self.theme_manager = theme_manager
|
||||||
self.renderer = Renderer()
|
self.renderer = Renderer()
|
||||||
@ -75,9 +77,11 @@ class RenderManager(object):
|
|||||||
log.debug(u'Update Display')
|
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 = MainDisplay(self, self.screens, False)
|
||||||
|
self.display.imageManager = self.image_manager
|
||||||
self.display.setup()
|
self.display.setup()
|
||||||
self.renderer.bg_frame = None
|
self.renderer.bg_frame = None
|
||||||
self.themedata = None
|
self.themedata = None
|
||||||
|
self.image_manager.update_display(self.width, self.height)
|
||||||
|
|
||||||
def set_global_theme(self, global_theme, theme_level=ThemeLevel.Global):
|
def set_global_theme(self, global_theme, theme_level=ThemeLevel.Global):
|
||||||
"""
|
"""
|
||||||
@ -153,7 +157,8 @@ class RenderManager(object):
|
|||||||
self.calculate_default(self.screens.current[u'size'])
|
self.calculate_default(self.screens.current[u'size'])
|
||||||
self.renderer.set_theme(self.themedata)
|
self.renderer.set_theme(self.themedata)
|
||||||
self.build_text_rectangle(self.themedata)
|
self.build_text_rectangle(self.themedata)
|
||||||
self.renderer.set_frame_dest(self.width, self.height)
|
self.image_manager.add_image(self.themedata.theme_name,
|
||||||
|
self.themedata.background_filename)
|
||||||
return self.renderer._rect, self.renderer._rect_footer
|
return self.renderer._rect, self.renderer._rect_footer
|
||||||
|
|
||||||
def build_text_rectangle(self, theme):
|
def build_text_rectangle(self, theme):
|
||||||
@ -211,7 +216,7 @@ class RenderManager(object):
|
|||||||
serviceItem.raw_footer = footer
|
serviceItem.raw_footer = footer
|
||||||
serviceItem.render(True)
|
serviceItem.render(True)
|
||||||
self.display.buildHtml(serviceItem)
|
self.display.buildHtml(serviceItem)
|
||||||
raw_html = serviceItem.get_rendered_frame(0)[1]
|
raw_html = serviceItem.get_rendered_frame(0)
|
||||||
preview = self.display.text(raw_html)
|
preview = self.display.text(raw_html)
|
||||||
# Reset the real screen size for subsequent render requests
|
# 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'])
|
||||||
|
@ -30,7 +30,6 @@ type and capability of an item.
|
|||||||
|
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import time
|
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
from PyQt4 import QtGui
|
from PyQt4 import QtGui
|
||||||
@ -160,12 +159,10 @@ class ServiceItem(object):
|
|||||||
theme = self.theme
|
theme = self.theme
|
||||||
self.main, self.footer = \
|
self.main, self.footer = \
|
||||||
self.render_manager.set_override_theme(theme, useOverride)
|
self.render_manager.set_override_theme(theme, useOverride)
|
||||||
self.bg_image_bytes = self.render_manager.renderer.bg_image_bytes
|
|
||||||
self.themedata = self.render_manager.renderer._theme
|
self.themedata = self.render_manager.renderer._theme
|
||||||
if self.service_item_type == ServiceItemType.Text:
|
if self.service_item_type == ServiceItemType.Text:
|
||||||
log.debug(u'Formatting slides')
|
log.debug(u'Formatting slides')
|
||||||
for slide in self._raw_frames:
|
for slide in self._raw_frames:
|
||||||
before = time.time()
|
|
||||||
formatted = self.render_manager \
|
formatted = self.render_manager \
|
||||||
.format_slide(slide[u'raw_slide'], line_break)
|
.format_slide(slide[u'raw_slide'], line_break)
|
||||||
for page in formatted:
|
for page in formatted:
|
||||||
@ -174,12 +171,8 @@ class ServiceItem(object):
|
|||||||
u'text': clean_tags(page.rstrip()),
|
u'text': clean_tags(page.rstrip()),
|
||||||
u'html': expand_tags(page.rstrip()),
|
u'html': expand_tags(page.rstrip()),
|
||||||
u'verseTag': slide[u'verseTag'] })
|
u'verseTag': slide[u'verseTag'] })
|
||||||
log.log(15, u'Formatting took %4s' % (time.time() - before))
|
elif self.service_item_type == ServiceItemType.Image or \
|
||||||
elif self.service_item_type == ServiceItemType.Image:
|
self.service_item_type == ServiceItemType.Command:
|
||||||
for slide in self._raw_frames:
|
|
||||||
slide[u'image'] = resize_image(slide[u'image'],
|
|
||||||
self.render_manager.width, self.render_manager.height)
|
|
||||||
elif self.service_item_type == ServiceItemType.Command:
|
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
log.error(u'Invalid value renderer :%s' % self.service_item_type)
|
log.error(u'Invalid value renderer :%s' % self.service_item_type)
|
||||||
@ -192,7 +185,7 @@ class ServiceItem(object):
|
|||||||
else:
|
else:
|
||||||
self.foot_text = u'%s<br>%s' % (self.foot_text, foot)
|
self.foot_text = u'%s<br>%s' % (self.foot_text, foot)
|
||||||
|
|
||||||
def add_from_image(self, path, title, image):
|
def add_from_image(self, path, title):
|
||||||
"""
|
"""
|
||||||
Add an image slide to the service item.
|
Add an image slide to the service item.
|
||||||
|
|
||||||
@ -201,13 +194,11 @@ class ServiceItem(object):
|
|||||||
|
|
||||||
``title``
|
``title``
|
||||||
A title for the slide in the service item.
|
A title for the slide in the service item.
|
||||||
|
|
||||||
``image``
|
|
||||||
The actual image file name.
|
|
||||||
"""
|
"""
|
||||||
self.service_item_type = ServiceItemType.Image
|
self.service_item_type = ServiceItemType.Image
|
||||||
self._raw_frames.append(
|
self._raw_frames.append(
|
||||||
{u'title': title, u'image': image, u'path': path})
|
{u'title': title, u'path': path})
|
||||||
|
self.render_manager.image_manager.add_image(title, path)
|
||||||
self._new_item()
|
self._new_item()
|
||||||
|
|
||||||
def add_from_text(self, title, raw_slide, verse_tag=None):
|
def add_from_text(self, title, raw_slide, verse_tag=None):
|
||||||
@ -310,8 +301,7 @@ class ServiceItem(object):
|
|||||||
elif self.service_item_type == ServiceItemType.Image:
|
elif self.service_item_type == ServiceItemType.Image:
|
||||||
for text_image in serviceitem[u'serviceitem'][u'data']:
|
for text_image in serviceitem[u'serviceitem'][u'data']:
|
||||||
filename = os.path.join(path, text_image)
|
filename = os.path.join(path, text_image)
|
||||||
real_image = QtGui.QImage(unicode(filename))
|
self.add_from_image(filename, text_image)
|
||||||
self.add_from_image(path, text_image, real_image)
|
|
||||||
elif self.service_item_type == ServiceItemType.Command:
|
elif self.service_item_type == ServiceItemType.Command:
|
||||||
for text_image in serviceitem[u'serviceitem'][u'data']:
|
for text_image in serviceitem[u'serviceitem'][u'data']:
|
||||||
filename = os.path.join(path, text_image[u'title'])
|
filename = os.path.join(path, text_image[u'title'])
|
||||||
@ -387,9 +377,11 @@ class ServiceItem(object):
|
|||||||
renders it if required.
|
renders it if required.
|
||||||
"""
|
"""
|
||||||
if self.service_item_type == ServiceItemType.Text:
|
if self.service_item_type == ServiceItemType.Text:
|
||||||
return None, self._display_frames[row][u'html'].split(u'\n')[0]
|
return self._display_frames[row][u'html'].split(u'\n')[0]
|
||||||
|
elif self.service_item_type == ServiceItemType.Image:
|
||||||
|
return self._raw_frames[row][u'title']
|
||||||
else:
|
else:
|
||||||
return self._raw_frames[row][u'image'], u''
|
return self._raw_frames[row][u'image']
|
||||||
|
|
||||||
def get_frame_title(self, row=0):
|
def get_frame_title(self, row=0):
|
||||||
"""
|
"""
|
||||||
|
@ -225,7 +225,14 @@ class MainDisplay(DisplayWidget):
|
|||||||
shrinkItem.resize(self.screen[u'size'].width(),
|
shrinkItem.resize(self.screen[u'size'].width(),
|
||||||
self.screen[u'size'].height())
|
self.screen[u'size'].height())
|
||||||
|
|
||||||
def image(self, image):
|
def directImage(self, name, path):
|
||||||
|
"""
|
||||||
|
API for replacement backgrounds so Images are added directly to cache
|
||||||
|
"""
|
||||||
|
image = self.imageManager.add_image(name, path)
|
||||||
|
self.image(name)
|
||||||
|
|
||||||
|
def image(self, name):
|
||||||
"""
|
"""
|
||||||
Add an image as the background. The image is converted to a
|
Add an image as the background. The image is converted to a
|
||||||
bytestream on route.
|
bytestream on route.
|
||||||
@ -234,24 +241,19 @@ class MainDisplay(DisplayWidget):
|
|||||||
The Image to be displayed can be QImage or QPixmap
|
The Image to be displayed can be QImage or QPixmap
|
||||||
"""
|
"""
|
||||||
log.debug(u'image to display')
|
log.debug(u'image to display')
|
||||||
if not isinstance(image, QtGui.QImage):
|
image = self.imageManager.get_image_bytes(name)
|
||||||
image = resize_image(image, self.screen[u'size'].width(),
|
|
||||||
self.screen[u'size'].height())
|
|
||||||
self.resetVideo()
|
self.resetVideo()
|
||||||
self.displayImage(image)
|
self.displayImage(image)
|
||||||
# show screen
|
# show screen
|
||||||
if self.isLive:
|
if self.isLive:
|
||||||
self.setVisible(True)
|
self.setVisible(True)
|
||||||
|
return self.preview()
|
||||||
|
|
||||||
def displayImage(self, image):
|
def displayImage(self, image):
|
||||||
"""
|
"""
|
||||||
Display an image, as is.
|
Display an image, as is.
|
||||||
"""
|
"""
|
||||||
if image:
|
if image:
|
||||||
if isinstance(image, QtGui.QImage):
|
|
||||||
js = u'show_image("data:image/png;base64,%s");' % \
|
|
||||||
image_to_byte(image)
|
|
||||||
else:
|
|
||||||
js = u'show_image("data:image/png;base64,%s");' % image
|
js = u'show_image("data:image/png;base64,%s");' % image
|
||||||
else:
|
else:
|
||||||
js = u'show_image("");'
|
js = u'show_image("");'
|
||||||
@ -399,6 +401,9 @@ class MainDisplay(DisplayWidget):
|
|||||||
self.loaded = False
|
self.loaded = False
|
||||||
self.initialFrame = False
|
self.initialFrame = False
|
||||||
self.serviceItem = serviceItem
|
self.serviceItem = serviceItem
|
||||||
|
if self.serviceItem.themedata.background_filename:
|
||||||
|
self.serviceItem.bg_image_bytes = self.imageManager. \
|
||||||
|
get_image_bytes(self.serviceItem.themedata.theme_name)
|
||||||
html = build_html(self.serviceItem, self.screen, self.parent.alertTab,
|
html = build_html(self.serviceItem, self.screen, self.parent.alertTab,
|
||||||
self.isLive)
|
self.isLive)
|
||||||
log.debug(u'buildHtml - pre setHtml')
|
log.debug(u'buildHtml - pre setHtml')
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
|
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
import time
|
||||||
|
|
||||||
from PyQt4 import QtCore, QtGui
|
from PyQt4 import QtCore, QtGui
|
||||||
from PyQt4.phonon import Phonon
|
from PyQt4.phonon import Phonon
|
||||||
@ -400,6 +401,7 @@ class SlideController(QtGui.QWidget):
|
|||||||
log.debug(u'screenSizeChanged live = %s' % self.isLive)
|
log.debug(u'screenSizeChanged live = %s' % self.isLive)
|
||||||
# rebuild display as screen size changed
|
# rebuild display as screen size changed
|
||||||
self.display = MainDisplay(self, self.screens, self.isLive)
|
self.display = MainDisplay(self, self.screens, self.isLive)
|
||||||
|
self.display.imageManager = self.parent.RenderManager.image_manager
|
||||||
self.display.alertTab = self.alertTab
|
self.display.alertTab = self.alertTab
|
||||||
self.ratio = float(self.screens.current[u'size'].width()) / \
|
self.ratio = float(self.screens.current[u'size'].width()) / \
|
||||||
float(self.screens.current[u'size'].height())
|
float(self.screens.current[u'size'].height())
|
||||||
@ -585,13 +587,14 @@ class SlideController(QtGui.QWidget):
|
|||||||
label = QtGui.QLabel()
|
label = QtGui.QLabel()
|
||||||
label.setMargin(4)
|
label.setMargin(4)
|
||||||
label.setScaledContents(True)
|
label.setScaledContents(True)
|
||||||
if isinstance(frame[u'image'], QtGui.QImage):
|
if self.serviceItem.is_command():
|
||||||
label.setPixmap(QtGui.QPixmap.fromImage(frame[u'image']))
|
image = resize_image(frame[u'image'],
|
||||||
else:
|
|
||||||
pixmap = resize_image(frame[u'image'],
|
|
||||||
self.parent.RenderManager.width,
|
self.parent.RenderManager.width,
|
||||||
self.parent.RenderManager.height)
|
self.parent.RenderManager.height)
|
||||||
label.setPixmap(QtGui.QPixmap.fromImage(pixmap))
|
else:
|
||||||
|
image = self.parent.RenderManager.image_manager. \
|
||||||
|
get_image(frame[u'title'])
|
||||||
|
label.setPixmap(QtGui.QPixmap.fromImage(image))
|
||||||
self.PreviewListWidget.setCellWidget(framenumber, 0, label)
|
self.PreviewListWidget.setCellWidget(framenumber, 0, label)
|
||||||
slideHeight = width * self.parent.RenderManager.screen_ratio
|
slideHeight = width * self.parent.RenderManager.screen_ratio
|
||||||
row += 1
|
row += 1
|
||||||
@ -782,15 +785,12 @@ class SlideController(QtGui.QWidget):
|
|||||||
[self.serviceItem, self.isLive, row])
|
[self.serviceItem, self.isLive, row])
|
||||||
self.updatePreview()
|
self.updatePreview()
|
||||||
else:
|
else:
|
||||||
frame, raw_html = self.serviceItem.get_rendered_frame(row)
|
toDisplay = self.serviceItem.get_rendered_frame(row)
|
||||||
if self.serviceItem.is_text():
|
if self.serviceItem.is_text():
|
||||||
frame = self.display.text(raw_html)
|
frame = self.display.text(toDisplay)
|
||||||
else:
|
else:
|
||||||
self.display.image(frame)
|
frame = self.display.image(toDisplay)
|
||||||
if isinstance(frame, QtGui.QImage):
|
|
||||||
self.SlidePreview.setPixmap(QtGui.QPixmap.fromImage(frame))
|
self.SlidePreview.setPixmap(QtGui.QPixmap.fromImage(frame))
|
||||||
else:
|
|
||||||
self.SlidePreview.setPixmap(QtGui.QPixmap(frame))
|
|
||||||
self.selectedRow = row
|
self.selectedRow = row
|
||||||
Receiver.send_message(u'slidecontroller_%s_changed' % self.typePrefix,
|
Receiver.send_message(u'slidecontroller_%s_changed' % self.typePrefix,
|
||||||
row)
|
row)
|
||||||
|
@ -166,9 +166,8 @@ class ImageMediaItem(MediaManagerItem):
|
|||||||
for item in items:
|
for item in items:
|
||||||
bitem = self.listView.item(item.row())
|
bitem = self.listView.item(item.row())
|
||||||
filename = unicode(bitem.data(QtCore.Qt.UserRole).toString())
|
filename = unicode(bitem.data(QtCore.Qt.UserRole).toString())
|
||||||
frame = QtGui.QImage(unicode(filename))
|
|
||||||
(path, name) = os.path.split(filename)
|
(path, name) = os.path.split(filename)
|
||||||
service_item.add_from_image(path, name, frame)
|
service_item.add_from_image(filename, name)
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
@ -185,7 +184,8 @@ class ImageMediaItem(MediaManagerItem):
|
|||||||
for item in items:
|
for item in items:
|
||||||
bitem = self.listView.item(item.row())
|
bitem = self.listView.item(item.row())
|
||||||
filename = unicode(bitem.data(QtCore.Qt.UserRole).toString())
|
filename = unicode(bitem.data(QtCore.Qt.UserRole).toString())
|
||||||
self.parent.liveController.display.image(filename)
|
(path, name) = os.path.split(filename)
|
||||||
|
self.parent.liveController.display.directImage(name, filename)
|
||||||
self.resetButton.setVisible(True)
|
self.resetButton.setVisible(True)
|
||||||
|
|
||||||
def onPreviewClick(self):
|
def onPreviewClick(self):
|
||||||
|
Loading…
Reference in New Issue
Block a user