reworked image manager _cache to contain unique images (to be cleaned up)

This commit is contained in:
Andreas Preikschat 2012-06-30 17:19:33 +02:00
parent 78753d03dc
commit 9da23266c6
9 changed files with 77 additions and 72 deletions

View File

@ -96,6 +96,15 @@ class Priority(object):
Urgent = 0
class ImageSource(object):
"""
This enumeration class represents different image sources. An image sources
states where an image is used.
"""
ImagePlugin = 1
Theme = 2
class Image(object):
"""
This class represents an image. To mark an image as *dirty* call the
@ -103,27 +112,22 @@ class Image(object):
argument.
"""
secondary_priority = 0
def __init__(self, name, path, source, background):
def __init__(self, path, source, background):
"""
Create an image for the :class:`ImageManager`'s cache.
``name``
The image name. This does not have to be part of the ``path``. It
can be of any value. It can be considered an ID.
``path``
The image's file path. This should be an existing file path.
``source``
The source describes the image's origin. Possible values are
``image`` and ``theme``.
``background``
A ``QtGui.QColor`` object specifying the colour to be used to fill
the gabs if the image's ratio does not match with the display ratio.
"""
self.name = name
self.path = path
self.image = None
self.image_bytes = None
@ -192,6 +196,7 @@ class ImageManager(QtCore.QObject):
self.imageThread = ImageThread(self)
self._conversionQueue = PriorityQueue()
self.stopManager = False
self.imageSource = ImageSource()
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'config_updated'), self.processUpdates)
@ -220,14 +225,14 @@ class ImageManager(QtCore.QObject):
image.background = background
self._resetImage(image)
def updateImageBorder(self, name, source, background):
def updateImageBorder(self, path, source, background):
"""
Border has changed so update the image affected.
"""
log.debug(u'updateImage')
# Mark the image as dirty for a rebuild by setting the image and byte
# stream to None.
image = self._cache[name]
image = self._cache[(path, source)]
if image.source == source:
image.background = background
self._resetImage(image)
@ -249,13 +254,13 @@ class ImageManager(QtCore.QObject):
if not self.imageThread.isRunning():
self.imageThread.start()
def getImage(self, name):
def getImage(self, path, source):
"""
Return the ``QImage`` from the cache. If not present wait for the
background thread to process it.
"""
log.debug(u'getImage %s' % name)
image = self._cache[name]
log.debug(u'getImage %s' % path)
image = self._cache[(path, source)]
if image.image is None:
self._conversionQueue.modify_priority(image, Priority.High)
# make sure we are running and if not give it a kick
@ -271,13 +276,13 @@ class ImageManager(QtCore.QObject):
self._conversionQueue.modify_priority(image, Priority.Low)
return image.image
def getImageBytes(self, name):
def getImageBytes(self, path, source):
"""
Returns the byte string for an image. If not present wait for the
background thread to process it.
"""
log.debug(u'getImageBytes %s' % name)
image = self._cache[name]
log.debug(u'getImageBytes %s' % path)
image = self._cache[(path, source)]
if image.image_bytes is None:
self._conversionQueue.modify_priority(image, Priority.Urgent)
# make sure we are running and if not give it a kick
@ -287,24 +292,22 @@ class ImageManager(QtCore.QObject):
time.sleep(0.1)
return image.image_bytes
def addImage(self, name, path, source, background):
def addImage(self, path, source, background):
"""
Add image to cache if it is not already there.
"""
log.debug(u'addImage %s:%s' % (name, path))
if not name in self._cache:
image = Image(name, path, source, background)
self._cache[name] = image
log.debug(u'addImage %s' % path)
if not (path, source) in self._cache:
image = Image(path, source, background)
self._cache[(path, source)] = image
self._conversionQueue.put(
(image.priority, image.secondary_priority, image))
else:
image = self._cache[name]
if os.path.isfile(path) and \
image.timestamp != os.stat(path).st_mtime:
image.path = path
# Check if the there are any images with the same path and check if the
# timestamp has changed.
for image in self._cache.values():
if image.path == path and image.timestamp != os.stat(path).st_mtime:
image.timestamp = os.stat(path).st_mtime
self._resetImage(image)
log.debug(u'Image in cache %s:%s' % (name, path))
# We want only one thread.
if not self.imageThread.isRunning():
self.imageThread.start()

