source: main/waeup.kofa/trunk/src/waeup/kofa/image/browser/widget.py

Last change on this file was 7819, checked in by Henrik Bettermann, 13 years ago

KOFA -> Kofa

  • Property svn:keywords set to Id
File size: 5.8 KB
Line 
1## $Id: widget.py 7819 2012-03-08 22:28:46Z henrik $
2##
3## Copyright (C) 2011 Uli Fouquet & Henrik Bettermann
4## This program is free software; you can redistribute it and/or modify
5## it under the terms of the GNU General Public License as published by
6## the Free Software Foundation; either version 2 of the License, or
7## (at your option) any later version.
8##
9## This program is distributed in the hope that it will be useful,
10## but WITHOUT ANY WARRANTY; without even the implied warranty of
11## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12## GNU General Public License for more details.
13##
14## You should have received a copy of the GNU General Public License
15## along with this program; if not, write to the Free Software
16## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17##
18"""Image file widgets.
19"""
20import os
21from waeup.kofa.image import KofaImageFile
22from hurry.file.browser.widget import (
23    EncodingFileWidget, DownloadWidget, FakeFieldStorage)
24from hurry.file.interfaces import IFileRetrieval
25from zope.app.form.browser.textwidgets import escape
26from zope.app.form.browser.widget import renderElement
27from zope.app.form.interfaces import ConversionError
28from zope.component import queryUtility
29from zope.publisher.browser import FileUpload
30
31
32class EncodingImageFileWidget(EncodingFileWidget):
33    """A hurry.file widget that stores images.
34
35    This is an upload widget suitable for edit forms and the like.
36    """
37    #: We can set a basename for the image to be rendered.
38    #: This will result in <img> links like <img src='.../<basename>.jpg' />
39    image_basename = None
40
41    def _toFieldValue(self, (input, file_id)):
42        # we got no file upload input
43        if not input:
44            # if we got a file_id, then retrieve file and return it
45            if file_id:
46                return self._retrieveFile(file_id)
47            # no file upload input nor file id, so return missing value
48            return self.context.missing_value
49        # read in file from input
50        try:
51            seek = input.seek
52            read = input.read
53        except AttributeError, e:
54            raise ConversionError('Form input is not a file object', e)
55
56        seek(0)
57        data = read()
58
59        if data:
60            retrieval = queryUtility(IFileRetrieval)
61            if retrieval is not None:
62                seek(0)
63                return retrieval.createFile(input.filename, input)
64            return KofaImageFile(input.filename, data)
65        else:
66            return self.context.missing_value
67
68    def _toFormValue(self, value):
69        if value == self.context.missing_value:
70            return self._missing
71        data = value.file.read()
72        return FileUpload(FakeFieldStorage(
73                value.filename.encode('UTF-8'), data))
74
75    def __call__(self):
76        value = self._getFormValue()
77        if value:
78            file_id = self._setFile(value)
79        else:
80            file_id = None
81        result = u''
82        options = dict(
83            type=self.type,
84            name=self.name,
85            id=self.name,
86            cssClass=self.cssClass,
87            size=self.displayWidth,
88            extra=self.extra,)
89        if self.displayMaxWidth:
90            options.update(maxlength=self.displayMaxWidth)
91        if value:
92            filename = value.filename
93            if self.image_basename is not None:
94                filename = self.image_basename + os.path.splitext(filename)[-1]
95            result = renderElement(
96                'img',
97                src=filename,
98                )
99            result += renderElement('br')
100        result += renderElement(self.tag, **options)
101        if file_id is not None:
102            if value:
103                result += ' (%s)' % value.filename
104            result += renderElement(
105                'input',
106                type='hidden',
107                name=self.name + '.file_id',
108                id=self.name + '.file_id',
109                value=file_id,
110                )
111        return result
112
113    def _setFile(self, file):
114        """Store away uploaded file (FileUpload object).
115
116        Returns file_id identifying file.
117        """
118        # if there was no file input and there was a file_id already in the
119        # input, reuse this for next request
120        if not self.request.get(self.name):
121            file_id = self.request.get(self.name + '.file_id')
122            if file_id is not None:
123                return file_id
124        # otherwise, stuff filedata away in session, making a new file_id
125        if file == self.context.missing_value:
126            return None
127        return self._storeFile(file)
128
129    def _storeFile(self, file_upload):
130        # filenames are normally in unicode encoding, while the contents
131        # are byte streams. We turn the filename into a bytestream.
132        retrieval = queryUtility(IFileRetrieval)
133        if retrieval is not None:
134            file_upload.seek(0)
135            file_obj = retrieval.createFile(file_upload.filename, file_upload)
136            data = file_obj.data
137        else:
138            data = file_upload.read()
139        data = '%s\n%s' % (str(file_upload.filename), data)
140        return data.encode('base64')[:-1]
141
142    def _retrieveFile(self, file_id):
143        data = file_id.decode('base64')
144        filename, filedata = data.split('\n', 1)
145        return KofaImageFile(filename, filedata)
146
147class ThumbnailWidget(DownloadWidget):
148    """An image file widget that displays the data as thumbnail.
149
150    XXX: give some reason to name this a _thumbnail_ widget.
151    """
152
153    def __call__(self):
154        if self._renderedValueSet():
155            value = self._data
156        else:
157            value = self.context.default
158        if value == self.context.missing_value:
159            return renderElement(
160                u'div',
161                contents=u'Download not available')
162        filename = escape(value.filename)
163        return renderElement(
164            u'img',
165            src=filename,
166            contents=None)
Note: See TracBrowser for help on using the repository browser.