appy.gen: ugly Zope acquisition-related bugfix; bugfix while rendering file widgets.

This commit is contained in:
Gaetan Delannay 2011-10-11 17:32:23 +02:00
parent 17f6d15185
commit f1136eb786
3 changed files with 47 additions and 42 deletions
gen/plone25
mixins
skin/widgets

View file

@ -26,7 +26,8 @@ class BaseMixin:
return self
o = property(get_o)
def createOrUpdate(self, created, values):
def createOrUpdate(self, created, values,
initiator=None, initiatorField=None):
'''This method creates (if p_created is True) or updates an object.
p_values are manipulated versions of those from the HTTP request.
In the case of an object creation (p_created is True), p_self is a
@ -56,13 +57,7 @@ class BaseMixin:
self.historizeData(previousData)
# Manage potential link with an initiator object
if created and rq.get('nav', None):
# Get the initiator
splitted = rq['nav'].split('.')
if splitted[0] == 'search': return # Not an initiator but a search.
initiator = self.getTool().getObject(splitted[1])
fieldName = splitted[2].split(':')[0]
initiator.appy().link(fieldName, obj)
if created and initiator: initiator.appy().link(initiatorField, obj)
# Manage "add" permissions and reindex the object
obj._appy_managePermissions()
@ -182,10 +177,11 @@ class BaseMixin:
# If this object is created from an initiator, get info about him.
initiator = None
initiatorPage = None
initiatorField = None
if rq.get('nav', '').startswith('ref.'):
splitted = rq['nav'].split('.')
initiator = tool.getObject(splitted[1])
initiatorPage = splitted[2].split(':')[1]
initiatorField, initiatorPage = splitted[2].split(':')
# If the user clicked on 'Cancel', go back to the previous page.
if rq.get('buttonCancel.x', None):
if initiator:
@ -230,14 +226,14 @@ class BaseMixin:
return self.gotoEdit()
# Create or update the object in the database
obj, msg = self.createOrUpdate(isNew, values)
obj, msg = self.createOrUpdate(isNew, values, initiator, initiatorField)
# Redirect the user to the appropriate page
if not msg: msg = obj.translate('Changes saved.', domain='plone')
# If the object has already been deleted (ie, it is a kind of transient
# object like a one-shot form and has already been deleted in method
# onEdit), redirect to the main site page.
if not getattr(obj.getParentNode(), obj.id, None):
if not getattr(obj.getParentNode().aq_base, obj.id, None):
obj.unindexObject()
return self.goto(tool.getSiteUrl(), msg)
# If the user can't access the object anymore, redirect him to the
@ -426,6 +422,8 @@ class BaseMixin:
def getMethod(self, methodName):
'''Returns the method named p_methodName.'''
# If I write "self.aq_base" instead of self, acquisition will be
# broken on returned object.
return getattr(self, methodName, None)
def getFieldValue(self, name, onlyIfSync=False, layoutType=None):
@ -441,6 +439,11 @@ class BaseMixin:
field named p_name.'''
return self.getAppyType(name).getFormattedValue(self, value)
def getFileInfo(self, fileObject):
'''Returns filename and size of p_fileObject.'''
if not fileObject: return {'filename': '', 'size': 0}
return {'filename': fileObject.filename, 'size': fileObject.size}
def getAppyRefs(self, name, startNumber=None):
'''Gets the objects linked to me through Ref field named p_name.
If p_startNumber is None, this method returns all referred objects.
@ -498,7 +501,7 @@ class BaseMixin:
def getAppyRefIndex(self, fieldName, obj):
'''Gets the position of p_obj within Ref field named p_fieldName.'''
refs = getattr(self, fieldName, None)
refs = getattr(self.aq_base, fieldName, None)
if not refs: raise IndexError()
return refs.index(obj.UID())
@ -782,7 +785,7 @@ class BaseMixin:
'''This method changes the position of object with uid p_objectUid in
reference field p_fieldName to p_newIndex i p_isDelta is False, or
to actualIndex+p_newIndex if p_isDelta is True.'''
refs = getattr(self, fieldName, None)
refs = getattr(self.aq_base, fieldName, None)
oldIndex = refs.index(objectUid)
refs.remove(objectUid)
if isDelta:
@ -1269,7 +1272,7 @@ class BaseMixin:
appyType = self.getAppyType(name)
if (not appyType.type =='File') or not appyType.isShowable(self,'view'):
return
theFile = getattr(self, name, None)
theFile = getattr(self.aq_base, name, None)
if theFile:
response = self.REQUEST.RESPONSE
response.setHeader('Content-Disposition', 'inline;filename="%s"' % \

View file

@ -1,14 +1,13 @@
<tal:comment replace="nothing">View macro for a File.</tal:comment>
<metal:view define-macro="view"
tal:define="empty python: not value or not value.size;
tal:define="info python: contextObj.getFileInfo(value);
empty not: info/size;
imageSrc string:${contextObj/absolute_url}/download?name=$name">
<tal:file condition="python: not empty and not widget['isImage']">
<img tal:define="icon value/getBestIcon"
tal:condition="icon" tal:attributes="src string: $appUrl/$icon"/>
<a tal:attributes="href imageSrc"
tal:content="value/filename">
tal:content="info/filename">
</a>&nbsp;&nbsp;-
<i class="discreet" tal:content="python:'%sKb' % (value.size / 1024)"></i>
<i class="discreet" tal:content="python:'%sKb' % (info['size'] / 1024)"></i>
</tal:file>
<tal:image condition="python: not empty and widget['isImage']">
<img tal:attributes="src python: imageSrc" />
@ -17,14 +16,17 @@
</metal:view>
<tal:comment replace="nothing">Edit macro for an File.</tal:comment>
<metal:edit define-macro="edit">
<tal:showFile condition="python: value and value.size">
<metal:edit define-macro="edit"
tal:define="info python: contextObj.getFileInfo(value);
empty not: info/size;">
<tal:showFile condition="not: empty">
<metal:call use-macro="app/skyn/widgets/file/macros/view"/><br/>
</tal:showFile>
<tal:editButtons condition="python: value and value.size">
</tal:showFile>
<tal:editButtons condition="not: empty">
<tal:comment replace="nothing">Keep the file untouched.</tal:comment>
<input type="radio" value="nochange"
tal:attributes="checked python:test(value.size!=0, 'checked', None);
tal:attributes="checked python:test(info['size']!=0, 'checked', None);
name string:${name}_delete;
id string:${name}_nochange;
onclick string:document.getElementById('${name}_file').disabled=true;"/>
@ -43,23 +45,23 @@
</tal:delete>
<tal:comment replace="nothing">Replace with a new file.</tal:comment>
<input type="radio" value=""
tal:attributes="checked python:test(value.size==0, 'checked', None);
tal:attributes="checked python:test(info['size']==0, 'checked', None);
name string:${name}_delete;
id string:${name}_upload;
onclick string:document.getElementById('${name}_file').disabled=false"/>
<label tal:attributes="for string:${name}_upload;"
i18n:translate="upload_file" i18n:domain="plone">Replace it with a new file</label>
<br/>
</tal:editButtons>
<tal:comment replace="nothing">The upload field.</tal:comment>
<input type="file"
</tal:editButtons>
<tal:comment replace="nothing">The upload field.</tal:comment>
<input type="file"
tal:attributes="name string:${name}_file;
id string:${name}_file;
size widget/width"/>
<script type="text/javascript"
tal:define="isDisabled python:test(value and value.size, 'true', 'false')"
tal:content="string: document.getElementById('${name}_file').disabled=$isDisabled;">
</script>
<script type="text/javascript"
tal:define="isDisabled python:test(empty, 'false', 'true')"
tal:content="string: document.getElementById('${name}_file').disabled=$isDisabled;">
</script>
</metal:edit>
<tal:comment replace="nothing">Cell macro for an File.</tal:comment>