Skip to content

Commit

Permalink
override scaling view to keep crops on metadata change
Browse files Browse the repository at this point in the history
  • Loading branch information
tomgross committed Feb 26, 2014
1 parent 24c8e3a commit ab47688
Show file tree
Hide file tree
Showing 9 changed files with 62 additions and 10 deletions.
3 changes: 3 additions & 0 deletions buildout.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ test-eggs +=

versions = versions

[versions]
Pillow = 2.3.0

[omelette]
recipe = collective.recipe.omelette
eggs = ${instance:eggs} ${buildout:test-eggs}
Expand Down
9 changes: 9 additions & 0 deletions src/plone/app/imagecropping/browser/configure.zcml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
xmlns="http://namespaces.zope.org/zope"
xmlns:browser="http://namespaces.zope.org/browser"
xmlns:i18n="http://xml.zope.org/namespaces/i18n"
xmlns:zcml="http://namespaces.zope.org/zcml"
i18n_domain="plone">

<include package="Products.CMFCore" file="permissions.zcml" />
Expand Down Expand Up @@ -43,4 +44,12 @@
permission="cmf.ModifyPortalContent"
/>

<browser:page
zcml:condition="installed Products.ATContentTypes"
for="Products.ATContentTypes.interfaces.IATImage"
name="images"
class=".scaling.ImageScaling"
allowed_interface="plone.app.imaging.interfaces.IImageScaling"
permission="zope2.View" />

</configure>
3 changes: 1 addition & 2 deletions src/plone/app/imagecropping/browser/crop.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ def _crop(self, fieldname, scale, box, interface=None):
"""switch between dexterity and Archetypes
"""
croputils = IImageCroppingUtils(self.context)
field = croputils.get_image_field(fieldname)
data = croputils.get_image_data(fieldname)

original_file = StringIO(data)
Expand All @@ -38,7 +37,7 @@ def _crop(self, fieldname, scale, box, interface=None):
cropped_image_file.seek(0)

croputils.save_cropped(
fieldname, field, scale, cropped_image_file, interface)
fieldname, scale, cropped_image_file, interface)

# store crop information in annotations
self._store(fieldname, scale, box)
Expand Down
4 changes: 0 additions & 4 deletions src/plone/app/imagecropping/browser/editor.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,10 +154,6 @@ def _crop(self):
scale=scale_name,
box=(x1, y1, x2, y2),
interface=self.interface)
# Avoid browser cache
# an empty call of setModificationDate uses current timestamp
self.context.setModificationDate()
self.context.reindexObject()

def __call__(self):
form = self.request.form
Expand Down
17 changes: 17 additions & 0 deletions src/plone/app/imagecropping/browser/scaling.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from zope.annotation.interfaces import IAnnotations

from plone.app.imagecropping import PAI_STORAGE_KEY
from plone.app.imaging.scaling import ImageScaling as BaseImageScaling


class ImageScaling(BaseImageScaling):

def modified(self):
cropped = IAnnotations(self.context).get(PAI_STORAGE_KEY)
if not cropped:
return super(ImageScaling, self).modified()
else:
return 1


# XXX need this for plone.namedfile and NEWSItem too
2 changes: 1 addition & 1 deletion src/plone/app/imagecropping/interfaces.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ def get_image_size(fieldname, interface):
(100, 200)
"""

def save_cropped(fieldname, field, scale, image_file, interface=None):
def save_cropped(fieldname, scale, image_file, interface=None):
""" Save the cropped iamge under the name of the selected scale in
plone.scale.storage.AnnotationStorage, so that it is available
in plone.app.imaging @@images view
Expand Down
21 changes: 21 additions & 0 deletions src/plone/app/imagecropping/tests/test_cropping.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,3 +117,24 @@ def test_image_formats(self):
# XXX: fixme
# self.assertEqual(open(croppedData).format, 'JPEG',
# "cropped scale does not have same format as the original")

def test_modify_context(self):
""" See https://github.com/collective/plone.app.imagecropping/issues/21
"""

view = self.img.restrictedTraverse('@@crop-image')
traverse = self.portal.REQUEST.traverseName
scales = traverse(self.img, '@@images')
unscaled_thumb = scales.scale('image', 'thumb')

# store cropped version for thumb and check if the result
# is a square now
view._crop(fieldname='image', scale='thumb', box=(14, 14, 218, 218))
thumb = scales.scale('image', 'thumb')
self.failIfEqual(thumb.data, unscaled_thumb.data)

self.img.setTitle('A new title')
self.img.reindexObject()

thumb2 = scales.scale('image', 'thumb')
self.assertEqual(thumb.data, thumb2.data)
3 changes: 2 additions & 1 deletion src/plone/app/imagecropping/tests/test_editor.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ def test_singleimage_editorview(self):

def test_editview_crop(self):
request = self.layer['request']
request.form.update({'x1': 1.0, 'y1': 2.7, 'x2': 10.6, 'y2': 8.4})
request.form.update({'x1': 1.0, 'y1': 2.7, 'x2': 10.6, 'y2': 8.4,
'scalename': 'mini'})
cropview = self.img.restrictedTraverse('@@croppingeditor')
cropview._crop()

Expand Down
10 changes: 8 additions & 2 deletions src/plone/app/imagecropping/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,10 @@ def get_image_size(self, fieldname, interface=None):
return image_size

def save_cropped(
self, fieldname, field, scale, image_file, interface=None):
self, fieldname, scale, image_file, interface=None):
""" see interface
"""
field = self.get_image_field(fieldname)
handler = IImageScaleHandler(field)
sizes = field.getAvailableSizes(self.context)
w, h = sizes[scale]
Expand All @@ -104,6 +105,10 @@ def crop_factory(fieldname, direction='keep', **parameters):
result.close()
return blob, image_format, dimensions

# Avoid browser cache
# calling reindexObject updates the modified metadate too
self.context.reindexObject()

# call storage with actual time in milliseconds
# this always invalidates old scales
storage = AnnotationStorage(self.context, self.now_millis)
Expand Down Expand Up @@ -162,7 +167,7 @@ def get_image_size(self, fieldname, interface=None):
return image_size

def save_cropped(
self, fieldname, field, scale, image_file, interface=None):
self, fieldname, scale, image_file, interface=None):
""" see interface
"""
sizes = getAllowedSizes()
Expand All @@ -173,6 +178,7 @@ def crop_factory(fieldname, **parameters):
if result is not None:
data, format, dimensions = result
mimetype = 'image/%s' % format.lower()
field = self.get_image_field(fieldname)
value = field.__class__(
data,
contentType=mimetype,
Expand Down

0 comments on commit ab47688

Please sign in to comment.