--- a/src/pyams_file/thumbnail.py Tue Feb 05 09:38:25 2019 +0100
+++ b/src/pyams_file/thumbnail.py Tue Feb 05 09:39:36 2019 +0100
@@ -12,6 +12,7 @@
__docformat__ = 'restructuredtext'
+import logging
import re
import transaction
@@ -20,12 +21,13 @@
from pyramid.events import subscriber
from pyramid.threadlocal import get_current_registry
from zope.interface import Interface, alsoProvides
-from zope.lifecycleevent import ObjectAddedEvent, ObjectCreatedEvent, ObjectRemovedEvent
+from zope.lifecycleevent import IObjectRemovedEvent, ObjectAddedEvent, ObjectCreatedEvent, ObjectRemovedEvent
from zope.location import locate
from zope.traversing.interfaces import ITraversable
from pyams_file.file import FileFactory
-from pyams_file.interfaces import IFileModifiedEvent, IImage, IThumbnailFile, IThumbnailer, IThumbnails, IWatermarker
+from pyams_file.interfaces import IFileModifiedEvent, IImage, IMediaFile, IThumbnailFile, IThumbnailer, IThumbnails, \
+ IWatermarker
from pyams_file.zmi.image import render_image
from pyams_utils.adapter import ContextAdapter, ContextRequestViewAdapter, adapter_config, get_annotation_adapter
from pyams_utils.interfaces.tales import ITALESExtension
@@ -33,6 +35,9 @@
from pyams_utils.request import check_request
+logger = logging.getLogger('PyAMS (file)')
+
+
THUMBNAIL_ANNOTATIONS_KEY = 'pyams_file.image.thumbnails'
THUMBNAIL_GEOMETRY_KEY = 'pyams_file.image.geometry'
@@ -123,32 +128,38 @@
return None, None
def get_selection(self, selection_name, format=None):
+ logger.debug(">>> Requested thumbnail selection: {}".format(selection_name))
if selection_name in self.thumbnails:
return self.thumbnails[selection_name]
geometry = self.get_geometry(selection_name)
- registry = get_current_registry()
- thumbnailer = registry.queryAdapter(self.image, IThumbnailer, name=selection_name)
- if thumbnailer is not None:
- selection = thumbnailer.create_thumbnail(geometry, format)
- if selection is not None:
- if isinstance(selection, tuple):
- selection, format = selection
- else:
- format = 'jpeg'
- selection = FileFactory(selection)
- alsoProvides(selection, IThumbnailFile)
- registry.notify(ObjectCreatedEvent(selection))
- self.thumbnails[selection_name] = selection
- selection_size = selection.get_image_size()
- locate(selection, self.image,
- '++thumb++{0}:{1}x{2}.{3}'.format(selection_name,
- selection_size[0],
- selection_size[1],
- format))
- registry.notify(ObjectAddedEvent(selection))
- return selection
+ if geometry == IThumbnailer(self.image).get_default_geometry():
+ return self.image
+ else:
+ registry = get_current_registry()
+ thumbnailer = registry.queryAdapter(self.image, IThumbnailer, name=selection_name)
+ if thumbnailer is not None:
+ selection = thumbnailer.create_thumbnail(geometry, format)
+ if selection is not None:
+ if isinstance(selection, tuple):
+ selection, format = selection
+ else:
+ format = 'jpeg'
+ selection = FileFactory(selection)
+ alsoProvides(selection, IThumbnailFile)
+ registry.notify(ObjectCreatedEvent(selection))
+ self.thumbnails[selection_name] = selection
+ selection_size = selection.get_image_size()
+ locate(selection, self.image,
+ '++thumb++{0}:{1}x{2}.{3}'.format(selection_name,
+ selection_size[0],
+ selection_size[1],
+ format))
+ logger.debug(" > Generated thumbnail selection: {}".format(selection.__name__))
+ registry.notify(ObjectAddedEvent(selection))
+ return selection
def get_thumbnail(self, thumbnail_name, format=None, watermark=None):
+ logger.debug(">>> Requested thumbnail: {}".format(thumbnail_name))
# check for existing thumbnail
if thumbnail_name in self.thumbnails:
return self.thumbnails[thumbnail_name]
@@ -204,25 +215,30 @@
thumbnail_size[0],
thumbnail_size[1],
format))
+ logger.debug(" < Generated thumbnail: {}".format(thumbnail_image.__name__))
registry.notify(ObjectAddedEvent(thumbnail_image))
return thumbnail_image
def delete_thumbnail(self, thumbnail_name):
if thumbnail_name in self.thumbnails:
thumbnail_image = self.thumbnails[thumbnail_name]
- registry = check_request().registry
+ registry = get_current_registry()
registry.notify(ObjectRemovedEvent(thumbnail_image))
del self.thumbnails[thumbnail_name]
+ logger.debug(">>> Removed thumbnail: {}".format(thumbnail_name))
def clear_thumbnails(self):
[self.delete_thumbnail(thumbnail_name) for thumbnail_name in list(self.thumbnails.keys())]
-@subscriber(IFileModifiedEvent, context_selector=IImage)
-def handle_modified_file(event):
- thumbnail = IThumbnails(event.object)
- thumbnail.clear_geometries()
- thumbnail.clear_thumbnails()
+@subscriber(IFileModifiedEvent, context_selector=IMediaFile)
+@subscriber(IObjectRemovedEvent, context_selector=IMediaFile)
+def handle_modified_image(event):
+ """Clear thumbnails when an image is updated or removed"""
+ thumbnails = IThumbnails(event.object, None)
+ if thumbnails is not None:
+ thumbnails.clear_geometries()
+ thumbnails.clear_thumbnails()
@adapter_config(name='thumb', context=IImage, provides=ITraversable)
@@ -261,7 +277,7 @@
@adapter_config(name='thumbnail', context=(Interface, Interface, Interface), provides=ITALESExtension)
class ThumbnailExtension(ContextRequestViewAdapter):
- """extension:thumbnail(image, width, height) TALES extension
+ """extension:thumbnail(image, width, height, css_class, img_class) TALES extension
This TALES extension doesn't return an adapter but HTML code matching given image and dimensions.
If image is a classic image, an "img" tag with source to thumbnail of required size is returned.