Andreas Preikschat has proposed merging lp:~googol/openlp/image-queue into lp:openlp.
Requested reviews: Tim Bentley (trb143) For more details, see: https://code.launchpad.net/~googol/openlp/image-queue/+merge/112948 Hello - update the image cache when the image timestamp changes (1. Bug) - reworked image manager's _cache (2. Bug and 3. Bug) 1. Bug: 1) Display/preview an image. 2) Edit the image. 3) Send it live/preview again. Result: Cache is not updated. Expected: Cache is updated. You especially expect this when you delete and add the image again. 2. Bug: 1) Open a service file with an image named test.jpg 2) Show it live/preview it 3) Send another image live/preview which has the same name (test.jpg), but a different content. Result: The second image shown is not correct. Expected: The second image should show the correct image. 3. Bug: 1) Send an item live/preview it (should not have an theme assigned) 2) Change a theme's background image (do not complete the wizard, cancel it on the last page). 3) Send the same item live again Result: The item incorrectly uses the image you changed in the theme wizard. Expected: The item should still use the correct image. -- https://code.launchpad.net/~googol/openlp/image-queue/+merge/112948 Your team OpenLP Core is subscribed to branch lp:openlp.
=== modified file 'openlp/core/lib/__init__.py' --- openlp/core/lib/__init__.py 2012-06-22 14:14:53 +0000 +++ openlp/core/lib/__init__.py 2012-07-01 19:42:22 +0000 @@ -36,6 +36,23 @@ log = logging.getLogger(__name__) + +class ImageSource(object): + """ + This enumeration class represents different image sources. An image sources + states where an image is used. This enumeration class is need in the context + of the :class:~openlp.core.lib.imagemanager`. + + ``ImagePlugin`` + This states that an image is being used by the image plugin. + + ``Theme`` + This says, that the image is used by a theme. + """ + ImagePlugin = 1 + Theme = 2 + + class MediaType(object): """ An enumeration class for types of media. === modified file 'openlp/core/lib/imagemanager.py' --- openlp/core/lib/imagemanager.py 2012-06-22 14:14:53 +0000 +++ openlp/core/lib/imagemanager.py 2012-07-01 19:42:22 +0000 @@ -32,6 +32,7 @@ to wait for the conversion to happen. """ import logging +import os import time import Queue @@ -97,19 +98,34 @@ class Image(object): """ - This class represents an image. To mark an image as *dirty* set the instance - variables ``image`` and ``image_bytes`` to ``None`` and add the image object - to the queue of images to process. + This class represents an image. To mark an image as *dirty* call the + :class:`ImageManager`'s ``_resetImage`` method with the Image instance as + argument. """ secondary_priority = 0 - def __init__(self, name, path, source, background): - self.name = name + + def __init__(self, path, source, background): + """ + Create an image for the :class:`ImageManager`'s cache. + + ``path`` + The image's file path. This should be an existing file path. + + ``source`` + The source describes the image's origin. Possible values are + described in the :class:`~openlp.core.lib.ImageSource` class. + + ``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.path = path self.image = None self.image_bytes = None self.priority = Priority.Normal self.source = source self.background = background + self.timestamp = os.stat(path).st_mtime self.secondary_priority = Image.secondary_priority Image.secondary_priority += 1 @@ -118,7 +134,7 @@ """ Customised ``Queue.PriorityQueue``. - Each item in the queue must be tuple with three values. The first value + Each item in the queue must be a tuple with three values. The first value is the :class:`Image`'s ``priority`` attribute, the second value the :class:`Image`'s ``secondary_priority`` attribute. The last value the :class:`Image` instance itself:: @@ -187,7 +203,7 @@ for image in self._cache.values(): self._resetImage(image) - def updateImages(self, imageType, background): + def updateImagesBorder(self, source, background): """ Border has changed so update all the images affected. """ @@ -195,23 +211,27 @@ # Mark the images as dirty for a rebuild by setting the image and byte # stream to None. for image in self._cache.values(): - if image.source == imageType: + if image.source == source: image.background = background self._resetImage(image) - def updateImage(self, name, imageType, background): + def updateImageBorder(self, path, source, background): """ Border has changed so update the image affected. """ log.debug(u'updateImage') - # Mark the images as dirty for a rebuild by setting the image and byte + # Mark the image as dirty for a rebuild by setting the image and byte # stream to None. - for image in self._cache.values(): - if image.source == imageType and image.name == name: - image.background = background - self._resetImage(image) + image = self._cache[(path, source)] + if image.source == source: + image.background = background + self._resetImage(image) def _resetImage(self, image): + """ + Mark the given :class:`Image` instance as dirt by setting its ``image`` + and ``image_bytes`` attributes to None. + """ image.image = None image.image_bytes = None self._conversionQueue.modify_priority(image, Priority.Normal) @@ -224,13 +244,13 @@ 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 @@ -246,13 +266,13 @@ 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 @@ -262,27 +282,22 @@ time.sleep(0.1) return image.image_bytes - def deleteImage(self, name): - """ - Delete the Image from the cache. - """ - log.debug(u'deleteImage %s' % name) - if name in self._cache: - self._conversionQueue.remove(self._cache[name]) - del self._cache[name] - - 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: - log.debug(u'Image in cache %s:%s' % (name, 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) # We want only one thread. if not self.imageThread.isRunning(): self.imageThread.start() === modified file 'openlp/core/lib/renderer.py' --- openlp/core/lib/renderer.py 2012-06-22 14:14:53 +0000 +++ openlp/core/lib/renderer.py 2012-07-01 19:42:22 +0000 @@ -32,7 +32,7 @@ from openlp.core.lib import ServiceItem, expand_tags, \ build_lyrics_format_css, build_lyrics_outline_css, Receiver, \ - ItemCapabilities, FormattingTags + ItemCapabilities, FormattingTags, ImageSource from openlp.core.lib.theme import ThemeLevel from openlp.core.ui import MainDisplay, ScreenList @@ -137,8 +137,8 @@ self._theme_dimensions[theme_name] # 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, + ImageSource.Theme, QtGui.QColor(theme_data.background_border_color)) def pre_render(self, override_theme_data=None): @@ -237,14 +237,13 @@ # make big page for theme edit dialog to get line count serviceItem.add_from_text(VERSE_FOR_LINE_COUNT) else: - self.image_manager.deleteImage(theme_data.theme_name) serviceItem.add_from_text(VERSE) serviceItem.renderer = self 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, + ImageSource.Theme, QtGui.QColor(theme_data.background_border_color)) theme_data, main, footer = self.pre_render(theme_data) serviceItem.themedata = theme_data === modified file 'openlp/core/lib/serviceitem.py' --- openlp/core/lib/serviceitem.py 2012-06-22 14:14:53 +0000 +++ openlp/core/lib/serviceitem.py 2012-07-01 19:42:22 +0000 @@ -36,7 +36,8 @@ import os import uuid -from openlp.core.lib import build_icon, clean_tags, expand_tags, translate +from openlp.core.lib import build_icon, clean_tags, expand_tags, translate, \ + ImageSource log = logging.getLogger(__name__) @@ -217,8 +218,8 @@ 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.image_border) + self.renderer.image_manager.addImage( + path, ImageSource.ImagePlugin, self.image_border) self._new_item() def add_from_text(self, raw_slide, verse_tag=None): @@ -432,13 +433,12 @@ 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'] === modified file 'openlp/core/ui/maindisplay.py' --- openlp/core/ui/maindisplay.py 2012-06-22 14:14:53 +0000 +++ openlp/core/ui/maindisplay.py 2012-07-01 19:42:22 +0000 @@ -37,7 +37,7 @@ from PyQt4.phonon import Phonon from openlp.core.lib import Receiver, build_html, ServiceItem, image_to_byte, \ - translate, PluginManager, expand_tags + translate, PluginManager, expand_tags, ImageSource from openlp.core.lib.theme import BackgroundType from openlp.core.lib.settings import Settings @@ -274,31 +274,33 @@ 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, 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, ImageSource.ImagePlugin) self.controller.mediaController.video_reset(self.controller) self.displayImage(image) @@ -360,7 +362,7 @@ 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,23 @@ 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']) + background = self.imageManager.getImageBytes( + self.override[u'image'], 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) + self.serviceItem.bg_image_bytes = self.imageManager.getImageBytes( + self.serviceItem.themedata.background_filename, + ImageSource.Theme) + if image_path: + image_bytes = self.imageManager.getImageBytes( + image_path, ImageSource.ImagePlugin) else: image_bytes = None html = build_html(self.serviceItem, self.screen, self.isLive, === modified file 'openlp/core/ui/slidecontroller.py' --- openlp/core/ui/slidecontroller.py 2012-06-22 14:14:53 +0000 +++ openlp/core/ui/slidecontroller.py 2012-07-01 19:42:22 +0000 @@ -34,7 +34,7 @@ from PyQt4 import QtCore, QtGui from openlp.core.lib import OpenLPToolbar, Receiver, ItemCapabilities, \ - translate, build_icon, build_html, PluginManager, ServiceItem + translate, build_icon, build_html, PluginManager, ServiceItem, ImageSource from openlp.core.lib.ui import UiStrings, create_action from openlp.core.lib.settings import Settings from openlp.core.lib import SlideLimits, ServiceItemAction @@ -861,8 +861,10 @@ # 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'], + ImageSource.ImagePlugin) + image = self.imageManager.getImage(frame[u'path'], + ImageSource.ImagePlugin) label.setPixmap(QtGui.QPixmap.fromImage(image)) self.previewListWidget.setCellWidget(framenumber, 0, label) slideHeight = width * (1 / self.ratio) @@ -1092,14 +1094,14 @@ 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() === modified file 'openlp/core/ui/thememanager.py' --- openlp/core/ui/thememanager.py 2012-06-22 14:14:53 +0000 +++ openlp/core/ui/thememanager.py 2012-07-01 19:42:22 +0000 @@ -38,7 +38,7 @@ from openlp.core.lib import OpenLPToolbar, get_text_file_string, build_icon, \ Receiver, SettingsManager, translate, check_item_selected, \ - check_directory_exists, create_thumb, validate_thumb + check_directory_exists, create_thumb, validate_thumb, ImageSource from openlp.core.lib.theme import ThemeXML, BackgroundType, VerticalType, \ BackgroundGradientType from openlp.core.lib.settings import Settings @@ -669,8 +669,9 @@ self._writeTheme(theme, image_from, image_to) if theme.background_type == \ BackgroundType.to_string(BackgroundType.Image): - self.mainwindow.imageManager.updateImage(theme.theme_name, - u'theme', QtGui.QColor(theme.background_border_color)) + self.mainwindow.imageManager.updateImageBorder( + theme.background_filename, + ImageSource.Theme, QtGui.QColor(theme.background_border_color)) self.mainwindow.imageManager.processUpdates() self.loadThemes() === modified file 'openlp/plugins/images/imageplugin.py' --- openlp/plugins/images/imageplugin.py 2012-06-22 14:14:53 +0000 +++ openlp/plugins/images/imageplugin.py 2012-07-01 19:42:22 +0000 @@ -31,7 +31,7 @@ import logging from openlp.core.lib import Plugin, StringContent, build_icon, translate, \ - Receiver + Receiver, ImageSource from openlp.core.lib.settings import Settings from openlp.plugins.images.lib import ImageMediaItem, ImageTab @@ -98,4 +98,5 @@ """ background = QtGui.QColor(Settings().value(self.settingsSection + u'/background color', QtCore.QVariant(u'#000000'))) - self.liveController.imageManager.updateImages(u'image', background) + self.liveController.imageManager.updateImagesBorder( + ImageSource.ImagePlugin, background) === modified file 'openlp/plugins/images/lib/mediaitem.py' --- openlp/plugins/images/lib/mediaitem.py 2012-06-22 14:14:53 +0000 +++ openlp/plugins/images/lib/mediaitem.py 2012-07-01 19:42:22 +0000 @@ -229,8 +229,7 @@ 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: === modified file 'openlp/plugins/presentations/lib/messagelistener.py' --- openlp/plugins/presentations/lib/messagelistener.py 2012-06-22 14:14:53 +0000 +++ openlp/plugins/presentations/lib/messagelistener.py 2012-07-01 19:42:22 +0000 @@ -278,8 +278,7 @@ 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)
_______________________________________________ Mailing list: https://launchpad.net/~openlp-core Post to : openlp-core@lists.launchpad.net Unsubscribe : https://launchpad.net/~openlp-core More help : https://help.launchpad.net/ListHelp