# HG changeset patch # User Thierry Florac # Date 1530094782 -7200 # Node ID db778bfa5f1732b1cf05697c2c32a2d6c74dad3a # Parent 2cbaa43fddec635e4f2586b1b49e2a387066c53f Added image rotate action and modified timestamps diff -r 2cbaa43fddec -r db778bfa5f17 src/pyams_file/file.py --- a/src/pyams_file/file.py Sat Jun 23 13:02:47 2018 +0200 +++ b/src/pyams_file/file.py Wed Jun 27 12:19:42 2018 +0200 @@ -254,6 +254,15 @@ request = check_request() request.registry.notify(FileModifiedEvent(self)) + def rotate(self, angle=-90): + image = Image.open(self.get_blob(mode='c')) + new_image = BytesIO() + image.rotate(angle, expand=True) \ + .save(new_image, image.format, quality=99) + self.data = new_image + request = check_request() + request.registry.notify(FileModifiedEvent(self)) + @implementer(ISVGImage) class SVGImageFile(File): diff -r 2cbaa43fddec -r db778bfa5f17 src/pyams_file/interfaces/__init__.py --- a/src/pyams_file/interfaces/__init__.py Sat Jun 23 13:02:47 2018 +0200 +++ b/src/pyams_file/interfaces/__init__.py Wed Jun 27 12:19:42 2018 +0200 @@ -84,6 +84,9 @@ def crop(self, x1, y1, x2, y2): """Crop image to given coordinates""" + def rotate(self, angle=-90): + """Rotate image, default to right""" + class ISVGImage(IBaseImage): """SVG file interface""" diff -r 2cbaa43fddec -r db778bfa5f17 src/pyams_file/locales/fr/LC_MESSAGES/pyams_file.mo Binary file src/pyams_file/locales/fr/LC_MESSAGES/pyams_file.mo has changed diff -r 2cbaa43fddec -r db778bfa5f17 src/pyams_file/locales/fr/LC_MESSAGES/pyams_file.po --- a/src/pyams_file/locales/fr/LC_MESSAGES/pyams_file.po Sat Jun 23 13:02:47 2018 +0200 +++ b/src/pyams_file/locales/fr/LC_MESSAGES/pyams_file.po Wed Jun 27 12:19:42 2018 +0200 @@ -5,7 +5,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE 1.0\n" -"POT-Creation-Date: 2018-06-08 12:31+0200\n" +"POT-Creation-Date: 2018-06-27 12:17+0200\n" "PO-Revision-Date: 2015-02-06 21:39+0100\n" "Last-Translator: Thierry Florac \n" "Language-Team: French\n" @@ -71,13 +71,9 @@ msgid "Delete content" msgstr "Supprimer ce contenu" -#: src/pyams_file/widget/templates/media-input.pt:30 -#: src/pyams_file/widget/templates/media-display.pt:12 -msgid "Zoom image" -msgstr "Agrandir l'image" - -#: src/pyams_file/widget/templates/media-input.pt:36 -#: src/pyams_file/widget/templates/media-input.pt:68 +#: src/pyams_file/widget/templates/media-input.pt:27 +#: src/pyams_file/widget/templates/media-input.pt:64 +#: src/pyams_file/widget/templates/media-input.pt:96 #: src/pyams_file/widget/templates/file-input.pt:31 #: src/pyams_file/widget/templates/file-display.pt:14 #: src/pyams_file/widget/templates/media-display.pt:20 @@ -85,8 +81,9 @@ msgid "Current value:" msgstr "Contenu actuel :" -#: src/pyams_file/widget/templates/media-input.pt:52 -#: src/pyams_file/widget/templates/media-input.pt:82 +#: src/pyams_file/widget/templates/media-input.pt:41 +#: src/pyams_file/widget/templates/media-input.pt:80 +#: src/pyams_file/widget/templates/media-input.pt:110 #: src/pyams_file/widget/templates/file-input.pt:45 #: src/pyams_file/widget/templates/file-display.pt:21 #: src/pyams_file/widget/templates/media-display.pt:30 @@ -94,6 +91,11 @@ msgid "Download" msgstr "Enregistrer sous..." +#: src/pyams_file/widget/templates/media-input.pt:55 +#: src/pyams_file/widget/templates/media-display.pt:12 +msgid "Zoom image" +msgstr "Agrandir l'image" + #: src/pyams_file/zmi/file.py:42 msgid "Properties..." msgstr "Propriétés" @@ -102,15 +104,19 @@ msgid "Update file properties" msgstr "Mise à jour des propriétés" -#: src/pyams_file/zmi/image.py:61 +#: src/pyams_file/zmi/image.py:107 +msgid "Rotate image to right..." +msgstr "Tourner l'image vers la droite" + +#: src/pyams_file/zmi/image.py:156 msgid "Crop image..." msgstr "Recadrer l'image" -#: src/pyams_file/zmi/image.py:83 +#: src/pyams_file/zmi/image.py:178 msgid "Crop image" msgstr "Recadrer l'image" -#: src/pyams_file/zmi/image.py:126 +#: src/pyams_file/zmi/image.py:226 msgid "" "You can use this form to crop an image.\n" "\n" @@ -128,7 +134,7 @@ "ou les vignettes déjà sélectionnées sur la base de l'ancienne image sont " "réinitialisées !" -#: src/pyams_file/zmi/image.py:140 +#: src/pyams_file/zmi/image.py:240 msgid "You can use this form to make a selection on an image." msgstr "" "Par défaut, l'image est affichée dans son intégralité quel que soit le type " @@ -141,39 +147,39 @@ "**ATTENTION** : si l'image d'origine est recadrée ou rechargée, la fonction " "est réinitialisée et il faut procéder à un nouveau choix." -#: src/pyams_file/zmi/image.py:160 +#: src/pyams_file/zmi/image.py:308 msgid "Select portrait thumbnail..." msgstr "Vignette portrait" -#: src/pyams_file/zmi/image.py:182 +#: src/pyams_file/zmi/image.py:330 msgid "Select portrait thumbnail" msgstr "Emprise de la vignette en mode portrait" -#: src/pyams_file/zmi/image.py:225 +#: src/pyams_file/zmi/image.py:341 msgid "" "You can use this form to select a portrait thumbnail of this image.\n" "\n" "**WARNING**: cropping or resizing an image will reset all selected " "thumbnails and adaptive images!!" msgstr "" -"L'utilisation d'une vignette en mode portrait n'est pas systématique, elle dépend " -"du modèle de présentation qui peut ou non y faire appel. Par défaut, la " -"vignette est positionnée au centre de l'image, la sélection de " -"son emprise ne modifie pas l'image d'origine.\n" +"L'utilisation d'une vignette en mode portrait n'est pas systématique, elle " +"dépend du modèle de présentation qui peut ou non y faire appel. Par défaut, " +"la vignette est positionnée au centre de l'image, la sélection de son " +"emprise ne modifie pas l'image d'origine.\n" "\n" "**ATTENTION** : lorsqu'une image est recadrée, redimentionnée ou rechargée, " "la sélection est réinitialisée sur sa position par défaut (centrée) ; s'il y " "a lieu, vous devez procéder à une nouvelle sélection personnalisée." -#: src/pyams_file/zmi/image.py:240 +#: src/pyams_file/zmi/image.py:356 msgid "Select square thumbnail..." msgstr "Vignette carrée" -#: src/pyams_file/zmi/image.py:262 +#: src/pyams_file/zmi/image.py:378 msgid "Select square thumbnail" msgstr "Emprise de la vignette carrée" -#: src/pyams_file/zmi/image.py:305 +#: src/pyams_file/zmi/image.py:389 msgid "" "You can use this form to select a square thumbnail of this image.\n" "\n" @@ -189,15 +195,15 @@ "la sélection est réinitialisée sur sa position par défaut (centrée) ; s'il y " "a lieu, vous devez procéder à une nouvelle sélection personnalisée." -#: src/pyams_file/zmi/image.py:320 +#: src/pyams_file/zmi/image.py:404 msgid "Select panoramic thumbnail..." msgstr "Vignette panoramique" -#: src/pyams_file/zmi/image.py:342 +#: src/pyams_file/zmi/image.py:426 msgid "Select panoramic thumbnail" msgstr "Emprise de la vignette panoramique" -#: src/pyams_file/zmi/image.py:385 +#: src/pyams_file/zmi/image.py:437 msgid "" "You can use this form to select a panoramic thumbnail of this image.\n" "\n" @@ -213,55 +219,55 @@ "la sélection est réinitialisée sur sa position par défaut (centrée) ; s'il y " "a lieu, vous devez procéder à une nouvelle sélection personnalisée." -#: src/pyams_file/zmi/image.py:458 +#: src/pyams_file/zmi/image.py:452 msgid "Select responsive XS image..." msgstr "Image adaptative pour smartphones" -#: src/pyams_file/zmi/image.py:479 +#: src/pyams_file/zmi/image.py:473 msgid "Select image for extra-small (XS) devices" msgstr "Portion de l'image affichée sur les smartphones (taille XS)" -#: src/pyams_file/zmi/image.py:494 +#: src/pyams_file/zmi/image.py:488 msgid "Select responsive SM image..." msgstr "Image adaptative pour tablettes" -#: src/pyams_file/zmi/image.py:515 +#: src/pyams_file/zmi/image.py:509 msgid "Select image for small (SM) devices" msgstr "Portion de l'image affichée sur les tablettes (taille SM)" -#: src/pyams_file/zmi/image.py:530 +#: src/pyams_file/zmi/image.py:524 msgid "Select responsive MD image..." msgstr "Image adaptative pour terminaux moyens" -#: src/pyams_file/zmi/image.py:551 +#: src/pyams_file/zmi/image.py:545 msgid "Select image for medium (MD) devices" msgstr "Portion de l'image affichée sur les terminaux moyens (taille MD)" -#: src/pyams_file/zmi/image.py:566 +#: src/pyams_file/zmi/image.py:560 msgid "Select responsive LG image..." msgstr "Image adaptative pour grands terminaux" -#: src/pyams_file/zmi/image.py:587 +#: src/pyams_file/zmi/image.py:581 msgid "Select image for large (LG) devices" msgstr "Portion de l'image affichée sur les grands terminaux (taille LG)" -#: src/pyams_file/zmi/image.py:602 +#: src/pyams_file/zmi/image.py:596 msgid "Display all thumbnails" msgstr "Voir toutes les vignettes" -#: src/pyams_file/zmi/image.py:619 +#: src/pyams_file/zmi/image.py:613 msgid "Display all image thumbnails" msgstr "Récapitulatif des vignettes associées" -#: src/pyams_file/zmi/image.py:664 +#: src/pyams_file/zmi/image.py:654 msgid "Resize image..." msgstr "Redimensionner l'image" -#: src/pyams_file/zmi/image.py:718 src/pyams_file/zmi/image.py:675 +#: src/pyams_file/zmi/image.py:708 src/pyams_file/zmi/image.py:665 msgid "Resize image" msgstr "Redimensionner l'image" -#: src/pyams_file/zmi/image.py:749 +#: src/pyams_file/zmi/image.py:739 msgid "" "You can use this form to change image dimensions.\n" "\n" @@ -273,32 +279,32 @@ "Une nouvelle image ne sera générée que si les dimensions indiquées sont " "inférieures à la taille du fichier actuel." -#: src/pyams_file/zmi/image.py:71 src/pyams_file/zmi/image.py:147 -#: src/pyams_file/zmi/image.py:398 src/pyams_file/zmi/image.py:674 +#: src/pyams_file/zmi/image.py:166 src/pyams_file/zmi/image.py:247 +#: src/pyams_file/zmi/image.py:664 msgid "Close" msgstr "Fermer" -#: src/pyams_file/zmi/image.py:72 +#: src/pyams_file/zmi/image.py:167 msgid "Crop" msgstr "Recadrer l'image" -#: src/pyams_file/zmi/image.py:148 src/pyams_file/zmi/image.py:399 +#: src/pyams_file/zmi/image.py:248 msgid "Select thumbnail" msgstr "Sélectionner cette portion d'image" -#: src/pyams_file/zmi/image.py:681 +#: src/pyams_file/zmi/image.py:671 msgid "New image width" msgstr "Largeur de l'image" -#: src/pyams_file/zmi/image.py:683 +#: src/pyams_file/zmi/image.py:673 msgid "New image height" msgstr "Hauteur de l'image" -#: src/pyams_file/zmi/image.py:685 +#: src/pyams_file/zmi/image.py:675 msgid "Keep aspect ratio" msgstr "Ne pas déformer l'image" -#: src/pyams_file/zmi/image.py:686 +#: src/pyams_file/zmi/image.py:676 msgid "" "Check to keep original aspect ratio; image will be resized as large as " "possible within given limits" @@ -307,27 +313,27 @@ "L'image sera redimensionnée (sans jamais être agrandie !) pour être aussi " "grande que possible en fonction des contraintes indiquées." -#: src/pyams_file/interfaces/__init__.py:99 +#: src/pyams_file/interfaces/__init__.py:110 msgid "Title" msgstr "Titre" -#: src/pyams_file/interfaces/__init__.py:102 +#: src/pyams_file/interfaces/__init__.py:113 msgid "Description" msgstr "Description" -#: src/pyams_file/interfaces/__init__.py:105 +#: src/pyams_file/interfaces/__init__.py:116 msgid "Save file as..." msgstr "Enregistrer sous..." -#: src/pyams_file/interfaces/__init__.py:106 +#: src/pyams_file/interfaces/__init__.py:117 msgid "Name under which the file will be saved" msgstr "Nom proposé automatiquement lors de l'enregistrement du fichier" -#: src/pyams_file/interfaces/__init__.py:109 +#: src/pyams_file/interfaces/__init__.py:120 msgid "Language" msgstr "Langue" -#: src/pyams_file/interfaces/__init__.py:110 +#: src/pyams_file/interfaces/__init__.py:121 msgid "File's content language" msgstr "Langue du contenu du fichier" diff -r 2cbaa43fddec -r db778bfa5f17 src/pyams_file/locales/pyams_file.pot --- a/src/pyams_file/locales/pyams_file.pot Sat Jun 23 13:02:47 2018 +0200 +++ b/src/pyams_file/locales/pyams_file.pot Wed Jun 27 12:19:42 2018 +0200 @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE 1.0\n" -"POT-Creation-Date: 2018-06-08 12:31+0200\n" +"POT-Creation-Date: 2018-06-27 12:17+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" @@ -71,13 +71,9 @@ msgid "Delete content" msgstr "" -#: ./src/pyams_file/widget/templates/media-input.pt:30 -#: ./src/pyams_file/widget/templates/media-display.pt:12 -msgid "Zoom image" -msgstr "" - -#: ./src/pyams_file/widget/templates/media-input.pt:36 -#: ./src/pyams_file/widget/templates/media-input.pt:68 +#: ./src/pyams_file/widget/templates/media-input.pt:27 +#: ./src/pyams_file/widget/templates/media-input.pt:64 +#: ./src/pyams_file/widget/templates/media-input.pt:96 #: ./src/pyams_file/widget/templates/file-input.pt:31 #: ./src/pyams_file/widget/templates/file-display.pt:14 #: ./src/pyams_file/widget/templates/media-display.pt:20 @@ -85,8 +81,9 @@ msgid "Current value:" msgstr "" -#: ./src/pyams_file/widget/templates/media-input.pt:52 -#: ./src/pyams_file/widget/templates/media-input.pt:82 +#: ./src/pyams_file/widget/templates/media-input.pt:41 +#: ./src/pyams_file/widget/templates/media-input.pt:80 +#: ./src/pyams_file/widget/templates/media-input.pt:110 #: ./src/pyams_file/widget/templates/file-input.pt:45 #: ./src/pyams_file/widget/templates/file-display.pt:21 #: ./src/pyams_file/widget/templates/media-display.pt:30 @@ -94,6 +91,11 @@ msgid "Download" msgstr "" +#: ./src/pyams_file/widget/templates/media-input.pt:55 +#: ./src/pyams_file/widget/templates/media-display.pt:12 +msgid "Zoom image" +msgstr "" + #: ./src/pyams_file/zmi/file.py:42 msgid "Properties..." msgstr "" @@ -102,176 +104,180 @@ msgid "Update file properties" msgstr "" -#: ./src/pyams_file/zmi/image.py:61 +#: ./src/pyams_file/zmi/image.py:107 +msgid "Rotate image to right..." +msgstr "" + +#: ./src/pyams_file/zmi/image.py:156 msgid "Crop image..." msgstr "" -#: ./src/pyams_file/zmi/image.py:83 +#: ./src/pyams_file/zmi/image.py:178 msgid "Crop image" msgstr "" -#: ./src/pyams_file/zmi/image.py:126 +#: ./src/pyams_file/zmi/image.py:226 msgid "" "You can use this form to crop an image.\n" "\n" "**WARNING**: cropping an image will reset all selected thumbnails and adaptive images!!" msgstr "" -#: ./src/pyams_file/zmi/image.py:140 +#: ./src/pyams_file/zmi/image.py:240 msgid "You can use this form to make a selection on an image." msgstr "" -#: ./src/pyams_file/zmi/image.py:160 +#: ./src/pyams_file/zmi/image.py:308 msgid "Select portrait thumbnail..." msgstr "" -#: ./src/pyams_file/zmi/image.py:182 +#: ./src/pyams_file/zmi/image.py:330 msgid "Select portrait thumbnail" msgstr "" -#: ./src/pyams_file/zmi/image.py:225 +#: ./src/pyams_file/zmi/image.py:341 msgid "" "You can use this form to select a portrait thumbnail of this image.\n" "\n" "**WARNING**: cropping or resizing an image will reset all selected thumbnails and adaptive images!!" msgstr "" -#: ./src/pyams_file/zmi/image.py:240 +#: ./src/pyams_file/zmi/image.py:356 msgid "Select square thumbnail..." msgstr "" -#: ./src/pyams_file/zmi/image.py:262 +#: ./src/pyams_file/zmi/image.py:378 msgid "Select square thumbnail" msgstr "" -#: ./src/pyams_file/zmi/image.py:305 +#: ./src/pyams_file/zmi/image.py:389 msgid "" "You can use this form to select a square thumbnail of this image.\n" "\n" "**WARNING**: cropping or resizing an image will reset all selected thumbnails and adaptive images!!" msgstr "" -#: ./src/pyams_file/zmi/image.py:320 +#: ./src/pyams_file/zmi/image.py:404 msgid "Select panoramic thumbnail..." msgstr "" -#: ./src/pyams_file/zmi/image.py:342 +#: ./src/pyams_file/zmi/image.py:426 msgid "Select panoramic thumbnail" msgstr "" -#: ./src/pyams_file/zmi/image.py:385 +#: ./src/pyams_file/zmi/image.py:437 msgid "" "You can use this form to select a panoramic thumbnail of this image.\n" "\n" "**WARNING**: cropping or resizing an image will reset all selected thumbnails and adaptive images!!" msgstr "" -#: ./src/pyams_file/zmi/image.py:458 +#: ./src/pyams_file/zmi/image.py:452 msgid "Select responsive XS image..." msgstr "" -#: ./src/pyams_file/zmi/image.py:479 +#: ./src/pyams_file/zmi/image.py:473 msgid "Select image for extra-small (XS) devices" msgstr "" -#: ./src/pyams_file/zmi/image.py:494 +#: ./src/pyams_file/zmi/image.py:488 msgid "Select responsive SM image..." msgstr "" -#: ./src/pyams_file/zmi/image.py:515 +#: ./src/pyams_file/zmi/image.py:509 msgid "Select image for small (SM) devices" msgstr "" -#: ./src/pyams_file/zmi/image.py:530 +#: ./src/pyams_file/zmi/image.py:524 msgid "Select responsive MD image..." msgstr "" -#: ./src/pyams_file/zmi/image.py:551 +#: ./src/pyams_file/zmi/image.py:545 msgid "Select image for medium (MD) devices" msgstr "" -#: ./src/pyams_file/zmi/image.py:566 +#: ./src/pyams_file/zmi/image.py:560 msgid "Select responsive LG image..." msgstr "" -#: ./src/pyams_file/zmi/image.py:587 +#: ./src/pyams_file/zmi/image.py:581 msgid "Select image for large (LG) devices" msgstr "" -#: ./src/pyams_file/zmi/image.py:602 +#: ./src/pyams_file/zmi/image.py:596 msgid "Display all thumbnails" msgstr "" -#: ./src/pyams_file/zmi/image.py:619 +#: ./src/pyams_file/zmi/image.py:613 msgid "Display all image thumbnails" msgstr "" -#: ./src/pyams_file/zmi/image.py:664 +#: ./src/pyams_file/zmi/image.py:654 msgid "Resize image..." msgstr "" -#: ./src/pyams_file/zmi/image.py:718 ./src/pyams_file/zmi/image.py:675 +#: ./src/pyams_file/zmi/image.py:708 ./src/pyams_file/zmi/image.py:665 msgid "Resize image" msgstr "" -#: ./src/pyams_file/zmi/image.py:749 +#: ./src/pyams_file/zmi/image.py:739 msgid "" "You can use this form to change image dimensions.\n" "\n" "This will generate a new image only if requested size is smaller than the original one." msgstr "" -#: ./src/pyams_file/zmi/image.py:71 ./src/pyams_file/zmi/image.py:147 -#: ./src/pyams_file/zmi/image.py:398 ./src/pyams_file/zmi/image.py:674 +#: ./src/pyams_file/zmi/image.py:166 ./src/pyams_file/zmi/image.py:247 +#: ./src/pyams_file/zmi/image.py:664 msgid "Close" msgstr "" -#: ./src/pyams_file/zmi/image.py:72 +#: ./src/pyams_file/zmi/image.py:167 msgid "Crop" msgstr "" -#: ./src/pyams_file/zmi/image.py:148 ./src/pyams_file/zmi/image.py:399 +#: ./src/pyams_file/zmi/image.py:248 msgid "Select thumbnail" msgstr "" -#: ./src/pyams_file/zmi/image.py:681 +#: ./src/pyams_file/zmi/image.py:671 msgid "New image width" msgstr "" -#: ./src/pyams_file/zmi/image.py:683 +#: ./src/pyams_file/zmi/image.py:673 msgid "New image height" msgstr "" -#: ./src/pyams_file/zmi/image.py:685 +#: ./src/pyams_file/zmi/image.py:675 msgid "Keep aspect ratio" msgstr "" -#: ./src/pyams_file/zmi/image.py:686 +#: ./src/pyams_file/zmi/image.py:676 msgid "" "Check to keep original aspect ratio; image will be resized as large as " "possible within given limits" msgstr "" -#: ./src/pyams_file/interfaces/__init__.py:99 +#: ./src/pyams_file/interfaces/__init__.py:110 msgid "Title" msgstr "" -#: ./src/pyams_file/interfaces/__init__.py:102 +#: ./src/pyams_file/interfaces/__init__.py:113 msgid "Description" msgstr "" -#: ./src/pyams_file/interfaces/__init__.py:105 +#: ./src/pyams_file/interfaces/__init__.py:116 msgid "Save file as..." msgstr "" -#: ./src/pyams_file/interfaces/__init__.py:106 +#: ./src/pyams_file/interfaces/__init__.py:117 msgid "Name under which the file will be saved" msgstr "" -#: ./src/pyams_file/interfaces/__init__.py:109 +#: ./src/pyams_file/interfaces/__init__.py:120 msgid "Language" msgstr "" -#: ./src/pyams_file/interfaces/__init__.py:110 +#: ./src/pyams_file/interfaces/__init__.py:121 msgid "File's content language" msgstr "" diff -r 2cbaa43fddec -r db778bfa5f17 src/pyams_file/widget/__init__.py --- a/src/pyams_file/widget/__init__.py Sat Jun 23 13:02:47 2018 +0200 +++ b/src/pyams_file/widget/__init__.py Wed Jun 27 12:19:42 2018 +0200 @@ -24,6 +24,7 @@ from pyams_form.interfaces.form import IFormLayer from pyramid.interfaces import IView from z3c.form.interfaces import NOT_CHANGED, IFieldWidget, IDataConverter +from zope.dublincore.interfaces import IZopeDublinCore # import packages from pyams_file.file import EXTENSIONS_THUMBNAILS @@ -72,7 +73,11 @@ @property def timestamp(self): - return datetime.utcnow().timestamp() + dc = IZopeDublinCore(self.current_value, None) + if dc is None: + return datetime.utcnow().timestamp() + else: + return dc.modified.timestamp() @property def current_value(self): diff -r 2cbaa43fddec -r db778bfa5f17 src/pyams_file/widget/templates/media-display.pt --- a/src/pyams_file/widget/templates/media-display.pt Sat Jun 23 13:02:47 2018 +0200 +++ b/src/pyams_file/widget/templates/media-display.pt Wed Jun 27 12:19:42 2018 +0200 @@ -10,10 +10,10 @@ target python:thumbnails.get_thumbnail('800x600', 'jpeg');" tal:attributes="href extension:absolute_url(target);" title="Zoom image" i18n:attributes="title"> - + tal:attributes="src string:${extension:absolute_url(thumbnail)}?_=${extension:timestamp(thumbnail)}; + title i18n:value.title;" />
diff -r 2cbaa43fddec -r db778bfa5f17 src/pyams_file/widget/templates/media-input.pt --- a/src/pyams_file/widget/templates/media-input.pt Sat Jun 23 13:02:47 2018 +0200 +++ b/src/pyams_file/widget/templates/media-input.pt Wed Jun 27 12:19:42 2018 +0200 @@ -53,9 +53,12 @@ target python:view.get_thumbnail('800x600');" tal:attributes="href extension:absolute_url(target);" title="Zoom image" i18n:attributes="title"> - +
Current value: diff -r 2cbaa43fddec -r db778bfa5f17 src/pyams_file/zmi/image.py --- a/src/pyams_file/zmi/image.py Sat Jun 23 13:02:47 2018 +0200 +++ b/src/pyams_file/zmi/image.py Wed Jun 27 12:19:42 2018 +0200 @@ -9,6 +9,7 @@ # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # +from transaction.interfaces import ITransactionManager __docformat__ = 'restructuredtext' @@ -24,10 +25,12 @@ from pyams_file.interfaces import IImage, IThumbnail, IResponsiveImage, IFileModifierForm, IThumbnailer, \ IFileInfo, IThumbnailForm, IMediaWidget, ISVGImage from pyams_form.interfaces.form import IWidgetsPrefixViewletsManager, IFormHelp +from pyams_i18n.interfaces import II18n from pyams_skin.interfaces.viewlet import IContextActions from pyams_skin.layer import IPyAMSLayer -from pyams_utils.interfaces import VIEW_PERMISSION +from pyams_utils.interfaces import VIEW_PERMISSION, ICacheKeyValue from pyams_zmi.layer import IAdminLayer +from zope.dublincore.interfaces import IZopeDublinCore # import packages from pyams_file.image import ThumbnailGeometry @@ -43,6 +46,7 @@ from pyams_viewlet.viewlet import viewlet_config, Viewlet from pyams_zmi.form import AdminDialogEditForm from pyramid.renderers import render +from pyramid.view import view_config from z3c.form import field, button from zope.interface import implementer, Interface from zope.schema import Int, Bool @@ -92,6 +96,55 @@ # +# Image rotate +# + +@viewlet_config(name='image-rotate.action', context=IImage, layer=IPyAMSLayer, view=IMediaWidget, + manager=IContextActions, weight=20) +class ImageRotateAction(FileModifierAction): + """Image rotate action""" + + label = _("Rotate image to right...") + label_css_class = 'fa fa-fw-md fa-rotate-right' + + @property + def url(self): + return 'MyAMS.ajax.getJSON?url={0}'.format(absolute_url(self.context, self.request, 'rotate.json')) + + def get_url(self): + return self.url + + +@view_config(name='rotate.json', context=IImage, request_type=IPyAMSLayer, + permission=VIEW_PERMISSION, renderer='json', xhr=True) +def rotate_image(request): + """Rotate given image to right""" + image = request.context + IImage(image).rotate(-90) + # Commit to save blobs!! + ITransactionManager(image).commit() + cache_key = ICacheKeyValue(image) + thumbnail = IThumbnail(image).get_thumbnail('128x128') + dc = IZopeDublinCore(thumbnail) + return { + 'status': 'success', + 'message': request.localizer.translate(AdminDialogEditForm.successMessage), + 'callbacks': [{ + 'callback': 'MyAMS.skin.refreshContent', + 'options': { + 'object_id': 'thumbnail_{0}'.format(cache_key), + 'content': ''.format( + key=cache_key, + src='{0}?_={1}'.format(absolute_url(thumbnail, request), dc.modified.timestamp()), + title=II18n(image).query_attribute('title', request=request) + ) + } + }], + 'close_form': False + } + + +# # Image crop # @@ -134,6 +187,11 @@ def title(self): return self.context.title or self.context.filename + @property + def timestamp(self): + dc = IZopeDublinCore(self.context) + return dc.modified.timestamp() + def updateActions(self): super(ImageCropForm, self).updateActions() if 'crop' in self.actions: @@ -232,6 +290,11 @@ class ImageSelectionThumbnailViewletsPrefix(Viewlet): """Image square thumbnail viewlets prefix""" + @property + def timestamp(self): + dc = IZopeDublinCore(self.context) + return dc.modified.timestamp() + # # Image portrait thumbnail selection @@ -560,10 +623,6 @@ class ImageThumbnailsViewletsPrefix(Viewlet): """Image thumbnails viewlets prefix""" - @property - def random(self): - return random.randint(0, sys.maxsize) - def get_thumbnails(self): registry = self.request.registry translate = self.request.localizer.translate diff -r 2cbaa43fddec -r db778bfa5f17 src/pyams_file/zmi/templates/image-crop.pt --- a/src/pyams_file/zmi/templates/image-crop.pt Sat Jun 23 13:02:47 2018 +0200 +++ b/src/pyams_file/zmi/templates/image-crop.pt Wed Jun 27 12:19:42 2018 +0200 @@ -9,7 +9,9 @@ + tal:attributes="src string:${base}/++thumb++${thname}200x128.jpeg?_=${extension:timestamp(context)}" />