## $Id: widget.py 7819 2012-03-08 22:28:46Z henrik $ ## ## Copyright (C) 2011 Uli Fouquet & Henrik Bettermann ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 2 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, write to the Free Software ## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## """Image file widgets. """ import os from waeup.kofa.image import KofaImageFile from hurry.file.browser.widget import ( EncodingFileWidget, DownloadWidget, FakeFieldStorage) from hurry.file.interfaces import IFileRetrieval from zope.app.form.browser.textwidgets import escape from zope.app.form.browser.widget import renderElement from zope.app.form.interfaces import ConversionError from zope.component import queryUtility from zope.publisher.browser import FileUpload class EncodingImageFileWidget(EncodingFileWidget): """A hurry.file widget that stores images. This is an upload widget suitable for edit forms and the like. """ #: We can set a basename for the image to be rendered. #: This will result in links like image_basename = None def _toFieldValue(self, (input, file_id)): # we got no file upload input if not input: # if we got a file_id, then retrieve file and return it if file_id: return self._retrieveFile(file_id) # no file upload input nor file id, so return missing value return self.context.missing_value # read in file from input try: seek = input.seek read = input.read except AttributeError, e: raise ConversionError('Form input is not a file object', e) seek(0) data = read() if data: retrieval = queryUtility(IFileRetrieval) if retrieval is not None: seek(0) return retrieval.createFile(input.filename, input) return KofaImageFile(input.filename, data) else: return self.context.missing_value def _toFormValue(self, value): if value == self.context.missing_value: return self._missing data = value.file.read() return FileUpload(FakeFieldStorage( value.filename.encode('UTF-8'), data)) def __call__(self): value = self._getFormValue() if value: file_id = self._setFile(value) else: file_id = None result = u'' options = dict( type=self.type, name=self.name, id=self.name, cssClass=self.cssClass, size=self.displayWidth, extra=self.extra,) if self.displayMaxWidth: options.update(maxlength=self.displayMaxWidth) if value: filename = value.filename if self.image_basename is not None: filename = self.image_basename + os.path.splitext(filename)[-1] result = renderElement( 'img', src=filename, ) result += renderElement('br') result += renderElement(self.tag, **options) if file_id is not None: if value: result += ' (%s)' % value.filename result += renderElement( 'input', type='hidden', name=self.name + '.file_id', id=self.name + '.file_id', value=file_id, ) return result def _setFile(self, file): """Store away uploaded file (FileUpload object). Returns file_id identifying file. """ # if there was no file input and there was a file_id already in the # input, reuse this for next request if not self.request.get(self.name): file_id = self.request.get(self.name + '.file_id') if file_id is not None: return file_id # otherwise, stuff filedata away in session, making a new file_id if file == self.context.missing_value: return None return self._storeFile(file) def _storeFile(self, file_upload): # filenames are normally in unicode encoding, while the contents # are byte streams. We turn the filename into a bytestream. retrieval = queryUtility(IFileRetrieval) if retrieval is not None: file_upload.seek(0) file_obj = retrieval.createFile(file_upload.filename, file_upload) data = file_obj.data else: data = file_upload.read() data = '%s\n%s' % (str(file_upload.filename), data) return data.encode('base64')[:-1] def _retrieveFile(self, file_id): data = file_id.decode('base64') filename, filedata = data.split('\n', 1) return KofaImageFile(filename, filedata) class ThumbnailWidget(DownloadWidget): """An image file widget that displays the data as thumbnail. XXX: give some reason to name this a _thumbnail_ widget. """ def __call__(self): if self._renderedValueSet(): value = self._data else: value = self.context.default if value == self.context.missing_value: return renderElement( u'div', contents=u'Download not available') filename = escape(value.filename) return renderElement( u'img', src=filename, contents=None)