[pod] When inserting an image via statement do... from document(...), parameter 'sizeUnit' can now be 'pc' (percentage): in this case, percentages are expressed as a tuple (widthPercentage, heightPercentage) in parameter 'size' and must be integers from 1 to 100. [bin] backup.py: better error handling when contacting SMTP server. [gen] Calendar widget for Date fields: bugfix (when the date range is in reverse chronological order). [gen] Ref field: added hook 'afterLink' allowing to execute a method just after an object has been linked. [gen] Ref field: added attribute 'unlinkElement' allowing to define a specific condition for unlinking a given object (before, it was only possible to define, in attribute 'unlink', a global condition allowing to unlink any object from the Ref. [gen] Bugfix: the link to the home page, when clicking on the logo, is fixed.
This commit is contained in:
parent
268309045a
commit
25f0e8184e
|
@ -172,6 +172,9 @@ class ZodbBackuper:
|
||||||
if res:
|
if res:
|
||||||
w('Could not send mail to some recipients. %s' % str(res))
|
w('Could not send mail to some recipients. %s' % str(res))
|
||||||
w('Done.')
|
w('Done.')
|
||||||
|
except smtplib.SMTPException, sme:
|
||||||
|
w('Error while contacting SMTP server %s (%s).' % \
|
||||||
|
(self.options.smtpServer, str(se)))
|
||||||
except socket.error, se:
|
except socket.error, se:
|
||||||
w('Could not connect to SMTP server %s (%s).' % \
|
w('Could not connect to SMTP server %s (%s).' % \
|
||||||
(self.options.smtpServer, str(se)))
|
(self.options.smtpServer, str(se)))
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
0.9.0
|
0.9.1
|
||||||
|
|
|
@ -267,7 +267,9 @@ class Date(Field):
|
||||||
'''Gets the Javascript init code for displaying a calendar popup for
|
'''Gets the Javascript init code for displaying a calendar popup for
|
||||||
this field, for an input named p_name (which can be different from
|
this field, for an input named p_name (which can be different from
|
||||||
self.name if, ie, it is a search field).'''
|
self.name if, ie, it is a search field).'''
|
||||||
|
# Always express the range of years in chronological order.
|
||||||
|
years = [years[0], years[-1]]
|
||||||
|
years.sort()
|
||||||
return 'Calendar.setup({inputField: "%s", button: "%s_img", ' \
|
return 'Calendar.setup({inputField: "%s", button: "%s_img", ' \
|
||||||
'onSelect: onSelectDate, range:[%d,%d]});' % \
|
'onSelect: onSelectDate, range:%s})' % (name, name, str(years))
|
||||||
(name, name, years[0], years[-1])
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
|
@ -123,7 +123,7 @@ class Ref(Field):
|
||||||
onclick=":'onDeleteObject(%s)' % q(tiedUid)"/>
|
onclick=":'onDeleteObject(%s)' % q(tiedUid)"/>
|
||||||
</td>
|
</td>
|
||||||
<!-- Unlink -->
|
<!-- Unlink -->
|
||||||
<td if="mayUnlink">
|
<td if="mayUnlink and field.mayUnlinkElement(obj, tied)">
|
||||||
<img var="imgName=linkList and 'unlinkUp' or 'unlink'; action='unlink'"
|
<img var="imgName=linkList and 'unlinkUp' or 'unlink'; action='unlink'"
|
||||||
class="clickable" title=":_('object_unlink')" src=":url(imgName)"
|
class="clickable" title=":_('object_unlink')" src=":url(imgName)"
|
||||||
onclick=":'onLink(%s,%s,%s,%s)' % (q(action), q(zobj.id), \
|
onclick=":'onLink(%s,%s,%s,%s)' % (q(action), q(zobj.id), \
|
||||||
|
@ -471,8 +471,9 @@ class Ref(Field):
|
||||||
|
|
||||||
def __init__(self, klass=None, attribute=None, validator=None,
|
def __init__(self, klass=None, attribute=None, validator=None,
|
||||||
multiplicity=(0,1), default=None, add=False, addConfirm=False,
|
multiplicity=(0,1), default=None, add=False, addConfirm=False,
|
||||||
delete=None, noForm=False, link=True, unlink=None, insert=None,
|
delete=None, noForm=False, link=True, unlink=None,
|
||||||
beforeLink=None, afterUnlink=None, back=None, show=True,
|
unlinkElement=None, insert=None, beforeLink=None,
|
||||||
|
afterLink=None, afterUnlink=None, back=None, show=True,
|
||||||
page='main', group=None, layouts=None, showHeaders=False,
|
page='main', group=None, layouts=None, showHeaders=False,
|
||||||
shownInfo=(), select=None, maxPerPage=30, move=0,
|
shownInfo=(), select=None, maxPerPage=30, move=0,
|
||||||
indexed=False, searchable=False, specificReadPermission=False,
|
indexed=False, searchable=False, specificReadPermission=False,
|
||||||
|
@ -516,6 +517,11 @@ class Ref(Field):
|
||||||
# By default, one may unlink objects via a Ref for which one can
|
# By default, one may unlink objects via a Ref for which one can
|
||||||
# link objects.
|
# link objects.
|
||||||
self.unlink = bool(self.link)
|
self.unlink = bool(self.link)
|
||||||
|
# "unlink" above is a global flag. If it is True, you can go further and
|
||||||
|
# determine, for every linked object, if it can be unlinked or not by
|
||||||
|
# defining a method in parameter "unlinkElement" below. This method
|
||||||
|
# accepts the linked object as unique arg.
|
||||||
|
self.unlinkElement = unlinkElement
|
||||||
# When an object is inserted through this Ref field, at what position is
|
# When an object is inserted through this Ref field, at what position is
|
||||||
# it inserted? If "insert" is:
|
# it inserted? If "insert" is:
|
||||||
# None, it will be inserted at the end;
|
# None, it will be inserted at the end;
|
||||||
|
@ -535,11 +541,15 @@ class Ref(Field):
|
||||||
# maintained in the order of their insertion.
|
# maintained in the order of their insertion.
|
||||||
self.insert = insert
|
self.insert = insert
|
||||||
# Immediately before an object is going to be linked via this Ref field,
|
# Immediately before an object is going to be linked via this Ref field,
|
||||||
# method specified in "beforeLink" wil be executed if specified and will
|
# method potentially specified in "beforeLink" will be executed and will
|
||||||
# take the object to link as single parameter.
|
# take the object to link as single parameter.
|
||||||
self.beforeLink = beforeLink
|
self.beforeLink = beforeLink
|
||||||
|
# Immediately after an object has been linked via this Ref field, method
|
||||||
|
# potentially specified in "afterLink" will be executed and will take
|
||||||
|
# the linked object as single parameter.
|
||||||
|
self.afterLink = afterLink
|
||||||
# Immediately after an object as been unlinked from this Ref field,
|
# Immediately after an object as been unlinked from this Ref field,
|
||||||
# method specified in "afterUnlink" will be executed if specified and
|
# method potentially specified in "afterUnlink" will be executed and
|
||||||
# will take the unlinked object as single parameter.
|
# will take the unlinked object as single parameter.
|
||||||
self.afterUnlink = afterUnlink
|
self.afterUnlink = afterUnlink
|
||||||
self.back = None
|
self.back = None
|
||||||
|
@ -937,6 +947,8 @@ class Ref(Field):
|
||||||
refs.data.sort(key=lambda uid:self.insert[1](obj, \
|
refs.data.sort(key=lambda uid:self.insert[1](obj, \
|
||||||
tool.getObject(uid, appy=True)))
|
tool.getObject(uid, appy=True)))
|
||||||
refs._p_changed = 1
|
refs._p_changed = 1
|
||||||
|
# Execute self.afterLink if present
|
||||||
|
if self.afterLink: self.afterLink(obj, value)
|
||||||
# Update the back reference
|
# Update the back reference
|
||||||
if not back: self.back.linkObject(value, obj, back=True)
|
if not back: self.back.linkObject(value, obj, back=True)
|
||||||
|
|
||||||
|
@ -945,7 +957,9 @@ class Ref(Field):
|
||||||
p_obj through this Ref field.'''
|
p_obj through this Ref field.'''
|
||||||
zobj = obj.o
|
zobj = obj.o
|
||||||
# Security check
|
# Security check
|
||||||
if not noSecurity: zobj.mayEdit(self.writePermission, raiseError=True)
|
if not noSecurity:
|
||||||
|
zobj.mayEdit(self.writePermission, raiseError=True)
|
||||||
|
self.mayUnlinkElement(obj, value, raiseError=True)
|
||||||
# p_value can be a list of objects
|
# p_value can be a list of objects
|
||||||
if type(value) in sutils.sequenceTypes:
|
if type(value) in sutils.sequenceTypes:
|
||||||
for v in value: self.unlinkObject(obj, v, back=back)
|
for v in value: self.unlinkObject(obj, v, back=back)
|
||||||
|
@ -1053,6 +1067,17 @@ class Ref(Field):
|
||||||
q(addConfirmMsg))
|
q(addConfirmMsg))
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
def mayUnlinkElement(self, obj, tied, raiseError=False):
|
||||||
|
'''May we unlink from this Ref field this specific p_tied object?'''
|
||||||
|
if not self.unlinkElement: return True
|
||||||
|
res = self.unlinkElement(obj, tied)
|
||||||
|
if res: return True
|
||||||
|
else:
|
||||||
|
if not raiseError: return
|
||||||
|
# Raise an exception.
|
||||||
|
obj.o.raiseUnauthorized('field.unlinkElement prevents you to ' \
|
||||||
|
'unlink this object.')
|
||||||
|
|
||||||
def getCbJsInit(self, obj):
|
def getCbJsInit(self, obj):
|
||||||
'''When checkboxes are enabled, this method defines a JS associative
|
'''When checkboxes are enabled, this method defines a JS associative
|
||||||
array (named "_appy_objs_cbs") that will store checkboxes' statuses.
|
array (named "_appy_objs_cbs") that will store checkboxes' statuses.
|
||||||
|
@ -1215,16 +1240,21 @@ class Ref(Field):
|
||||||
# Perform the action on every target. Count the number of failed
|
# Perform the action on every target. Count the number of failed
|
||||||
# operations.
|
# operations.
|
||||||
failed = 0
|
failed = 0
|
||||||
mustDelete = action == 'delete_many'
|
singleAction = action.split('_')[0]
|
||||||
|
mustDelete = singleAction == 'delete'
|
||||||
for target in targets:
|
for target in targets:
|
||||||
if mustDelete:
|
if mustDelete:
|
||||||
# Delete
|
# Delete
|
||||||
if target.o.mayDelete(): target.o.delete()
|
if target.o.mayDelete(): target.o.delete()
|
||||||
else: failed += 1
|
else: failed += 1
|
||||||
else:
|
else:
|
||||||
# Link or unlink
|
# Link or unlink. For unlinking, we need to perform an
|
||||||
exec 'self.%sObject(appyObj, target)' % \
|
# additional check.
|
||||||
action.split('_')[0]
|
if (singleAction == 'unlink') and \
|
||||||
|
not self.mayUnlinkElement(appyObj, target):
|
||||||
|
failed += 1
|
||||||
|
else:
|
||||||
|
exec 'self.%sObject(appyObj, target)' % singleAction
|
||||||
if failed:
|
if failed:
|
||||||
msg = obj.translate('action_partial', mapping={'nb':failed})
|
msg = obj.translate('action_partial', mapping={'nb':failed})
|
||||||
urlBack = obj.getUrl(rq['HTTP_REFERER'])
|
urlBack = obj.getUrl(rq['HTTP_REFERER'])
|
||||||
|
|
|
@ -153,7 +153,7 @@ class User(ModelClass):
|
||||||
'toTool']
|
'toTool']
|
||||||
# All methods defined below are fake. Real versions are in the wrapper.
|
# All methods defined below are fake. Real versions are in the wrapper.
|
||||||
title = gen.String(show=False, indexed=True)
|
title = gen.String(show=False, indexed=True)
|
||||||
gm = {'group': 'main', 'width': 25}
|
gm = {'group': 'main', 'width': 34}
|
||||||
def showName(self): pass
|
def showName(self): pass
|
||||||
name = gen.String(show=showName, **gm)
|
name = gen.String(show=showName, **gm)
|
||||||
firstName = gen.String(show=showName, **gm)
|
firstName = gen.String(show=showName, **gm)
|
||||||
|
|
BIN
gen/ui/space.gif
BIN
gen/ui/space.gif
Binary file not shown.
Before Width: | Height: | Size: 43 B After Width: | Height: | Size: 43 B |
|
@ -187,8 +187,8 @@ class AbstractWrapper(object):
|
||||||
style=":url(bannerName, bg=True) + '; background-repeat:no-repeat;\
|
style=":url(bannerName, bg=True) + '; background-repeat:no-repeat;\
|
||||||
position:relative'">
|
position:relative'">
|
||||||
<!-- Logo (transparent clickable zone by default) -->
|
<!-- Logo (transparent clickable zone by default) -->
|
||||||
<div align=":dleft" style="position: absolute"><a href="/">
|
<div align=":dleft" style="position: absolute">
|
||||||
<img src=":url('logo')"/></a></div>
|
<a href=":ztool.getSiteUrl()"><img src=":url('logo')"/></a></div>
|
||||||
|
|
||||||
<!-- Top links -->
|
<!-- Top links -->
|
||||||
<div style="margin-top: 4px" align=":dright">
|
<div style="margin-top: 4px" align=":dright">
|
||||||
|
|
|
@ -54,7 +54,6 @@ class BufferAction:
|
||||||
'''Gets the line describing exception p_e, containing the exception
|
'''Gets the line describing exception p_e, containing the exception
|
||||||
class, message and line number.'''
|
class, message and line number.'''
|
||||||
return '%s: %s' % (e.__class__.__name__, str(e))
|
return '%s: %s' % (e.__class__.__name__, str(e))
|
||||||
return '%s.%s: %s' % (e.__module__, e.__class__.__name__, str(e))
|
|
||||||
|
|
||||||
def manageError(self, result, context, errorMessage, dumpTb=True):
|
def manageError(self, result, context, errorMessage, dumpTb=True):
|
||||||
'''Manage the encountered error: dump it into the buffer or raise an
|
'''Manage the encountered error: dump it into the buffer or raise an
|
||||||
|
|
|
@ -383,7 +383,7 @@ class ImageImporter(DocImporter):
|
||||||
self.format = 'png'
|
self.format = 'png'
|
||||||
# Retrieve image size from self.size.
|
# Retrieve image size from self.size.
|
||||||
width = height = None
|
width = height = None
|
||||||
if self.size:
|
if self.size and (self.sizeUnit != 'pc'):
|
||||||
width, height = self.size
|
width, height = self.size
|
||||||
if self.sizeUnit == 'px':
|
if self.sizeUnit == 'px':
|
||||||
# Convert it to cm
|
# Convert it to cm
|
||||||
|
@ -397,6 +397,10 @@ class ImageImporter(DocImporter):
|
||||||
# If width and/or height is missing, compute it.
|
# If width and/or height is missing, compute it.
|
||||||
if not width or not height:
|
if not width or not height:
|
||||||
width, height = getSize(self.importPath, self.format)
|
width, height = getSize(self.importPath, self.format)
|
||||||
|
if self.sizeUnit == 'pc':
|
||||||
|
# Apply the given percentage to the real width and height.
|
||||||
|
width = width * (float(self.size[0])/100)
|
||||||
|
height = height * (float(self.size[1])/100)
|
||||||
if width != None:
|
if width != None:
|
||||||
size = ' %s:width="%fcm" %s:height="%fcm"' % (s, width, s, height)
|
size = ' %s:width="%fcm" %s:height="%fcm"' % (s, width, s, height)
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -314,7 +314,8 @@ class Renderer:
|
||||||
(width, height) expressing size in p_sizeUnit (see below).
|
(width, height) expressing size in p_sizeUnit (see below).
|
||||||
If not specified, size will be computed from image info;
|
If not specified, size will be computed from image info;
|
||||||
* p_sizeUnit is the unit for p_size elements, it can be "cm"
|
* p_sizeUnit is the unit for p_size elements, it can be "cm"
|
||||||
(centimeters) or "px" (pixels);
|
(centimeters), "px" (pixels) or "pc" (percentage). Percentages, in
|
||||||
|
p_size, must be expressed as integers from 1 to 100.
|
||||||
* if p_style is given, it is the content of a "style" attribute,
|
* if p_style is given, it is the content of a "style" attribute,
|
||||||
containing CSS attributes. If "width" and "heigth" attributes are
|
containing CSS attributes. If "width" and "heigth" attributes are
|
||||||
found there, they will override p_size and p_sizeUnit.
|
found there, they will override p_size and p_sizeUnit.
|
||||||
|
|
Loading…
Reference in a new issue