# HG changeset patch # User Thierry Florac # Date 1505129446 -7200 # Node ID 83ef19bfaa635f5038847c2e0eafc3c8d71efff3 # Parent 3b2cb5046d8666e4e5191cfcf227f61f066c51ae Added view to display all images thumbnails diff -r 3b2cb5046d86 -r 83ef19bfaa63 src/pyams_file/zmi/image.py --- a/src/pyams_file/zmi/image.py Mon Sep 11 13:28:59 2017 +0200 +++ b/src/pyams_file/zmi/image.py Mon Sep 11 13:30:46 2017 +0200 @@ -14,9 +14,13 @@ # import standard library +import random +import sys +from collections import OrderedDict # import interfaces -from pyams_file.interfaces import IImage, IThumbnail, IResponsiveImage, IImageWidget, IFileModifierForm +from pyams_file.interfaces import IImage, IThumbnail, IResponsiveImage, IImageWidget, IFileModifierForm, IThumbnailer, \ + IFileInfo, IThumbnailForm from pyams_form.interfaces.form import IWidgetsPrefixViewletsManager, IFormHelp from pyams_skin.interfaces.viewlet import IContextActions from pyams_skin.layer import IPyAMSLayer @@ -26,12 +30,14 @@ # import packages from pyams_file.image import ThumbnailGeometry from pyams_file.zmi import FileModifierAction -from pyams_form.form import AJAXEditForm +from pyams_form.form import AJAXEditForm, DialogDisplayForm from pyams_form.help import FormHelp from pyams_form.schema import CloseButton from pyams_pagelet.pagelet import pagelet_config +from pyams_skin.viewlet.toolbar import ToolbarActionItem from pyams_template.template import template_config from pyams_utils.adapter import adapter_config +from pyams_utils.url import absolute_url from pyams_viewlet.viewlet import viewlet_config, Viewlet from pyams_zmi.form import AdminDialogEditForm from pyramid.view import view_config @@ -44,11 +50,494 @@ # +# Image crop +# + +@viewlet_config(name='image.crop.action', context=IImage, layer=IPyAMSLayer, view=IImageWidget, + manager=IContextActions, weight=21) +class ImageCropAction(FileModifierAction): + """Image crop action""" + + label = _("Crop image...") + label_css_class = 'fa fa-fw-md fa-crop' + + url = 'crop.html' + modal_target = True + + +class ICropFormButtons(Interface): + """Image crop form buttons""" + + close = CloseButton(name='close', title=_("Close")) + crop = button.Button(name='crop', title=_("Crop")) + + +@pagelet_config(name='crop.html', context=IImage, layer=IPyAMSLayer, permission=VIEW_PERMISSION) +@implementer(IFileModifierForm) +class ImageCropForm(AdminDialogEditForm): + """Image crop form""" + + legend = _("Crop image") + icon_css_class = 'fa fa-fw fa-crop' + dialog_class = 'modal-large' + + fields = field.Fields(Interface) + buttons = button.Buttons(ICropFormButtons) + ajax_handler = 'crop.json' + edit_permission = None + + @property + def title(self): + return self.context.title or self.context.filename + + def updateActions(self): + super(ImageCropForm, self).updateActions() + if 'crop' in self.actions: + self.actions['crop'].addClass('btn-primary') + + +@view_config(name='crop.json', context=IImage, request_type=IPyAMSLayer, + permission=VIEW_PERMISSION, renderer='json', xhr=True) +class ImageCropAJAXForm(AJAXEditForm, ImageCropForm): + """Image crop form, AJAX renderer""" + + def update_content(self, content, data): + image_size = self.context.get_image_size() + x1 = int(self.request.params.get('selection.x1', 0)) + y1 = int(self.request.params.get('selection.y1', 0)) + x2 = int(self.request.params.get('selection.x2', image_size[0])) + y2 = int(self.request.params.get('selection.y2', image_size[1])) + self.context.crop(x1, y1, x2, y2) + + def get_ajax_output(self, changes): + return {'status': 'reload', + 'smallbox': self.request.localizer.translate(self.successMessage), + 'smallbox_status': 'success'} + + +@viewlet_config(name='crop.widgets-prefix', context=IImage, layer=IAdminLayer, view=ImageCropForm, + manager=IWidgetsPrefixViewletsManager) +@template_config(template='templates/image-crop.pt') +class ImageCropViewletsPrefix(Viewlet): + """Image crop viewlets prefix""" + + +@adapter_config(context=(IImage, IAdminLayer, ImageCropForm), provides=IFormHelp) +class ImageCropFormHelpAdapter(FormHelp): + """Image crop form help adapter""" + + message = _("""You can use this form to crop an image. + +**WARNING**: cropping an image will reset all selected thumbnails and adaptive images!!""") + message_format = 'rest' + + +# +# Image square thumbnail selection +# + +@adapter_config(context=(IImage, IAdminLayer, IThumbnailForm), provides=IFormHelp) +class ThumbnailFormHelpAdapter(FormHelp): + """Thumbnail form help adapter""" + + message = _("""You can use this form to make a selection on an image.""") + message_format = 'rest' + + +class IThumbnailFormButtons(Interface): + """Image crop form buttons""" + + close = CloseButton(name='close', title=_("Close")) + crop = button.Button(name='crop', title=_("Select thumbnail")) + + +@viewlet_config(name='image.thumb.square.action', context=IImage, layer=IPyAMSLayer, view=IImageWidget, + manager=IContextActions, weight=60) +class ImageSquareThumbnailAction(FileModifierAction): + """Square thumbnail image selection""" + + _label = _("Select square thumbnail...") + + @property + def label(self): + return '
{label}
'.format(label=self.request.localizer.translate(self._label), + url=absolute_url(self.context, self.request)) + + label_css_class = 'fa fa-fw-md fa-instagram' + + url = 'square-thumbnail.html' + modal_target = True + + +@pagelet_config(name='square-thumbnail.html', context=IImage, layer=IPyAMSLayer, permission=VIEW_PERMISSION) +@implementer(IThumbnailForm) +class ImageSquareThumbnailEditForm(AdminDialogEditForm): + """Image square thumbnail edit form""" + + legend = _("Select square thumbnail") + icon_css_class = 'fa fa-fw fa-instagram' + dialog_class = 'modal-large' + + fields = field.Fields(Interface) + buttons = button.Buttons(IThumbnailFormButtons) + ajax_handler = 'square-thumbnail.json' + edit_permission = None + + @property + def title(self): + return self.context.title or self.context.filename + + def updateActions(self): + super(ImageSquareThumbnailEditForm, self).updateActions() + if 'crop' in self.actions: + self.actions['crop'].addClass('btn-primary') + + +@view_config(name='square-thumbnail.json', context=IImage, request_type=IPyAMSLayer, + permission=VIEW_PERMISSION, renderer='json', xhr=True) +class ImageSquareThumbnailAJAXEditForm(AJAXEditForm, ImageSquareThumbnailEditForm): + """Image square thumbnail edit form, AJAX renderer""" + + def update_content(self, content, data): + geometry = ThumbnailGeometry() + geometry.x1 = int(self.request.params.get('selection.x1')) + geometry.y1 = int(self.request.params.get('selection.y1')) + geometry.x2 = int(self.request.params.get('selection.x2')) + geometry.y2 = int(self.request.params.get('selection.y2')) + IThumbnail(self.context).set_geometry('square', geometry) + + def get_ajax_output(self, changes): + return {'status': 'success', + 'smallbox': self.request.localizer.translate(self.successMessage), + 'smallbox_status': 'success'} + + +@viewlet_config(name='square-thumbnail.widgets-prefix', context=IImage, layer=IAdminLayer, + view=ImageSquareThumbnailEditForm, manager=IWidgetsPrefixViewletsManager) +@template_config(template='templates/image-square-thumbnail.pt') +class ImageSquareThumbnailViewletsPrefix(Viewlet): + """Image square thumbnail viewlets prefix""" + + +@adapter_config(context=(IImage, IAdminLayer, ImageSquareThumbnailEditForm), provides=IFormHelp) +class ImageSquareThumbnailEditFormHelpAdapter(FormHelp): + """Square image thumbnail edit form help adapter""" + + message = _("""You can use this form to select a square thumbnail of this image. + +**WARNING**: cropping or resizing an image will reset all selected thumbnails and adaptive images!!""") + message_format = 'rest' + + +# +# Image panoramic thumbnail selection +# + +@viewlet_config(name='image.thumb.pano.action', context=IImage, layer=IAdminLayer, view=IImageWidget, + manager=IContextActions, weight=65) +class ImagePanoThumbnailAction(FileModifierAction): + """Panoramic thumbnail image selection""" + + _label = _("Select panoramic thumbnail...") + + @property + def label(self): + return '
{label}
'.format(label=self.request.localizer.translate(self._label), + url=absolute_url(self.context, self.request)) + + label_css_class = 'fa fa-fw-md fa-youtube-play' + + url = 'pano-thumbnail.html' + modal_target = True + + +@pagelet_config(name='pano-thumbnail.html', context=IImage, layer=IPyAMSLayer, permission=VIEW_PERMISSION) +@implementer(IThumbnailForm) +class ImagePanoThumbnailEditForm(AdminDialogEditForm): + """Image panoramic thumbnail edit form""" + + legend = _("Select panoramic thumbnail") + icon_css_class = 'fa fa-fw fa-youtube-play' + dialog_class = 'modal-large' + + fields = field.Fields(Interface) + buttons = button.Buttons(IThumbnailFormButtons) + ajax_handler = 'pano-thumbnail.json' + edit_permission = None + + @property + def title(self): + return self.context.title or self.context.filename + + def updateActions(self): + super(ImagePanoThumbnailEditForm, self).updateActions() + if 'crop' in self.actions: + self.actions['crop'].addClass('btn-primary') + + +@view_config(name='pano-thumbnail.json', context=IImage, request_type=IPyAMSLayer, + permission=VIEW_PERMISSION, renderer='json', xhr=True) +class ImagePanoThumbnailAJAXEditForm(AJAXEditForm, ImagePanoThumbnailEditForm): + """Image panoramic thumbnail edit form, AJAX renderer""" + + def update_content(self, content, data): + geometry = ThumbnailGeometry() + geometry.x1 = int(self.request.params.get('selection.x1')) + geometry.y1 = int(self.request.params.get('selection.y1')) + geometry.x2 = int(self.request.params.get('selection.x2')) + geometry.y2 = int(self.request.params.get('selection.y2')) + IThumbnail(self.context).set_geometry('pano', geometry) + + def get_ajax_output(self, changes): + return {'status': 'success', + 'smallbox': self.request.localizer.translate(self.successMessage), + 'smallbox_status': 'success'} + + +@viewlet_config(name='pano-thumbnail.widgets-prefix', context=IImage, layer=IAdminLayer, + view=ImagePanoThumbnailEditForm, manager=IWidgetsPrefixViewletsManager) +@template_config(template='templates/image-pano-thumbnail.pt') +class ImagePanoThumbnailViewletsPrefix(Viewlet): + """Image panoramic thumbnail viewlets prefix""" + + +@adapter_config(context=(IImage, IAdminLayer, ImagePanoThumbnailEditForm), provides=IFormHelp) +class ImagePanoThumbnailEditFormHelpAdapter(FormHelp): + """Panoramic image thumbnail edit form help adapter""" + + message = _("""You can use this form to select a panoramic thumbnail of this image. + +**WARNING**: cropping or resizing an image will reset all selected thumbnails and adaptive images!!""") + message_format = 'rest' + + +# +# Image responsive selections +# + +class IResponsiveImageSelectionFormButtons(Interface): + """Responsive image selection form buttons""" + + close = CloseButton(name='close', title=_("Close")) + select = button.Button(name='select', title=_("Select thumbnail")) + + +@implementer(IThumbnailForm) +class ResponsiveImageSelectionForm(AdminDialogEditForm): + """Base responsive image selection edit form""" + + dialog_class = 'modal-large' + + fields = field.Fields(Interface) + buttons = button.Buttons(IResponsiveImageSelectionFormButtons) + edit_permission = None + + @property + def title(self): + return self.context.title or self.context.filename + + def updateActions(self): + super(ResponsiveImageSelectionForm, self).updateActions() + if 'select' in self.actions: + self.actions['select'].addClass('btn-primary') + + +class ResponsiveImageSelectionAJAXForm(AJAXEditForm): + """Base responsive image selection edit form, JSON renderer""" + + def update_content(self, content, data): + geometry = ThumbnailGeometry() + geometry.x1 = int(self.request.params.get('selection.x1')) + geometry.y1 = int(self.request.params.get('selection.y1')) + geometry.x2 = int(self.request.params.get('selection.x2')) + geometry.y2 = int(self.request.params.get('selection.y2')) + IThumbnail(self.context).set_geometry(self.selection_size, geometry) + + def get_ajax_output(self, changes): + return {'status': 'success', + 'smallbox': self.request.localizer.translate(self.successMessage), + 'smallbox_status': 'success'} + + +@viewlet_config(name='responsive-image.selection.widgets-prefix', context=IResponsiveImage, layer=IAdminLayer, + view=ResponsiveImageSelectionForm, manager=IWidgetsPrefixViewletsManager) +@template_config(template='templates/image-selection.pt') +class ResponsiveImageSelectionViewletsPrefix(Viewlet): + """Responsive image selection viewlets prefix""" + + +# +# Extra-small devices selection +# + +@viewlet_config(name='responsive-image.selection.xs.action', context=IResponsiveImage, layer=IAdminLayer, + view=IImageWidget, manager=IContextActions, weight=41) +class ResponsiveImageXsSelectionAction(FileModifierAction): + """Responsive image XS selection""" + + _label = _("Select responsive XS image...") + + @property + def label(self): + return '
{label}
'.format(label=self.request.localizer.translate(self._label), + url=absolute_url(self.context, self.request)) + + label_css_class = 'fa fa-fw-md fa-mobile' + + url = 'selection-xs.html' + modal_target = True + + +@pagelet_config(name='selection-xs.html', context=IResponsiveImage, layer=IPyAMSLayer, + permission=VIEW_PERMISSION) +class ResponsiveImageXsSelectionForm(ResponsiveImageSelectionForm): + """Responsive image XS selection edit form""" + + legend = _("Select image for extra-small (XS) devices") + icon_css_class = 'fa fa-fw fa-mobile' + + selection_size = 'xs' + ajax_handler = 'selection-xs.json' + + +@view_config(name='selection-xs.json', context=IResponsiveImage, request_type=IPyAMSLayer, + permission=VIEW_PERMISSION, renderer='json', xhr=True) +class ResponsiveImageXsSelectionAJAXEditForm(ResponsiveImageSelectionAJAXForm, ResponsiveImageXsSelectionForm): + """Responsive image XS selection edit form, JSON renderer""" + + +# +# Small devices selection +# + +@viewlet_config(name='responsive-image.selection.sm.action', context=IResponsiveImage, layer=IAdminLayer, + view=IImageWidget, manager=IContextActions, weight=42) +class ResponsiveImageSmSelectionAction(FileModifierAction): + """Responsive image SM selection""" + + _label = _("Select responsive SM image...") + + @property + def label(self): + return '
{label}
'.format(label=self.request.localizer.translate(self._label), + url=absolute_url(self.context, self.request)) + + label_css_class = 'fa fa-fw-md fa-tablet' + + url = 'selection-sm.html' + modal_target = True + + +@pagelet_config(name='selection-sm.html', context=IResponsiveImage, layer=IPyAMSLayer, + permission=VIEW_PERMISSION) +class ResponsiveImageSmSelectionForm(ResponsiveImageSelectionForm): + """Responsive image SM selection edit form""" + + legend = _("Select image for small (SM) devices") + icon_css_class = 'fa fa-fw fa-tablet' + + selection_size = 'sm' + ajax_handler = 'selection-sm.json' + + +@view_config(name='selection-sm.json', context=IResponsiveImage, request_type=IPyAMSLayer, + permission=VIEW_PERMISSION, renderer='json', xhr=True) +class ResponsiveImageSmSelectionAJAXEditForm(ResponsiveImageSelectionAJAXForm, ResponsiveImageSmSelectionForm): + """Responsive image SM selection edit form, JSON renderer""" + + +# +# Medium devices selection +# + +@viewlet_config(name='responsive-image.selection.md.action', context=IResponsiveImage, layer=IAdminLayer, + view=IImageWidget, manager=IContextActions, weight=43) +class ResponsiveImageMdSelectionAction(FileModifierAction): + """Responsive image MD selection""" + + _label = _("Select responsive MD image...") + + @property + def label(self): + return '
{label}
'.format(label=self.request.localizer.translate(self._label), + url=absolute_url(self.context, self.request)) + + label_css_class = 'fa fa-fw-md fa-desktop' + + url = 'selection-md.html' + modal_target = True + + +@pagelet_config(name='selection-md.html', context=IResponsiveImage, layer=IPyAMSLayer, + permission=VIEW_PERMISSION) +class ResponsiveImageMdSelectionForm(ResponsiveImageSelectionForm): + """Responsive image MD selection edit form""" + + legend = _("Select image for medium (MD) devices") + icon_css_class = 'fa fa-fw fa-desktop' + + selection_size = 'md' + ajax_handler = 'selection-md.json' + + +@view_config(name='selection-md.json', context=IResponsiveImage, request_type=IPyAMSLayer, + permission=VIEW_PERMISSION, renderer='json', xhr=True) +class ResponsiveImageMdSelectionAJAXEditForm(ResponsiveImageSelectionAJAXForm, ResponsiveImageMdSelectionForm): + """Responsive image MD selection edit form, JSON renderer""" + + +# +# Large devices selection +# + +@viewlet_config(name='responsive-image.selection.lg.action', context=IResponsiveImage, layer=IAdminLayer, + view=IImageWidget, manager=IContextActions, weight=44) +class ResponsiveImageLgSelectionAction(FileModifierAction): + """Responsive image LG selection""" + + _label = _("Select responsive LG image...") + + @property + def label(self): + return '
{label}
'.format(label=self.request.localizer.translate(self._label), + url=absolute_url(self.context, self.request)) + + label_css_class = 'fa fa-fw-md fa-television' + + url = 'selection-lg.html' + modal_target = True + + +@pagelet_config(name='selection-lg.html', context=IResponsiveImage, layer=IPyAMSLayer, + permission=VIEW_PERMISSION) +class ResponsiveImageLgSelectionForm(ResponsiveImageSelectionForm): + """Responsive image LG selection edit form""" + + legend = _("Select image for large (LG) devices") + icon_css_class = 'fa fa-fw fa-television' + + selection_size = 'lg' + ajax_handler = 'selection-lg.json' + + +@view_config(name='selection-lg.json', context=IResponsiveImage, request_type=IPyAMSLayer, + permission=VIEW_PERMISSION, renderer='json', xhr=True) +class ResponsiveImageLgSelectionAJAXEditForm(ResponsiveImageSelectionAJAXForm, ResponsiveImageLgSelectionForm): + """Responsive image LG selection edit form, JSON renderer""" + + +# # Image resize # @viewlet_config(name='image.resize.action', context=IImage, layer=IPyAMSLayer, view=IImageWidget, - manager=IContextActions, weight=20) + manager=IContextActions, weight=80) class ImageResizeAction(FileModifierAction): """Image resize action""" @@ -146,413 +635,55 @@ # -# Image crop +# See all thumbnails!! # -@viewlet_config(name='image.crop.action', context=IImage, layer=IPyAMSLayer, view=IImageWidget, - manager=IContextActions, weight=21) -class ImageCropAction(FileModifierAction): - """Image crop action""" +@viewlet_config(name='display-all-thumbnails.action', context=IImage, layer=IAdminLayer, + view=IImageWidget, manager=IContextActions, weight=90) +class ImageThumbnailsDisplayAction(ToolbarActionItem): + """Image thumbnails display action""" - label = _("Crop image...") - label_css_class = 'fa fa-fw-md fa-crop' + label = _("Display all thumbnails") + label_css_class = 'fa fa-fw fa-th-large text-primary' + hint_gravity = 'nw' - url = 'crop.html' + url = 'display-all-thumbnails.html' modal_target = True -class ICropFormButtons(Interface): - """Image crop form buttons""" - - close = CloseButton(name='close', title=_("Close")) - crop = button.Button(name='crop', title=_("Crop")) - - -@pagelet_config(name='crop.html', context=IImage, layer=IPyAMSLayer, permission=VIEW_PERMISSION) -@implementer(IFileModifierForm) -class ImageCropForm(AdminDialogEditForm): - """Image crop form""" - - legend = _("Crop image") - icon_css_class = 'fa fa-fw fa-crop' - dialog_class = 'modal-large' - - fields = field.Fields(Interface) - buttons = button.Buttons(ICropFormButtons) - ajax_handler = 'crop.json' - edit_permission = None - - @property - def title(self): - return self.context.title or self.context.filename - - def updateActions(self): - super(ImageCropForm, self).updateActions() - if 'crop' in self.actions: - self.actions['crop'].addClass('btn-primary') - - -@view_config(name='crop.json', context=IImage, request_type=IPyAMSLayer, - permission=VIEW_PERMISSION, renderer='json', xhr=True) -class ImageCropAJAXForm(AJAXEditForm, ImageCropForm): - """Image crop form, AJAX renderer""" - - def update_content(self, content, data): - image_size = self.context.get_image_size() - x1 = int(self.request.params.get('selection.x1', 0)) - y1 = int(self.request.params.get('selection.y1', 0)) - x2 = int(self.request.params.get('selection.x2', image_size[0])) - y2 = int(self.request.params.get('selection.y2', image_size[1])) - self.context.crop(x1, y1, x2, y2) - - def get_ajax_output(self, changes): - return {'status': 'reload', - 'smallbox': self.request.localizer.translate(self.successMessage), - 'smallbox_status': 'success'} - - -@viewlet_config(name='crop.widgets-prefix', context=IImage, layer=IAdminLayer, view=ImageCropForm, - manager=IWidgetsPrefixViewletsManager) -@template_config(template='templates/image-crop.pt') -class ImageCropViewletsPrefix(Viewlet): - """Image crop viewlets prefix""" - - -@adapter_config(context=(IImage, IAdminLayer, ImageCropForm), provides=IFormHelp) -class ImageCropFormHelpAdapter(FormHelp): - """Image crop form help adapter""" - - message = _("""You can use this form to crop an image. - -**WARNING**: cropping an image will reset all selected thumbnails and adaptive images!!""") - message_format = 'rest' - - -# -# Image square thumbnail selection -# - -class IThumbnailFormButtons(Interface): - """Image crop form buttons""" - - close = CloseButton(name='close', title=_("Close")) - crop = button.Button(name='crop', title=_("Select thumbnail")) - - -@viewlet_config(name='image.thumb.square.action', context=IImage, layer=IPyAMSLayer, view=IImageWidget, - manager=IContextActions, weight=31) -class ImageSquareThumbnailAction(FileModifierAction): - """Square thumbnail image selection""" - - label = _("Select square thumbnail...") - label_css_class = 'fa fa-fw-md fa-instagram' - - url = 'square-thumbnail.html' - modal_target = True - - -@pagelet_config(name='square-thumbnail.html', context=IImage, layer=IPyAMSLayer, permission=VIEW_PERMISSION) -@implementer(IFileModifierForm) -class ImageSquareThumbnailEditForm(AdminDialogEditForm): - """Image square thumbnail edit form""" - - legend = _("Select square thumbnail") - icon_css_class = 'fa fa-fw fa-instagram' - dialog_class = 'modal-large' - - fields = field.Fields(Interface) - buttons = button.Buttons(IThumbnailFormButtons) - ajax_handler = 'square-thumbnail.json' - edit_permission = None - - @property - def title(self): - return self.context.title or self.context.filename - - def updateActions(self): - super(ImageSquareThumbnailEditForm, self).updateActions() - if 'crop' in self.actions: - self.actions['crop'].addClass('btn-primary') - - -@view_config(name='square-thumbnail.json', context=IImage, request_type=IPyAMSLayer, - permission=VIEW_PERMISSION, renderer='json', xhr=True) -class ImageSquareThumbnailAJAXEditForm(AJAXEditForm, ImageSquareThumbnailEditForm): - """Image square thumbnail edit form, AJAX renderer""" - - def update_content(self, content, data): - geometry = ThumbnailGeometry() - geometry.x1 = int(self.request.params.get('selection.x1')) - geometry.y1 = int(self.request.params.get('selection.y1')) - geometry.x2 = int(self.request.params.get('selection.x2')) - geometry.y2 = int(self.request.params.get('selection.y2')) - IThumbnail(self.context).set_geometry('square', geometry) - - def get_ajax_output(self, changes): - return {'status': 'success', - 'smallbox': self.request.localizer.translate(self.successMessage), - 'smallbox_status': 'success'} - - -@viewlet_config(name='square-thumbnail.widgets-prefix', context=IImage, layer=IAdminLayer, - view=ImageSquareThumbnailEditForm, manager=IWidgetsPrefixViewletsManager) -@template_config(template='templates/image-square-thumbnail.pt') -class ImageSquareThumbnailViewletsPrefix(Viewlet): - """Image square thumbnail viewlets prefix""" - - -# -# Image panoramic thumbnail selection -# - -@viewlet_config(name='image.thumb.pano.action', context=IImage, layer=IAdminLayer, view=IImageWidget, - manager=IContextActions, weight=32) -class ImagePanoThumbnailAction(FileModifierAction): - """Panoramic thumbnail image selection""" - - label = _("Select panoramic thumbnail...") - label_css_class = 'fa fa-fw-md fa-youtube-play' - - url = 'pano-thumbnail.html' - modal_target = True - - -@pagelet_config(name='pano-thumbnail.html', context=IImage, layer=IPyAMSLayer, permission=VIEW_PERMISSION) -@implementer(IFileModifierForm) -class ImagePanoThumbnailEditForm(AdminDialogEditForm): - """Image panoramic thumbnail edit form""" - - legend = _("Select panoramic thumbnail") - icon_css_class = 'fa fa-fw fa-youtube-play' - dialog_class = 'modal-large' - - fields = field.Fields(Interface) - buttons = button.Buttons(IThumbnailFormButtons) - ajax_handler = 'pano-thumbnail.json' - edit_permission = None +@pagelet_config(name='display-all-thumbnails.html', context=IImage, layer=IPyAMSLayer, permission=VIEW_PERMISSION) +class ImageThumbnailsDisplayForm(DialogDisplayForm): + """Image thumbnails display form""" @property def title(self): - return self.context.title or self.context.filename - - def updateActions(self): - super(ImagePanoThumbnailEditForm, self).updateActions() - if 'crop' in self.actions: - self.actions['crop'].addClass('btn-primary') - - -@view_config(name='pano-thumbnail.json', context=IImage, request_type=IPyAMSLayer, - permission=VIEW_PERMISSION, renderer='json', xhr=True) -class ImagePanoThumbnailAJAXEditForm(AJAXEditForm, ImagePanoThumbnailEditForm): - """Image panoramic thumbnail edit form, AJAX renderer""" - - def update_content(self, content, data): - geometry = ThumbnailGeometry() - geometry.x1 = int(self.request.params.get('selection.x1')) - geometry.y1 = int(self.request.params.get('selection.y1')) - geometry.x2 = int(self.request.params.get('selection.x2')) - geometry.y2 = int(self.request.params.get('selection.y2')) - IThumbnail(self.context).set_geometry('pano', geometry) + info = IFileInfo(self.context) + return info.title or info.filename - def get_ajax_output(self, changes): - return {'status': 'success', - 'smallbox': self.request.localizer.translate(self.successMessage), - 'smallbox_status': 'success'} - - -@viewlet_config(name='pano-thumbnail.widgets-prefix', context=IImage, layer=IAdminLayer, - view=ImagePanoThumbnailEditForm, manager=IWidgetsPrefixViewletsManager) -@template_config(template='templates/image-pano-thumbnail.pt') -class ImagePanoThumbnailViewletsPrefix(Viewlet): - """Image panoramic thumbnail viewlets prefix""" - - -# -# Image responsive selections -# - -class IResponsiveImageSelectionFormButtons(Interface): - """Responsive image selection form buttons""" - - close = CloseButton(name='close', title=_("Close")) - select = button.Button(name='select', title=_("Select image")) - - -@implementer(IFileModifierForm) -class ResponsiveImageSelectionForm(AdminDialogEditForm): - """Base responsive image selection edit form""" - + legend = _("Display all image thumbnails") + icon_css_class = 'fa fa-fw fa-th-large' dialog_class = 'modal-large' fields = field.Fields(Interface) - buttons = button.Buttons(IResponsiveImageSelectionFormButtons) - edit_permission = None - - @property - def title(self): - return self.context.title or self.context.filename - - def updateActions(self): - super(ResponsiveImageSelectionForm, self).updateActions() - if 'select' in self.actions: - self.actions['select'].addClass('btn-primary') - - -class ResponsiveImageSelectionAJAXForm(AJAXEditForm): - """Base responsive image selection edit form, JSON renderer""" - - def update_content(self, content, data): - geometry = ThumbnailGeometry() - geometry.x1 = int(self.request.params.get('selection.x1')) - geometry.y1 = int(self.request.params.get('selection.y1')) - geometry.x2 = int(self.request.params.get('selection.x2')) - geometry.y2 = int(self.request.params.get('selection.y2')) - IThumbnail(self.context).set_geometry(self.selection_size, geometry) - - def get_ajax_output(self, changes): - return {'status': 'success', - 'smallbox': self.request.localizer.translate(self.successMessage), - 'smallbox_status': 'success'} - - -@viewlet_config(name='responsive-image.selection.widgets-prefix', context=IResponsiveImage, layer=IAdminLayer, - view=ResponsiveImageSelectionForm, manager=IWidgetsPrefixViewletsManager) -@template_config(template='templates/image-selection.pt') -class ResponsiveImageSelectionViewletsPrefix(Viewlet): - """Responsive image selection viewlets prefix""" - - -# -# Extra-small devices selection -# - -@viewlet_config(name='responsive-image.selection.xs.action', context=IResponsiveImage, layer=IAdminLayer, - view=IImageWidget, manager=IContextActions, weight=41) -class ResponsiveImageXsSelectionAction(FileModifierAction): - """Responsive image XS selection""" - - label = _("Select responsive XS image...") - label_css_class = 'fa fa-fw-md fa-mobile' - - url = 'selection-xs.html' - modal_target = True - - -@pagelet_config(name='selection-xs.html', context=IResponsiveImage, layer=IPyAMSLayer, - permission=VIEW_PERMISSION) -class ResponsiveImageXsSelectionForm(ResponsiveImageSelectionForm): - """Responsive image XS selection edit form""" - - legend = _("Select image for extra-small (XS) devices") - icon_css_class = 'fa fa-fw fa-mobile' - - selection_size = 'xs' - ajax_handler = 'selection-xs.json' - - -@view_config(name='selection-xs.json', context=IResponsiveImage, request_type=IPyAMSLayer, - permission=VIEW_PERMISSION, renderer='json', xhr=True) -class ResponsiveImageXsSelectionAJAXEditForm(ResponsiveImageSelectionAJAXForm, ResponsiveImageXsSelectionForm): - """Responsive image XS selection edit form, JSON renderer""" -# -# Small devices selection -# - -@viewlet_config(name='responsive-image.selection.sm.action', context=IResponsiveImage, layer=IAdminLayer, - view=IImageWidget, manager=IContextActions, weight=42) -class ResponsiveImageSmSelectionAction(FileModifierAction): - """Responsive image SM selection""" - - label = _("Select responsive SM image...") - label_css_class = 'fa fa-fw-md fa-tablet' - - url = 'selection-sm.html' - modal_target = True - - -@pagelet_config(name='selection-sm.html', context=IResponsiveImage, layer=IPyAMSLayer, - permission=VIEW_PERMISSION) -class ResponsiveImageSmSelectionForm(ResponsiveImageSelectionForm): - """Responsive image SM selection edit form""" - - legend = _("Select image for small (SM) devices") - icon_css_class = 'fa fa-fw fa-tablet' +@viewlet_config(name='image-thumbnails', context=IImage, layer=IPyAMSLayer, + view=ImageThumbnailsDisplayForm, manager=IWidgetsPrefixViewletsManager) +@template_config(template='templates/image-thumbnails.pt') +class ImageThumbnailsViewletsPrefix(Viewlet): + """Image thumbnails viewlets prefix""" - selection_size = 'sm' - ajax_handler = 'selection-sm.json' - - -@view_config(name='selection-sm.json', context=IResponsiveImage, request_type=IPyAMSLayer, - permission=VIEW_PERMISSION, renderer='json', xhr=True) -class ResponsiveImageSmSelectionAJAXEditForm(ResponsiveImageSelectionAJAXForm, ResponsiveImageSmSelectionForm): - """Responsive image SM selection edit form, JSON renderer""" - - -# -# Medium devices selection -# - -@viewlet_config(name='responsive-image.selection.md.action', context=IResponsiveImage, layer=IAdminLayer, - view=IImageWidget, manager=IContextActions, weight=43) -class ResponsiveImageMdSelectionAction(FileModifierAction): - """Responsive image MD selection""" - - label = _("Select responsive MD image...") - label_css_class = 'fa fa-fw-md fa-desktop' - - url = 'selection-md.html' - modal_target = True - + @property + def random(self): + return random.randint(0, sys.maxsize) -@pagelet_config(name='selection-md.html', context=IResponsiveImage, layer=IPyAMSLayer, - permission=VIEW_PERMISSION) -class ResponsiveImageMdSelectionForm(ResponsiveImageSelectionForm): - """Responsive image MD selection edit form""" - - legend = _("Select image for medium (MD) devices") - icon_css_class = 'fa fa-fw fa-desktop' - - selection_size = 'md' - ajax_handler = 'selection-md.json' - - -@view_config(name='selection-md.json', context=IResponsiveImage, request_type=IPyAMSLayer, - permission=VIEW_PERMISSION, renderer='json', xhr=True) -class ResponsiveImageMdSelectionAJAXEditForm(ResponsiveImageSelectionAJAXForm, ResponsiveImageMdSelectionForm): - """Responsive image MD selection edit form, JSON renderer""" - - -# -# Large devices selection -# - -@viewlet_config(name='responsive-image.selection.lg.action', context=IResponsiveImage, layer=IAdminLayer, - view=IImageWidget, manager=IContextActions, weight=44) -class ResponsiveImageLgSelectionAction(FileModifierAction): - """Responsive image LG selection""" - - label = _("Select responsive LG image...") - label_css_class = 'fa fa-fw-md fa-television' - - url = 'selection-lg.html' - modal_target = True - - -@pagelet_config(name='selection-lg.html', context=IResponsiveImage, layer=IPyAMSLayer, - permission=VIEW_PERMISSION) -class ResponsiveImageLgSelectionForm(ResponsiveImageSelectionForm): - """Responsive image LG selection edit form""" - - legend = _("Select image for large (LG) devices") - icon_css_class = 'fa fa-fw fa-television' - - selection_size = 'lg' - ajax_handler = 'selection-lg.json' - - -@view_config(name='selection-lg.json', context=IResponsiveImage, request_type=IPyAMSLayer, - permission=VIEW_PERMISSION, renderer='json', xhr=True) -class ResponsiveImageLgSelectionAJAXEditForm(ResponsiveImageSelectionAJAXForm, ResponsiveImageLgSelectionForm): - """Responsive image LG selection edit form, JSON renderer""" + def get_thumbnails(self): + registry = self.request.registry + translate = self.request.localizer.translate + thumbnailers = OrderedDict() + adapters = sorted(registry.getAdapters((self.context, ), IThumbnailer), + key=lambda x: x[1].weight) + for name, adapter in adapters: + thumbnailers.setdefault(translate(adapter.section), []).append({'name': name, + 'label': translate(adapter.label)}) + return thumbnailers diff -r 3b2cb5046d86 -r 83ef19bfaa63 src/pyams_file/zmi/templates/image-thumbnails.pt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/pyams_file/zmi/templates/image-thumbnails.pt Mon Sep 11 13:30:46 2017 +0200 @@ -0,0 +1,20 @@ + + +
+ + +
+

Label

+
+ +
+
+
+
+
+