View File

@ -135,11 +135,10 @@ class Renderer(object):
else:
theme_data, main_rect, footer_rect = \
self._theme_dimensions[theme_name]
#FIXME: REMOVE deleteImage() call which will be added soon.
# if No file do not update cache
if theme_data.background_filename:
self.image_manager.addImage(theme_data.theme_name,
theme_data.background_filename, u'theme',
self.image_manager.addImage(theme_data.background_filename,
self.image_manager.imageSource.Theme,
QtGui.QColor(theme_data.background_border_color))
def pre_render(self, override_theme_data=None):
@ -243,8 +242,8 @@ class Renderer(object):
serviceItem.raw_footer = FOOTER
# if No file do not update cache
if theme_data.background_filename:
self.image_manager.addImage(theme_data.theme_name,
theme_data.background_filename, u'theme',
self.image_manager.addImage(theme_data.background_filename,
self.image_manager.imageSource.Theme,
QtGui.QColor(theme_data.background_border_color))
theme_data, main, footer = self.pre_render(theme_data)
serviceItem.themedata = theme_data

View File

@ -217,7 +217,8 @@ class ServiceItem(object):
self.image_border = background
self.service_item_type = ServiceItemType.Image
self._raw_frames.append({u'title': title, u'path': path})
self.renderer.image_manager.addImage(title, path, u'image',
self.renderer.image_manager.addImage(path,
self.renderer.image_manager.imageSource.ImagePlugin,
self.image_border)
self._new_item()
@ -432,13 +433,12 @@ class ServiceItem(object):
def get_rendered_frame(self, row):
"""
Returns the correct frame for a given list and
renders it if required.
Returns the correct frame for a given list and renders it if required.
"""
if self.service_item_type == ServiceItemType.Text:
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']
return self._raw_frames[row][u'path']
else:
return self._raw_frames[row][u'image']

View File

@ -274,31 +274,33 @@ class MainDisplay(Display):
self.setVisible(False)
self.setGeometry(self.screen[u'size'])
def directImage(self, name, path, background):
def directImage(self, path, background):
"""
API for replacement backgrounds so Images are added directly to cache.
"""
self.imageManager.addImage(name, path, u'image', background)
if hasattr(self, u'serviceItem'):
self.override[u'image'] = name
self.override[u'theme'] = self.serviceItem.themedata.theme_name
self.image(name)
# Update the preview frame.
if self.isLive:
self.parent().updatePreview()
return True
return False
self.imageManager.addImage(path, self.imageManager.imageSource.ImagePlugin, background)
if not hasattr(self, u'serviceItem'):
return False
self.override[u'image'] = path
self.override[u'theme'] = self.serviceItem.themedata.background_filename
self.image(path)
# Update the preview frame.
if self.isLive:
self.parent().updatePreview()
return True
def image(self, name):
def image(self, path):
"""
Add an image as the background. The image has already been added to the
cache.
``name``
The name of the image to be displayed.
``path``
The path to the image to be displayed. **Note**, the path is only
passed to identify the image. If the image has changed it has to be
re-added to the image manager.
"""
log.debug(u'image to display')
image = self.imageManager.getImageBytes(name)
image = self.imageManager.getImageBytes(path, self.imageManager.imageSource.ImagePlugin)
self.controller.mediaController.video_reset(self.controller)
self.displayImage(image)
@ -360,7 +362,7 @@ class MainDisplay(Display):
self.setVisible(True)
return QtGui.QPixmap.grabWidget(self)
def buildHtml(self, serviceItem, image=None):
def buildHtml(self, serviceItem, image_path=u''):
"""
Store the serviceItem and build the new HTML from it. Add the
HTML to the display
@ -377,20 +379,20 @@ class MainDisplay(Display):
Receiver.send_message(u'video_background_replaced')
self.override = {}
# We have a different theme.
elif self.override[u'theme'] != serviceItem.themedata.theme_name:
elif self.override[u'theme'] != serviceItem.themedata.background_filename:
Receiver.send_message(u'live_theme_changed')
self.override = {}
else:
# replace the background
background = self.imageManager. \
getImageBytes(self.override[u'image'])
getImageBytes(self.override[u'image'], self.imageManager.imageSource.ImagePlugin)
self.setTransparency(self.serviceItem.themedata.background_type ==
BackgroundType.to_string(BackgroundType.Transparent))
if self.serviceItem.themedata.background_filename:
self.serviceItem.bg_image_bytes = self.imageManager. \
getImageBytes(self.serviceItem.themedata.theme_name)
if image:
image_bytes = self.imageManager.getImageBytes(image)
getImageBytes(self.serviceItem.themedata.background_filename, self.imageManager.imageSource.Theme)
if image_path:
image_bytes = self.imageManager.getImageBytes(image_path, self.imageManager.imageSource.ImagePlugin)
else:
image_bytes = None
html = build_html(self.serviceItem, self.screen, self.isLive,

View File

@ -861,8 +861,10 @@ class SlideController(Controller):
# If current slide set background to image
if framenumber == slideno:
self.serviceItem.bg_image_bytes = \
self.imageManager.getImageBytes(frame[u'title'])
image = self.imageManager.getImage(frame[u'title'])
self.imageManager.getImageBytes(frame[u'path'],
self.imageManager.imageSource.ImagePlugin)
image = self.imageManager.getImage(frame[u'path'],
self.imageManager.imageSource.ImagePlugin)
label.setPixmap(QtGui.QPixmap.fromImage(image))
self.previewListWidget.setCellWidget(framenumber, 0, label)
slideHeight = width * (1 / self.ratio)
@ -1092,14 +1094,14 @@ class SlideController(Controller):
u'%s_slide' % self.serviceItem.name.lower(),
[self.serviceItem, self.isLive, row])
else:
toDisplay = self.serviceItem.get_rendered_frame(row)
to_display = self.serviceItem.get_rendered_frame(row)
if self.serviceItem.is_text():
self.display.text(toDisplay)
self.display.text(to_display)
else:
if start:
self.display.buildHtml(self.serviceItem, toDisplay)
self.display.buildHtml(self.serviceItem, to_display)
else:
self.display.image(toDisplay)
self.display.image(to_display)
# reset the store used to display first image
self.serviceItem.bg_image_bytes = None
self.updatePreview()

View File

@ -669,8 +669,9 @@ class ThemeManager(QtGui.QWidget):
self._writeTheme(theme, image_from, image_to)
if theme.background_type == \
BackgroundType.to_string(BackgroundType.Image):
self.mainwindow.imageManager.updateImageBorder(theme.theme_name,
u'theme', QtGui.QColor(theme.background_border_color))
self.mainwindow.imageManager.updateImageBorder(
theme.background_filename,
self.mainwindow.imageManager.imageSource.Theme, QtGui.QColor(theme.background_border_color))
self.mainwindow.imageManager.processUpdates()
self.loadThemes()

View File

@ -99,4 +99,4 @@ class ImagePlugin(Plugin):
background = QtGui.QColor(Settings().value(self.settingsSection
+ u'/background color', QtCore.QVariant(u'#000000')))
self.liveController.imageManager.updateImagesBorder(
u'image', background)
self.liveController.imageManager.imageSource.ImagePlugin, background)

View File

@ -229,8 +229,7 @@ class ImageMediaItem(MediaManagerItem):
bitem = self.listView.item(item.row())
filename = unicode(bitem.data(QtCore.Qt.UserRole).toString())
if os.path.exists(filename):
name = os.path.split(filename)[1]
if self.plugin.liveController.display.directImage(name,
if self.plugin.liveController.display.directImage(
filename, background):
self.resetAction.setVisible(True)
else:

View File

@ -278,8 +278,7 @@ class MessageListener(object):
item = message[0]
log.debug(u'Startup called with message %s' % message)
hide_mode = message[2]
file = os.path.join(item.get_frame_path(),
item.get_frame_title())
file = os.path.join(item.get_frame_path(), item.get_frame_title())
self.handler = item.title
if self.handler == self.mediaitem.Automatic:
self.handler = self.mediaitem.findControllerByType(file)