1903 lines
74 KiB
Python
1903 lines
74 KiB
Python
# -*- coding: iso-8859-15 -*-
|
|
|
|
|
|
# Glasnost
|
|
# By: Odile Bénassy <obenassy@entrouvert.com>
|
|
# Romain Chantereau <rchantereau@entrouvert.com>
|
|
# Nicolas Clapiès <nclapies@easter-eggs.org>
|
|
# Pierre-Antoine Dejace <padejace@entrouvert.be>
|
|
# Thierry Dulieu <tdulieu@easter-eggs.com>
|
|
# Florent Monnier <monnier@codelutin.com>
|
|
# Cédric Musso <cmusso@easter-eggs.org>
|
|
# Frédéric Péters <fpeters@entrouvert.be>
|
|
# Benjamin Poussin <poussin@codelutin.com>
|
|
# Emmanuel Raviart <eraviart@entrouvert.com>
|
|
# Sébastien Régnier <regnier@codelutin.com>
|
|
# Emmanuel Saracco <esaracco@easter-eggs.com>
|
|
#
|
|
# Copyright (C) 2000, 2001 Easter-eggs & Emmanuel Raviart
|
|
# Copyright (C) 2002 Odile Bénassy, Code Lutin, Thierry Dulieu, Easter-eggs,
|
|
# Entr'ouvert, Frédéric Péters, Benjamin Poussin, Emmanuel Raviart,
|
|
# Emmanuel Saracco & Théridion
|
|
# Copyright (C) 2003 Odile Bénassy, Romain Chantereau, Nicolas Clapiès,
|
|
# Code Lutin, Pierre-Antoine Dejace, Thierry Dulieu, Easter-eggs,
|
|
# Entr'ouvert, Florent Monnier, Cédric Musso, Ouvaton, Frédéric Péters,
|
|
# Benjamin Poussin, Rodolphe Quiédeville, Emmanuel Raviart, Sébastien
|
|
# Régnier, Emmanuel Saracco, Théridion & Vecam
|
|
#
|
|
# 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.
|
|
|
|
|
|
from __future__ import nested_scopes
|
|
|
|
|
|
__doc__ = """Glasnost Web Widgets"""
|
|
|
|
__version__ = '$Revision$'[11:-2]
|
|
|
|
|
|
import difflib
|
|
import locale
|
|
import re
|
|
import time
|
|
import types
|
|
import urllib
|
|
|
|
import glasnost.common.context as context
|
|
import glasnost.common.faults as faults
|
|
import glasnost.common.parsers as parsers
|
|
import glasnost.common.tools_new as commonTools
|
|
import glasnost.common.xhtmlgenerator as X
|
|
|
|
import glasnost.proxy.widgets as proxyWidgets
|
|
|
|
import kinds
|
|
import properties
|
|
import things
|
|
|
|
import calendaring
|
|
from tools import *
|
|
import translation
|
|
|
|
|
|
register = things.register
|
|
helpTextRegEx = re.compile(r'\[(\S+)->(\S+)\]')
|
|
|
|
|
|
class WidgetMixin(things.ThingMixin):
|
|
def fillModelFieldChildrenLayout(self, slot, fields, layout, **keywords):
|
|
label = self.getHtmlFieldLabel(slot)
|
|
layout += label
|
|
balloonHelp = slot.getKind().balloonHelp
|
|
if balloonHelp and not self.isReadOnly(slot):
|
|
helpMode = context.getVar('helpMode')
|
|
if helpMode == 'none':
|
|
regEx = r'\1'
|
|
elif helpMode == 'local':
|
|
regEx = r'<a href="/help/\2">\1</a>'
|
|
elif helpMode == 'internet':
|
|
regEx = r'<a href="http://glasnost.entrouvert.org/help/\2">\1</a>'
|
|
layout += X.div(_class = 'formHelp')(X.asIs(
|
|
helpTextRegEx.sub(regEx, _(balloonHelp))))
|
|
cell = self.getHtmlFieldValue(slot, fields, **keywords)
|
|
if cell is not None:
|
|
if isinstance(cell, X.array):
|
|
tooltipCell = [x for x in cell.children if x][0]
|
|
else:
|
|
tooltipCell = cell
|
|
if self.colSpan:
|
|
cell.setAttribute('class', ' '.join(
|
|
[cell.getAttribute('class'), 'fullwidth']))
|
|
|
|
if slot.getObject().getError(slot.getPath()) and \
|
|
not context.getVar('hideErrors'):
|
|
layout.setAttribute('class', ' '.join(
|
|
[layout.getAttribute('class'), 'error']))
|
|
layout += self.getModelErrorLayout(slot, fields)
|
|
layout += cell
|
|
|
|
def getHtmlColumnLabel(self, slot):
|
|
label = self.getModelLabel(slot)
|
|
return X.th(scope = 'col')(_(label))
|
|
|
|
def getHtmlColumnValue(self, slot, fields, **keywords):
|
|
tdAttributes = {}
|
|
return X.td(**tdAttributes)(
|
|
self.getHtmlValue(slot, fields, **keywords))
|
|
|
|
def getHtmlCompactValue(self, slot, fields, **keywords):
|
|
# We have to enclose the field value in a tag with class 'cell' but we
|
|
# want a nice markup so we can't simply <div class="cell"> v </div> and
|
|
# go away with this.
|
|
return X.enclose(self.getHtmlValue(slot, fields, **keywords),
|
|
_class = 'compact-value')
|
|
|
|
def getHtmlFieldLabel(self, slot):
|
|
label = self.getModelLabel(slot)
|
|
|
|
# Disabled since <label> caused some problems (with Mozilla 1.0?)
|
|
# labelAttributes = {'for': slot.getFieldName()}
|
|
#
|
|
# Seen on css-discuss:
|
|
# > This will, however cause a problem with Netscape 6 (7 is fine),
|
|
# > wherein the floated labels will not be visible. To fix that,
|
|
# > unfortunately you have to put the labels inside spans and float the
|
|
# > spans instead.
|
|
#
|
|
# if self.isInForm():
|
|
# if slot.getKind().isRequired and self.isInForm() \
|
|
# and not self.isReadOnly(slot):
|
|
# labelAttributes['class'] = 'required'
|
|
# return X.label(**labelAttributes)(_(label), X.asIs(_(':') + ' '))
|
|
|
|
label = X.span(_class = 'label')(
|
|
X.label(_for = slot.getFieldName())(
|
|
_(label), X.asIs(_(':') + ' ')) )
|
|
|
|
if slot.getKind().isRequired and self.isInForm() \
|
|
and not self.isReadOnly(slot):
|
|
return X.array(label,
|
|
X.span(_class = 'fieldRequired',
|
|
title = _('Required'))(_('(Required)')))
|
|
return label
|
|
|
|
def getHtmlFieldValue(self, slot, fields, **keywords):
|
|
# We have to enclose the field value in a tag with class 'cell' but we
|
|
# want a nice markup so we can't simply <div class="cell"> v </div> and
|
|
# go away with this.
|
|
return X.enclose(self.getHtmlValue(slot, fields, **keywords),
|
|
_class = 'cell')
|
|
|
|
def getHtmlValue(self, slot, fields, **keywords):
|
|
# FIXME: To rename to getModelFieldValueChildrenLayout?
|
|
if not self.isInForm():
|
|
return self.getHtmlViewValue(slot, fields, **keywords)
|
|
elif self.isReadOnly(slot):
|
|
return self.getHtmlReadOnlyValue(slot, fields, **keywords)
|
|
else:
|
|
return self.getHtmlFormValue(slot, fields, **keywords)
|
|
|
|
def getHtmlViewDiffValue(self, oldSlot, newSlot, **keywords):
|
|
return X.table(_class = 'diff')(
|
|
X.td(self.getHtmlViewValue(oldSlot, None, **keywords)),
|
|
X.td(self.getHtmlViewValue(newSlot, None, **keywords)) )
|
|
|
|
def getHtmlViewValue(self, slot, fields, **keywords):
|
|
fieldValue = slot.getValue() or ''
|
|
format = slot.getKind().getTextFormat(slot)
|
|
if format == 'html':
|
|
formattedText = parsers.makeHtmlFromHtml(fieldValue, inline = 1)
|
|
elif format == 'text':
|
|
formattedText = parsers.makeHtmlFromPreformattedText(
|
|
fieldValue, inline = 1)
|
|
elif format == 'rst':
|
|
formattedText = parsers.makeHtmlFromReStructuredText(
|
|
fieldValue, inline = 1)
|
|
elif format == 'spip':
|
|
formattedText = parsers.makeHtmlFromSpip(fieldValue, inline = 1)
|
|
else:
|
|
formattedText = parsers.makeHtmlFromUnformattedText(
|
|
fieldValue, inline = 1)
|
|
formattedText = replaceSpecialTags(formattedText)
|
|
return X.asIs(formattedText)
|
|
|
|
def getHtmlReadOnlyValue(self, slot, fields, **keywords):
|
|
return X.array(
|
|
self.getModelHiddenLayout(slot, fields),
|
|
self.getHtmlViewValue(slot, fields, **keywords) )
|
|
|
|
def getHtmlFormValue(self, slot, fields, **keywords):
|
|
fieldName = slot.getFieldName()
|
|
fieldValue = slot.getValue() or ''
|
|
layout = X.array()
|
|
layout += self.getModelErrorLayout(slot, fields)
|
|
inputAttributes = {}
|
|
layout += X.input(name = fieldName, type = 'text',
|
|
value = fieldValue, **inputAttributes)
|
|
return layout
|
|
|
|
def getModelErrorLayout(self, slot, fields):
|
|
if context.getVar('hideErrors'):
|
|
return None
|
|
try:
|
|
error = slot.getObject().getError(slot.getPath())
|
|
except (TypeError, IndexError, AttributeError):
|
|
error = None
|
|
if error:
|
|
return X.div(_class = 'field-error-message')(
|
|
_(error.uiFaultString))
|
|
return None
|
|
|
|
def getModelFieldLayout(self, slot, fields, **keywords):
|
|
kind = slot.getKind()
|
|
tagName = kind.getModelFieldTag(slot)
|
|
if tagName == 'div-with-label':
|
|
layout = X.div(_class = 'field',
|
|
id = 'field-%s' % slot.getFieldName())
|
|
self.fillModelFieldChildrenLayout(slot, fields, layout, **keywords)
|
|
return layout
|
|
else:
|
|
tagClass = getattr(X, tagName)
|
|
fieldName = slot.getFieldName()
|
|
level = 'getModelFieldLayout %s' % fieldName
|
|
context.push(_level = level, inline = tagClass.inlineElements)
|
|
try:
|
|
childrenLayout = self.getHtmlValue(slot, fields, **keywords)
|
|
finally:
|
|
context.pull(_level = level)
|
|
if not childrenLayout:
|
|
return None
|
|
return tagClass(id = 'field-%s' % fieldName)(childrenLayout)
|
|
|
|
def getModelHiddenLayout(self, slot, fields):
|
|
fieldName = slot.getFieldName()
|
|
value = slot.getValue()
|
|
if value is None:
|
|
value = ''
|
|
if type(value) is not types.StringType:
|
|
value = slot.getKind().convertValueToOtherType(
|
|
value, types.StringType)
|
|
return X.input(name = fieldName, type = 'hidden', value = value)
|
|
|
|
def getModelPageBodyLayout(self, slot, fields):
|
|
layoutMode = context.getVar('layoutMode')
|
|
if layoutMode != 'edit':
|
|
layout = self.getHtmlViewValue(slot, fields)
|
|
elif self.isReadOnly(slot):
|
|
layout = self.getHtmlReadOnlyValue(slot, fields)
|
|
else:
|
|
layout = self.getHtmlFormValue(slot, fields)
|
|
return layout
|
|
|
|
def submitEmbedded(self, slot, fields):
|
|
kind = slot.getKind()
|
|
parentSlot, value = kind.getCreatedModelSlotAndValue(slot)
|
|
value.submitFields(fields, parentSlot = parentSlot)
|
|
return value
|
|
|
|
def submit(self, slot, fields):
|
|
return slot.getField(fields) or None
|
|
|
|
|
|
class ExclusiveChoiceMixin(WidgetMixin):
|
|
def getHtmlViewValue(self, slot, fields, **keywords):
|
|
kind = slot.getKind()
|
|
value = slot.getValue() or ''
|
|
valueAsString = kind.getModelValueAsString(value)
|
|
labels = self.getLabels(slot)
|
|
if labels.has_key(valueAsString):
|
|
return self.makeModelTitleFromValue(slot, fields, value)
|
|
elif value == '__all__':
|
|
return _(self.allLabel)
|
|
else:
|
|
return _(self.noneLabel)
|
|
|
|
def makeModelTitleFromValue(self, slot, fields, value):
|
|
kind = slot.getKind()
|
|
valueAsString = kind.getModelValueAsString(value)
|
|
layoutMode = context.getVar('layoutMode')
|
|
if layoutMode != 'edit':
|
|
if self.titles and self.titles.has_key(valueAsString):
|
|
return _(self.titles[valueAsString])
|
|
title = kind.makeModelTitleFromValue(slot, fields, value)
|
|
if title:
|
|
return title
|
|
labels = self.getLabels(slot)
|
|
if labels and labels.has_key(valueAsString):
|
|
return _(labels[valueAsString])
|
|
return None
|
|
|
|
|
|
class InputTextMixin(WidgetMixin):
|
|
def getHtmlViewValue(self, slot, fields, **keywords):
|
|
fieldValue, translationBar = \
|
|
translation.getFieldValueAndTranslationBar(slot)
|
|
if not fieldValue:
|
|
fieldValue = ''
|
|
|
|
format = slot.getKind().getTextFormat(slot)
|
|
if format == 'html':
|
|
formattedText = parsers.makeHtmlFromHtml(fieldValue, inline = 1)
|
|
elif format == 'text':
|
|
formattedText = parsers.makeHtmlFromPreformattedText(
|
|
fieldValue, inline = 1)
|
|
elif format == 'rst':
|
|
formattedText = parsers.makeHtmlFromReStructuredText(
|
|
fieldValue, inline = 1)
|
|
elif format == 'spip':
|
|
formattedText = parsers.makeHtmlFromSpip(fieldValue, inline = 1)
|
|
else:
|
|
formattedText = parsers.makeHtmlFromUnformattedText(
|
|
fieldValue, inline = 1)
|
|
formattedText = replaceSpecialTags(formattedText)
|
|
|
|
layout = X.asIs(formattedText)
|
|
|
|
if translationBar:
|
|
layout = X.array(layout, translationBar)
|
|
|
|
return layout
|
|
|
|
def getHtmlReadOnlyValue(self, slot, fields, **keywords):
|
|
fieldValue = slot.getValue() or ''
|
|
|
|
if type(fieldValue) is not types.StringType:
|
|
fieldValue = slot.getKind().convertValueToOtherType(fieldValue,
|
|
types.StringType)
|
|
|
|
format = slot.getKind().getTextFormat(slot)
|
|
if format == 'html':
|
|
formattedText = parsers.makeHtmlFromHtml(fieldValue, inline = 1)
|
|
elif format == 'text':
|
|
formattedText = parsers.makeHtmlFromPreformattedText(
|
|
fieldValue, inline = 1)
|
|
elif format == 'rst':
|
|
formattedText = parsers.makeHtmlFromReStructuredText(
|
|
fieldValue, inline = 1)
|
|
elif format == 'spip':
|
|
formattedText = parsers.makeHtmlFromSpip(fieldValue, inline = 1)
|
|
else:
|
|
formattedText = parsers.makeHtmlFromUnformattedText(
|
|
fieldValue, inline = 1)
|
|
formattedText = replaceSpecialTags(formattedText)
|
|
|
|
return X.array(
|
|
self.getModelHiddenLayout(slot, fields),
|
|
X.asIs(formattedText))
|
|
|
|
def getHtmlFormValue(self, slot, fields, **keywords):
|
|
fieldName = slot.getFieldName()
|
|
fieldValue = slot.getValue()
|
|
|
|
if type(fieldValue) is not types.StringType:
|
|
fieldValue = slot.getKind().convertValueToOtherType(fieldValue,
|
|
types.StringType)
|
|
|
|
layout = X.array()
|
|
#layout += self.getModelErrorLayout(slot, fields)
|
|
|
|
inputAttributes = {}
|
|
maxLength = slot.getKind().getTextMaxLength()
|
|
if maxLength is not None:
|
|
inputAttributes['maxlength'] = maxLength
|
|
if self.size is not None:
|
|
size = self.size
|
|
elif maxLength is not None:
|
|
size = min(80, maxLength)
|
|
else:
|
|
size = None
|
|
if size is not None:
|
|
inputAttributes['size'] = size
|
|
layout += X.input(name = fieldName, type = 'text',
|
|
value = fieldValue, **inputAttributes)
|
|
if self.apply:
|
|
layout += ' '
|
|
layout += X.buttonInForm('apply', 'applyButton')
|
|
return layout
|
|
|
|
def submit(self, slot, fields):
|
|
value = WidgetMixin.submit(self, slot, fields)
|
|
if value is None:
|
|
return None
|
|
value = value.replace('\r\n', '\n')
|
|
value = value.replace(
|
|
'\x91', "'").replace('\x92', "'").replace(
|
|
'\x93', "'").replace('\x94', "'").replace(
|
|
'\x81', "'").replace('\x82', "'").replace(
|
|
'’', "'").replace('…', '...').replace(
|
|
'–', '--').replace('“', '"').replace(
|
|
'´', "'").replace('”', '"').replace(
|
|
'‘', "'")
|
|
return value
|
|
|
|
|
|
class ThingMixin(WidgetMixin):
|
|
def getHtmlValue(self, slot, fields, **keywords):
|
|
kind = slot.getKind()
|
|
parentSlot, value = kind.getCreatedModelSlotAndValue(slot)
|
|
if not self.isInForm():
|
|
layout = X.div(value.getFieldValueChildrenViewLayout(
|
|
fields, parentSlot = parentSlot))
|
|
elif self.isReadOnly(slot):
|
|
layout = X.array(
|
|
value.getHiddenLayout(fields, parentSlot = parentSlot),
|
|
X.div(value.getFieldValueChildrenViewLayout(
|
|
fields, parentSlot = parentSlot)))
|
|
else:
|
|
layout = X.array(
|
|
self.getModelErrorLayout(slot, fields),
|
|
X.div(value.getFieldValueChildrenEditLayout(
|
|
fields, parentSlot = parentSlot)))
|
|
return layout
|
|
|
|
def getModelPageBodyLayout(self, slot, fields):
|
|
kind = slot.getKind()
|
|
parentSlot, value = kind.getCreatedModelSlotAndValue(slot)
|
|
layoutMode = context.getVar('layoutMode')
|
|
if layoutMode == 'edit':
|
|
layout = value.getEditLayout(fields, parentSlot = parentSlot)
|
|
else:
|
|
layout = value.getViewLayout(fields, parentSlot = parentSlot)
|
|
return layout
|
|
|
|
def submit(self, slot, fields):
|
|
kind = slot.getKind()
|
|
parentSlot, value = kind.getCreatedModelSlotAndValue(slot)
|
|
value.submitFields(fields, parentSlot)
|
|
return value
|
|
|
|
|
|
class TimeMixin(InputTextMixin):
|
|
pass
|
|
|
|
|
|
class BaseWidget(WidgetMixin, proxyWidgets.BaseWidget):
|
|
pass
|
|
register(BaseWidget)
|
|
|
|
|
|
class Duration(WidgetMixin, proxyWidgets.Duration):
|
|
partLabels = {
|
|
'day' : N_('day'),
|
|
'hour' : N_('hour'),
|
|
'minute' : N_('minute'),
|
|
'second' : N_('second'),
|
|
}
|
|
|
|
def getHtmlViewValue(self, slot, fields, **keywords):
|
|
secondFieldValue = slot.getFieldOption(fields, 'second', default = 0)
|
|
minuteFieldValue = slot.getFieldOption(fields, 'minute', default = 0)
|
|
hourFieldValue = slot.getFieldOption(fields, 'hour', default = 0)
|
|
dayFieldValue = slot.getFieldOption(fields, 'day', default = 0)
|
|
|
|
partsToDisplay = slot.getKind().requiredParts
|
|
layout = X.array()
|
|
for partName in partsToDisplay:
|
|
partValue = locals()['%sFieldValue' % partName]
|
|
if partValue:
|
|
layout += X.asIs(partValue)
|
|
layout += X.nbsp
|
|
if partValue == 1:
|
|
layout += X.asIs('%s' % _(self.partLabels[partName]))
|
|
else:
|
|
layout += X.asIs('%ss' % _(self.partLabels[partName]))
|
|
layout += X.nbsp
|
|
return layout
|
|
|
|
def getHtmlFormValue(self, slot, fields, **keywords):
|
|
secondFieldName = slot.getFieldOptionName('second')
|
|
minuteFieldName = slot.getFieldOptionName('minute')
|
|
hourFieldName = slot.getFieldOptionName('hour')
|
|
dayFieldName = slot.getFieldOptionName('day')
|
|
|
|
secondFieldValue = slot.getFieldOption(fields, 'second', default = 0)
|
|
minuteFieldValue = slot.getFieldOption(fields, 'minute', default = 0)
|
|
hourFieldValue = slot.getFieldOption(fields, 'hour', default = 0)
|
|
dayFieldValue = slot.getFieldOption(fields, 'day', default = 0)
|
|
|
|
partsToDisplay = slot.getKind().requiredParts
|
|
|
|
layout = X.array()
|
|
|
|
for partName in partsToDisplay:
|
|
layout += X.input(maxlength = 3,
|
|
name = locals()['%sFieldName' % partName],
|
|
size = 3, type = 'text',
|
|
value = locals()['%sFieldValue' % partName])
|
|
layout += X.nbsp
|
|
layout += X.asIs('%ss' % _(self.partLabels[partName]))
|
|
layout += X.nbsp
|
|
return layout
|
|
|
|
def getModelHiddenLayout(self, slot, fields):
|
|
secondFieldName = slot.getFieldOptionName('second')
|
|
minuteFieldName = slot.getFieldOptionName('minute')
|
|
hourFieldName = slot.getFieldOptionName('hour')
|
|
dayFieldName = slot.getFieldOptionName('day')
|
|
|
|
secondFieldValue = slot.getFieldOption(fields, 'second', default = 0)
|
|
minuteFieldValue = slot.getFieldOption(fields, 'minute', default = 0)
|
|
hourFieldValue = slot.getFieldOption(fields, 'hour', default = 0)
|
|
dayFieldValue = slot.getFieldOption(fields, 'day', default = 0)
|
|
|
|
return X.array(
|
|
X.input(name = secondFieldName, type = 'hidden',
|
|
value = secondFieldValue),
|
|
X.input(name = minuteFieldName, type = 'hidden',
|
|
value = minuteFieldValue),
|
|
X.input(name = hourFieldName, type = 'hidden',
|
|
value = hourFieldValue),
|
|
X.input(name = dayFieldName, type = 'hidden',
|
|
value = dayFieldValue),
|
|
)
|
|
|
|
def submit(self, slot, fields):
|
|
factors = {
|
|
'second' : 1,
|
|
'minute' : 60,
|
|
'hour' : 60*60,
|
|
'day' : 24*60*60
|
|
}
|
|
try:
|
|
return reduce(lambda x,y:x+y,
|
|
[int(slot.getFieldOption(
|
|
fields, z, default = '0')) * factors[z]
|
|
for z in factors.keys()] )
|
|
except: # should be tighter
|
|
raise faults.BadValue()
|
|
register(Duration)
|
|
|
|
|
|
class Email(WidgetMixin, proxyWidgets.Email):
|
|
def getHtmlViewValue(self, slot, fields, **keywords):
|
|
fieldValue = slot.getValue()
|
|
if fieldValue:
|
|
fieldValueMailTo = fieldValue.replace('@', '%40')
|
|
fieldValueHtml = fieldValue.replace('@', ' [at] ')
|
|
return X.a(href = 'mailto:%s' % fieldValueMailTo)(
|
|
fieldValueHtml)
|
|
else:
|
|
return X.asIs(_('undefined'))
|
|
|
|
def getHtmlFormValue(self, slot, fields, **keywords):
|
|
fieldName = slot.getFieldName()
|
|
fieldValue = slot.getValue() or ''
|
|
|
|
layout = X.array()
|
|
|
|
inputAttributes = {}
|
|
maxLength = slot.getKind().getTextMaxLength()
|
|
if maxLength is not None:
|
|
inputAttributes['maxlength'] = maxLength
|
|
if self.size is not None:
|
|
size = self.size
|
|
elif maxLength is not None:
|
|
size = min(80, maxLength)
|
|
else:
|
|
size = None
|
|
if size is not None:
|
|
inputAttributes['size'] = size
|
|
layout += X.input(name = fieldName, type = 'text',
|
|
value = fieldValue, **inputAttributes)
|
|
if self.apply:
|
|
layout += ' '
|
|
layout += X.buttonInForm('apply', 'applyButton')
|
|
return layout
|
|
register(Email)
|
|
|
|
|
|
class InputCheckBox(WidgetMixin, proxyWidgets.InputCheckBox):
|
|
def getHtmlViewValue(self, slot, fields, **keywords):
|
|
kind = slot.getKind()
|
|
value = slot.getValue()
|
|
return self.makeModelTitleFromValue(slot, fields, value)
|
|
|
|
def getHtmlFormValue(self, slot, fields, **keywords):
|
|
fieldName = slot.getFieldName()
|
|
kind = slot.getKind()
|
|
value = slot.getValue() or 0
|
|
|
|
layout = X.array()
|
|
inputAttributes = {}
|
|
if value:
|
|
inputAttributes['checked'] = 'checked'
|
|
trueValue = kind.getValues(slot)[1]
|
|
layout += X.input(
|
|
_class = 'checkbox', name = fieldName, type = 'checkbox',
|
|
value = kind.getModelValueAsString(trueValue),
|
|
**inputAttributes)
|
|
layout += X.nbsp
|
|
labels = self.getLabels(slot)
|
|
label = labels[kind.getModelValueAsString(trueValue)]
|
|
layout += _(label)
|
|
if self.apply:
|
|
layout += ' '
|
|
layout += X.buttonInForm('apply', 'applyButton')
|
|
return layout
|
|
|
|
def makeModelTitleFromValue(self, slot, fields, value):
|
|
kind = slot.getKind()
|
|
valueAsString = kind.getModelValueAsString(value)
|
|
layoutMode = context.getVar('layoutMode')
|
|
if layoutMode != 'edit':
|
|
if self.titles and self.titles.has_key(valueAsString):
|
|
return _(self.titles[valueAsString])
|
|
title = kind.makeModelTitleFromValue(slot, fields, value)
|
|
if title:
|
|
return title
|
|
labels = self.getLabels(slot)
|
|
if labels and labels.has_key(valueAsString):
|
|
return _(labels[valueAsString])
|
|
return None
|
|
|
|
def submit(self, slot, fields):
|
|
value = WidgetMixin.submit(self, slot, fields)
|
|
if value is None:
|
|
value = 0
|
|
return int(value)
|
|
register(InputCheckBox)
|
|
|
|
|
|
class InputPassword(WidgetMixin, proxyWidgets.InputPassword):
|
|
def getHtmlViewValue(self, slot, fields, **keywords):
|
|
fieldValue = slot.getValue() or ''
|
|
cryptedValue = '*' * len(fieldValue)
|
|
return cryptedValue
|
|
|
|
def getHtmlFormValue(self, slot, fields, **keywords):
|
|
fieldName = slot.getFieldName()
|
|
fieldValue = slot.getValue() or ''
|
|
|
|
layout = X.array()
|
|
|
|
inputAttributes = {}
|
|
maxLength = slot.getKind().getTextMaxLength()
|
|
if maxLength is not None:
|
|
inputAttributes['maxlength'] = maxLength
|
|
if self.size is not None:
|
|
size = self.size
|
|
elif maxLength is not None:
|
|
size = min(80, maxLength)
|
|
else:
|
|
size = None
|
|
if size is not None:
|
|
inputAttributes['size'] = size
|
|
layout += X.input(name = fieldName, type = 'password',
|
|
value = fieldValue, **inputAttributes)
|
|
if self.apply:
|
|
layout += ' '
|
|
layout += X.buttonInForm('apply', 'applyButton')
|
|
return layout
|
|
register(InputPassword)
|
|
|
|
|
|
class InputText(InputTextMixin, proxyWidgets.InputText):
|
|
pass
|
|
register(InputText)
|
|
|
|
|
|
class Link(WidgetMixin, proxyWidgets.Link):
|
|
def getHtmlViewValue(self, slot, fields, **keywords):
|
|
nameFieldValue = slot.getFieldOption(fields, 'name', default = '')
|
|
urlFieldValue = slot.getFieldOption(fields, 'url', default = '')
|
|
|
|
nameFieldValue, translationBar = \
|
|
translation.getFieldValueAndTranslationBar(slot, fields,
|
|
fieldValue = nameFieldValue)
|
|
|
|
if urlFieldValue.startswith('glasnost://'):
|
|
url = X.idUrl(urlFieldValue)
|
|
else:
|
|
url = urlFieldValue
|
|
layout = X.a(href = url)(nameFieldValue)
|
|
|
|
if translationBar:
|
|
layout = X.array(layout, translationBar)
|
|
|
|
return layout
|
|
|
|
def getHtmlReadOnlyValue(self, slot, fields, **keywords):
|
|
nameFieldValue = slot.getFieldOption(fields, 'name', default = '')
|
|
urlFieldValue = slot.getFieldOption(fields, 'url', default = '')
|
|
return X.array(
|
|
self.getModelHiddenLayout(slot, fields),
|
|
X.a(href = X.absoluteUrl(urlFieldValue))(nameFieldValue))
|
|
|
|
def getHtmlFormValue(self, slot, fields, **keywords):
|
|
nameFieldName = slot.getFieldOptionName('name')
|
|
urlFieldName = slot.getFieldOptionName('url')
|
|
nameFieldValue = slot.getFieldOption(fields, 'name', default = '')
|
|
urlFieldValue = slot.getFieldOption(fields, 'url', default = '')
|
|
|
|
layout = X.array()
|
|
layout += X.table(
|
|
X.tr(
|
|
X.td(_class = 'field-label')(_('Title'), X.asIs(_(':') + \
|
|
' ')),
|
|
X.td(X.input(
|
|
maxlength = 80, name = nameFieldName, size = 80,
|
|
type = 'text', value = nameFieldValue))),
|
|
X.tr(
|
|
X.td(_class = 'field-label')(_('URL'), X.asIs(_(':') + \
|
|
' ')),
|
|
X.td(X.input(
|
|
maxlength = 80, name = urlFieldName, size = 80,
|
|
type = 'text', value = urlFieldValue))),
|
|
)
|
|
return layout
|
|
|
|
def getModelHiddenLayout(self, slot, fields):
|
|
nameFieldName = slot.getFieldOptionName('name')
|
|
urlFieldName = slot.getFieldOptionName('url')
|
|
nameFieldValue = slot.getFieldOption(fields, 'name', default = '')
|
|
urlFieldValue = slot.getFieldOption(fields, 'url', default = '')
|
|
return X.array(
|
|
X.input(name = nameFieldName, type = 'hidden',
|
|
value = nameFieldValue),
|
|
X.input(name = urlFieldName, type = 'hidden',
|
|
value = urlFieldValue),
|
|
)
|
|
|
|
def submit(self, slot, fields):
|
|
return (slot.getFieldOption(fields, 'name', default = ''),
|
|
slot.getFieldOption(fields, 'url', default = '') )
|
|
register(Link)
|
|
|
|
|
|
class Mapping(WidgetMixin, proxyWidgets.Mapping):
|
|
def getHtmlValue(self, slot, fields, **keywords):
|
|
kind = slot.getKind()
|
|
countName = slot.getFieldOptionName('count')
|
|
count = kind.getItemsCount(slot, fields)
|
|
layout = X.array()
|
|
fieldset = X.div(_class = 'fieldset')
|
|
layout += fieldset
|
|
if self.isInForm():
|
|
layout += X.input(name = countName, type = 'hidden', value = count)
|
|
for i in range(count):
|
|
keySlot = kind.getItemKeySlot(slot, i)
|
|
keyWidget = keySlot.getWidget()
|
|
if keyWidget is None:
|
|
raise Exception('Missing key widget for %s in %s' % (
|
|
slot.getPath(), str(keySlot.getKind().__dict__)))
|
|
valueSlot = kind.getItemKeyValueSlot(keySlot)
|
|
valueWidget = kind.valueKind.getModelWidget(valueSlot)
|
|
if valueWidget is None:
|
|
raise Exception('Missing value widget for %s in %s' % (
|
|
slot.getPath(), str(valueSlot.getKind().__dict__)))
|
|
fieldset += X.div(_class = 'field',
|
|
id = 'field-%s' % slot.getFieldName())(
|
|
keyWidget.getHtmlFieldValue(keySlot, fields),
|
|
valueWidget.getHtmlFieldValue(valueSlot, fields))
|
|
if self.isInForm() and not self.isReadOnly(slot):
|
|
if kind.canAddItem(slot, fields):
|
|
addButtonName = slot.getFieldOptionName('addButton')
|
|
layout += X.buttonInForm('add', addButtonName)
|
|
if self.apply:
|
|
layout += X.buttonInForm('apply', 'applyButton')
|
|
return layout
|
|
|
|
def getModelHiddenLayout(self, slot, fields):
|
|
countName = slot.getFieldOptionName('count')
|
|
count = slot.getKind().fieldsCountMin
|
|
try:
|
|
count = max(count, int(slot.getFieldOption(
|
|
fields, 'count', default = '0')))
|
|
except ValueError:
|
|
pass
|
|
layout = X.array()
|
|
for i in range(count):
|
|
keySlot = slot.getKind().getItemKeySlot(slot, i)
|
|
keyWidget = keySlot.getWidget()
|
|
if keyWidget is None:
|
|
raise Exception('Missing key widget for %s in %s' % (
|
|
slot.getPath(), str(keySlot.getKind().__dict__)))
|
|
layout += keyWidget.getModelHiddenLayout(keySlot, fields)
|
|
valueSlot = slot.getKind().getItemKeyValueSlot(keySlot)
|
|
valueWidget = valueSlot.getWidget()
|
|
if valueWidget is None:
|
|
raise Exception('Missing value widget for %s in %s' % (
|
|
slot.getPath(), str(valueSlot.getKind().__dict__)))
|
|
layout += valueWidget.getModelHiddenLayout(valueSlot, fields)
|
|
return layout
|
|
|
|
def submit(self, slot, fields):
|
|
count = slot.getKind().fieldsCountMin
|
|
try:
|
|
count = max(count,
|
|
int(slot.getFieldOption(fields, 'count', default = '0')))
|
|
except ValueError:
|
|
pass
|
|
|
|
value = {}
|
|
for i in range(count):
|
|
keySlot = slot.getKind().getItemKeySlot(slot, i)
|
|
try:
|
|
keyKind = keySlot.getKind()
|
|
keyValue = keySlot.getWidget().submit(keySlot, fields)
|
|
if keyValue is None:
|
|
continue
|
|
if type(keyValue) != keyKind.pythonStorageType:
|
|
keyValue = keyKind.convertValueFromOtherType(keyValue)
|
|
if keyKind.isEmptyModelValue(keySlot, keyValue):
|
|
continue
|
|
keyKind.checkModelValue(keySlot, keyValue)
|
|
except faults.BaseFault, f:
|
|
slot.getObject().setError(keySlot.getPath(), f)
|
|
|
|
itemSlot = slot.getKind().getItemKeyValueSlot(keySlot)
|
|
try:
|
|
itemKind = itemSlot.getKind()
|
|
itemValue = itemSlot.getWidget().submit(itemSlot, fields)
|
|
if itemValue is None and kind.deleteNullValues:
|
|
continue
|
|
if type(itemValue) != itemKind.pythonStorageType:
|
|
itemValue = itemKind.convertValueFromOtherType(itemValue)
|
|
if itemKind.isEmptyModelValue(itemSlot, itemValue) and \
|
|
kind.deleteNullValues:
|
|
continue
|
|
except faults.BaseFault, f:
|
|
slot.getObject().setError(itemSlot.getPath(), f)
|
|
|
|
value[keyValue] = itemValue
|
|
|
|
addButtonName = slot.getFieldOptionName('addButton')
|
|
if isButtonSelected(addButtonName, fields):
|
|
# TODO: fill with default value
|
|
count = count + 1
|
|
slot.setFieldOption(fields, 'count', str(count))
|
|
context.setVar('again', 1)
|
|
context.setVar('hideErrors', 1)
|
|
return value
|
|
register(Mapping)
|
|
|
|
|
|
class Multi(WidgetMixin, proxyWidgets.Multi):
|
|
def getHtmlViewValue(self, slot, fields, **keywords):
|
|
kind = slot.getKind()
|
|
layout = X.ul(_class = 'multi')
|
|
value = slot.getValue() or []
|
|
|
|
for i, v in zip(range(len(value)), value):
|
|
itemSlot = kind.getItemSlot(slot, i)
|
|
itemWidget = itemSlot.getWidget()
|
|
if kind.isLabelImportant(slot):
|
|
layout += X.li(itemWidget.getModelFieldLayout(
|
|
itemSlot, fields))
|
|
else:
|
|
layout += X.li(itemWidget.getHtmlValue(itemSlot, fields))
|
|
return layout
|
|
|
|
def getHtmlFormValue(self, slot, fields, **keywords):
|
|
kind = slot.getKind()
|
|
countName = slot.getFieldOptionName('count')
|
|
count = kind.getItemsCount(slot, fields)
|
|
value = slot.getValue() or []
|
|
if value:
|
|
count = max(count, len(value))
|
|
if count == 0:
|
|
count = 1
|
|
layout = X.array()
|
|
|
|
changed = 0
|
|
while len(value) < kind.getMinCount(slot) or 0:
|
|
itemSlot = kind.getItemSlot(slot, 0)
|
|
value.append(itemSlot.getKind().getDefaultValue(itemSlot))
|
|
changed = 1
|
|
if changed:
|
|
slot.setValue(value)
|
|
|
|
if self.inline:
|
|
fieldset = X.ul(_class = 'multi inline')
|
|
else:
|
|
fieldset = X.ul(_class = 'multi')
|
|
|
|
layout += X.input(name = countName, type = 'hidden', value = count)
|
|
layout += X.div(fieldset)
|
|
|
|
webTools.addContextualHeader('jsform')
|
|
|
|
for i in range(count):
|
|
itemSlot = kind.getItemSlot(slot, i)
|
|
itemWidget = itemSlot.getWidget()
|
|
if itemWidget is None:
|
|
raise Exception('Missing item widget for %s in %s' % (
|
|
slot.getPath(), str(itemSlot.getKind().__dict__)))
|
|
if kind.isLabelImportant(slot):
|
|
fieldset += X.li(itemWidget.getModelFieldLayout(
|
|
itemSlot, fields))
|
|
else:
|
|
childWidget = X.array(
|
|
itemWidget.getHtmlValue(itemSlot, fields))
|
|
if count > 1 and self.reorderingButtons:
|
|
childWidget.append(
|
|
X.button(type = 'button',
|
|
onclick = 'moveItemUp(this.parentNode)')(
|
|
X.asIs('↑')))
|
|
#if i == 0:
|
|
# childWidget.children[-1].setAttribute(
|
|
# 'disabled', 'disabled')
|
|
childWidget.append(
|
|
X.button(type = 'button',
|
|
onclick = 'moveItemDown(this.parentNode)')(
|
|
X.asIs('↓')))
|
|
#if i == count-1:
|
|
# childWidget.children[-1].setAttribute(
|
|
# 'disabled', 'disabled')
|
|
|
|
fieldset += X.li(childWidget)
|
|
if kind.canAddItem(slot, fields):
|
|
addButtonName = slot.getFieldOptionName('addButton')
|
|
if self.addButtonLabel:
|
|
layout += X.buttonInForm(self.addButtonLabel, addButtonName)
|
|
else:
|
|
layout += X.buttonInForm('add', addButtonName)
|
|
if self.apply:
|
|
layout += X.buttonInForm('apply', 'applyButton')
|
|
return layout
|
|
|
|
def getHtmlReadOnlyValue(self, slot, fields, **keywords):
|
|
return X.array(
|
|
self.getModelHiddenLayout(slot, fields, children = 0),
|
|
self.getHtmlViewValue(slot, fields, **keywords) )
|
|
|
|
def getModelHiddenLayout(self, slot, fields, children = 1):
|
|
countName = slot.getFieldOptionName('count')
|
|
kind = slot.getKind()
|
|
count = kind.getItemsCount(slot, fields)
|
|
layout = X.array()
|
|
if count:
|
|
layout += X.input(name = countName, type = 'hidden', value = count)
|
|
if children:
|
|
for i in range(count):
|
|
itemSlot = slot.getKind().getItemSlot(slot, i)
|
|
itemWidget = itemSlot.getWidget()
|
|
if itemWidget is None:
|
|
raise Exception('Missing item widget for %s in %s' % (
|
|
slot.getPath(), str(itemSlot.getKind().__dict__)))
|
|
layout += itemWidget.getModelHiddenLayout(itemSlot, fields)
|
|
return layout
|
|
|
|
def submit(self, slot, fields):
|
|
kind = slot.getKind()
|
|
count = kind.getMinCount(slot)
|
|
try:
|
|
count = max(count,
|
|
int(slot.getFieldOption(fields, 'count', default = '0')))
|
|
except ValueError:
|
|
pass
|
|
|
|
value = []
|
|
for i in range(count):
|
|
itemSlot = kind.getItemSlot(slot, i)
|
|
itemWidget = itemSlot.getWidget()
|
|
itemKind = itemSlot.getKind()
|
|
try:
|
|
itemValue = itemWidget.submit(itemSlot, fields)
|
|
if itemValue is None:
|
|
# what if emptyValue != None ?
|
|
continue
|
|
if type(itemValue) != itemKind.pythonStorageType:
|
|
itemValue = itemKind.convertValueFromOtherType(itemValue)
|
|
if itemKind.isEmptyModelValue(itemSlot, itemValue):
|
|
continue
|
|
itemKind.checkModelValue(itemSlot, itemValue)
|
|
except faults.BaseFault, f:
|
|
itemSlot.getObject().setError(slot.getPath(), f)
|
|
context.setVar('again', 1)
|
|
context.setVar('error', 1)
|
|
continue
|
|
value.append(itemValue)
|
|
|
|
if self.uniqueValues:
|
|
uniq = {}
|
|
for v in value:
|
|
uniq[v] = 1
|
|
value = uniq.keys()
|
|
|
|
addButtonName = slot.getFieldOptionName('addButton')
|
|
if isButtonSelected(addButtonName, fields):
|
|
itemSlot = kind.getItemSlot(slot, count)
|
|
itemKind = itemSlot.getKind()
|
|
value.append(itemKind.getDefaultValue(itemSlot))
|
|
context.setVar('again', 1)
|
|
context.setVar('hideErrors', 1)
|
|
return value
|
|
register(Multi)
|
|
|
|
|
|
class MultiCheck(WidgetMixin, proxyWidgets.MultiCheck):
|
|
def getHtmlViewValue(self, slot, fields, **keywords):
|
|
kind = slot.getKind()
|
|
layout = X.ul()
|
|
value = slot.getValue() or []
|
|
for i, v in zip(range(len(value)), value):
|
|
itemSlot = kind.getItemSlot(slot, i)
|
|
itemWidget = itemSlot.getWidget()
|
|
layout += X.li(itemWidget.getHtmlValue(itemSlot, fields))
|
|
return layout
|
|
|
|
def getHtmlFormValue(self, slot, fields, **keywords):
|
|
kind = slot.getKind()
|
|
layout = X.ul()
|
|
values = kind.itemKind.getSortedValues(slot)
|
|
labels = kind.itemKind.getLabels(slot)
|
|
for i in range(len(values)):
|
|
itemSlot = kind.getItemSlot(slot, i)
|
|
itemWidget = itemSlot.getWidget()
|
|
fieldName = slot.getFieldOptionName(values[i])
|
|
attrs = {}
|
|
if values[i] in (slot.getValue() or []):
|
|
attrs = {'checked': 'checked'}
|
|
layout += X.li(
|
|
X.input(type = 'checkbox', name = fieldName, **attrs),
|
|
_(labels[values[i]]))
|
|
return layout
|
|
|
|
def submit(self, slot, fields):
|
|
kind = slot.getKind()
|
|
value = []
|
|
values = kind.itemKind.getValues(slot)
|
|
for i in range(len(values)):
|
|
fieldName = slot.getFieldOptionName(values[i])
|
|
itemValue = slot.getFieldOption(fields, values[i])
|
|
if itemValue == 'on':
|
|
value.append(values[i])
|
|
return value
|
|
register(MultiCheck)
|
|
|
|
|
|
class Path(WidgetMixin, proxyWidgets.Path):
|
|
def getHtmlViewValue(self, slot, fields, **keywords):
|
|
fieldValue = slot.getValue() or ''
|
|
return X.a(href = X.idUrl(object.id).add('path', fieldValue))(
|
|
fieldValue)
|
|
|
|
def getHtmlFormValue(self, slot, fields, **keywords):
|
|
fieldName = slot.getFieldName()
|
|
fieldValue = slot.getValue() or ''
|
|
|
|
layout = X.array()
|
|
layout += X.input(
|
|
maxlength = 80, name = fieldName, size = 80,
|
|
type = 'text', value = fieldValue)
|
|
return layout
|
|
register(Path)
|
|
|
|
|
|
class PushButton(WidgetMixin, proxyWidgets.PushButton):
|
|
def getHtmlViewValue(self, slot, fields, **keywords):
|
|
label = self.getModelLabel(slot)
|
|
kind = slot.getKind()
|
|
# FIXME: To improve using a class Command, like CardsWeb.
|
|
nextObjectId = kind.nextObjectId
|
|
if nextObjectId is None:
|
|
nextObjectId = slot.getObject().id
|
|
url = X.idUrl(nextObjectId, action = kind.nextModeName)
|
|
return X.buttonStandalone(_(label), url)
|
|
|
|
def getHtmlReadOnlyValue(self, slot, fields, **keywords):
|
|
return self.getHtmlFormValue(slot, fields, **keywords)
|
|
|
|
def getHtmlFormValue(self, slot, fields, **keywords):
|
|
label = self.getModelLabel(slot)
|
|
layout = X.array()
|
|
buttonName = slot.getFieldName()
|
|
layout += X.buttonInForm(_(label), buttonName)
|
|
return layout
|
|
register(PushButton)
|
|
|
|
|
|
class RadioButtons(ExclusiveChoiceMixin, proxyWidgets.RadioButtons):
|
|
def getHtmlFormValue(self, slot, fields, **keywords):
|
|
fieldName = slot.getFieldName()
|
|
kind = slot.getKind()
|
|
try:
|
|
value = slot.getValue()
|
|
except IndexError:
|
|
value = None
|
|
|
|
if type(value) is types.StringType:
|
|
valueAsString = value
|
|
else:
|
|
try:
|
|
valueAsString = kind.convertValueToOtherType(value, types.StringType)
|
|
except: # happens with class_ instance
|
|
valueAsString = ''
|
|
|
|
if hasattr(kind, 'sortLabels') and kind.sortLabels:
|
|
values = kind.getSortedValues(slot)
|
|
else:
|
|
values = kind.getValues(slot)
|
|
if values is None:
|
|
raise Exception('Kind "%s" of slot "%s" has no values' % (
|
|
kind, slot))
|
|
labels = self.getLabels(slot)
|
|
|
|
layout = X.array()
|
|
|
|
group = X.span(_class = 'radio-buttons-group')
|
|
itemsCount = len(values)
|
|
if not value in values:
|
|
if labels.has_key(valueAsString):
|
|
noneLabel = _(labels[valueAsString])
|
|
else:
|
|
noneLabel = _(self.noneLabel)
|
|
radioButton = X.span(_class = 'radio-button')
|
|
radioButton += X.input(checked = 'checked', name = fieldName,
|
|
type = 'radio', value = '')
|
|
radioButton += X.nbsp
|
|
radioButton += noneLabel
|
|
group += radioButton
|
|
itemsCount += 1
|
|
elif not kind.isRequired and not None in values:
|
|
noneAsString = kind.getModelValueAsString(None)
|
|
if labels.has_key(noneAsString):
|
|
noneLabel = _(labels[noneAsString])
|
|
else:
|
|
noneLabel = _(self.noneLabel)
|
|
radioButton = X.span(_class = 'radio-button')
|
|
radioButton += X.input(name = fieldName, type = 'radio',
|
|
value = '')
|
|
radioButton += X.nbsp
|
|
radioButton += noneLabel
|
|
group += radioButton
|
|
itemsCount += 1
|
|
if itemsCount == 1:
|
|
# The menu has only one item. Replace it by a read-only value.
|
|
layout += self.getHtmlReadOnlyValue(slot, fields, **keywords)
|
|
return layout
|
|
|
|
for itemValue in values:
|
|
inputAttributes = {}
|
|
itemValueAsString = kind.getModelValueAsString(itemValue)
|
|
if itemValue == value:
|
|
inputAttributes['checked'] = 'checked'
|
|
if labels.has_key(itemValueAsString):
|
|
label = _(labels[itemValueAsString])
|
|
elif itemValue == '__all__':
|
|
label = _(self.allLabel)
|
|
elif itemValueAsString:
|
|
label = _(itemValueAsString)
|
|
else:
|
|
label = _(self.noneLabel)
|
|
radioButton = X.span(_class = 'radio-button')
|
|
radioButton += X.input(
|
|
name = fieldName, type = 'radio',
|
|
value = itemValueAsString, **inputAttributes)
|
|
radioButton += X.nbsp
|
|
radioButton += label
|
|
group += radioButton
|
|
layout += group
|
|
if self.apply:
|
|
layout += ' '
|
|
layout += X.buttonInForm('apply', 'applyButton')
|
|
return layout
|
|
register(RadioButtons)
|
|
|
|
|
|
class Select(ExclusiveChoiceMixin, proxyWidgets.Select):
|
|
def getHtmlFormValue(self, slot, fields, **keywords):
|
|
fieldName = slot.getFieldName()
|
|
kind = slot.getKind()
|
|
try:
|
|
value = slot.getValue() or ''
|
|
except IndexError:
|
|
value = None
|
|
|
|
if type(value) is types.StringType:
|
|
valueAsString = value
|
|
else:
|
|
try:
|
|
valueAsString = kind.convertValueToOtherType(value, types.StringType)
|
|
except: # happens with class_ instance
|
|
valueAsString = ''
|
|
|
|
if hasattr(kind, 'sortLabels') and kind.sortLabels:
|
|
values = kind.getSortedValues(slot)
|
|
else:
|
|
values = kind.getValues(slot)
|
|
if values is None:
|
|
raise Exception('Kind "%s" of slot "%s" has no values' % (
|
|
kind, slot))
|
|
|
|
labels = self.getLabels(slot)
|
|
|
|
layout = X.array()
|
|
|
|
selectAttributes = {}
|
|
selectAttributes['name'] = fieldName
|
|
select = X.select(**selectAttributes)
|
|
itemsCount = len(values)
|
|
if not valueAsString in [kind.getModelValueAsString(x) for x in values]:
|
|
if labels.has_key(valueAsString):
|
|
noneLabel = _(labels[valueAsString])
|
|
else:
|
|
noneLabel = _(self.noneLabel)
|
|
select += X.option(selected = 'selected',
|
|
value = valueAsString)(noneLabel)
|
|
itemsCount += 1
|
|
elif not kind.isRequired and not None in values:
|
|
noneAsString = kind.getModelValueAsString(None)
|
|
if labels.has_key(noneAsString):
|
|
noneLabel = _(labels[noneAsString])
|
|
else:
|
|
noneLabel = _(self.noneLabel)
|
|
select += X.option(value = '')(noneLabel)
|
|
itemsCount += 1
|
|
|
|
if itemsCount == 1:
|
|
# The menu has only one item. Replace it by a read-only value.
|
|
layout += self.getHtmlReadOnlyValue(slot, fields, **keywords)
|
|
return layout
|
|
|
|
groupedValues = {}
|
|
if hasattr(kind, 'getGroupedValues'):
|
|
groupedValues = kind.getGroupedValues(slot)
|
|
|
|
if groupedValues:
|
|
groupLabelsDict = kind.getGroupLabels(slot)
|
|
groupLabels = groupLabelsDict.keys()
|
|
groupLabels.sort(lambda x,y: locale.strcoll(x, y))
|
|
for label in groupLabels:
|
|
role = groupLabelsDict[label]
|
|
groupValues = groupedValues[role]
|
|
if role is None:
|
|
optgroup = select
|
|
else:
|
|
optgroup = X.optgroup(label = label)
|
|
select += optgroup
|
|
for value in groupValues[:]:
|
|
if not value in labels.keys():
|
|
groupValues.remove(value)
|
|
groupValues.sort(lambda x,y: locale.strcoll(
|
|
labels[x], labels[y]))
|
|
for itemValue in groupValues:
|
|
optionAttributes = {}
|
|
itemValueAsString = kind.getModelValueAsString(itemValue)
|
|
if itemValueAsString == valueAsString:
|
|
optionAttributes['selected'] = 'selected'
|
|
if labels.has_key(itemValueAsString):
|
|
label = labels[itemValueAsString]
|
|
elif itemValue == '__all__':
|
|
label = _(self.allLabel)
|
|
elif itemValueAsString:
|
|
label = itemValueAsString
|
|
else:
|
|
label = _(self.noneLabel)
|
|
optgroup += X.option(value = itemValueAsString,
|
|
**optionAttributes)(label)
|
|
else:
|
|
for itemValue in values:
|
|
optionAttributes = {}
|
|
itemValueAsString = kind.getModelValueAsString(itemValue)
|
|
if itemValue == value:
|
|
optionAttributes['selected'] = 'selected'
|
|
if labels.has_key(itemValueAsString):
|
|
label = _(labels[itemValueAsString])
|
|
elif itemValue == '__all__':
|
|
label = _(self.allLabel)
|
|
elif itemValueAsString:
|
|
label = _(itemValueAsString)
|
|
else:
|
|
label = _(self.noneLabel)
|
|
select += X.option(value = itemValueAsString,
|
|
**optionAttributes)(label)
|
|
layout += select
|
|
|
|
if self.apply:
|
|
layout += ' '
|
|
layout += X.buttonInForm('apply', 'applyButton')
|
|
return layout
|
|
register(Select)
|
|
|
|
|
|
class SelectId(Select, proxyWidgets.SelectId):
|
|
def getHtmlViewValue(self, slot, fields, **keywords):
|
|
fieldValue = slot.getValue()
|
|
if fieldValue:
|
|
if self.provideHypertextLink:
|
|
return X.objectHypertextLabel(fieldValue)
|
|
else:
|
|
try:
|
|
return getObjectLabelTranslated(
|
|
fieldValue, context.getVar('readLanguages'))
|
|
except faults.MissingItem:
|
|
return X.span(_class = 'deleted')(_('Missing Object (%s)') % objectId)
|
|
else:
|
|
return _(self.noneLabel)
|
|
|
|
|
|
def getHtmlFormValue(self, slot, fields, **keywords):
|
|
layout = Select.getHtmlFormValue(self, slot, fields, **keywords)
|
|
kind = slot.getKind()
|
|
if hasattr(kind, 'rememberedIds') and kind.rememberedIds:
|
|
webTools.addContextualHeader('jsform')
|
|
roles = []
|
|
for role in (kind.serverRoles or context.getVar('knownRoles')):
|
|
web = getWebForServerRole(role)
|
|
if hasattr(web, 'useObjectIds') and web.useObjectIds:
|
|
roles.append(role)
|
|
roles = ','.join(roles)
|
|
url = X.url('/selectOthers').add('roles', roles)
|
|
layout += X.input(
|
|
_class = 'button others', type = 'button',
|
|
onClick = 'selectOthers(this.parentNode, "%s")' % url,
|
|
value = _('Others'))
|
|
return layout
|
|
register(SelectId)
|
|
|
|
|
|
class TextArea(WidgetMixin, proxyWidgets.TextArea):
|
|
def getHtmlViewDiffValue(self, oldSlot, newSlot, **keywords):
|
|
newValue = newSlot.getValue().split('\n')
|
|
oldValue = oldSlot.getValue().split('\n')
|
|
try:
|
|
difflib.ndiff
|
|
except AttributeError:
|
|
# no ndiff function in Python 2.1
|
|
return WidgetMixin.getHtmlViewDiffValue(
|
|
self, oldSlot, newSlot, **keywords)
|
|
|
|
result = []
|
|
for line in difflib.ndiff(oldValue, newValue):
|
|
marker, line = line[0], line[2:]
|
|
if marker == ' ':
|
|
result.append(line)
|
|
elif marker == '-':
|
|
result.append('<span class="diff-old">%s</span>' % line)
|
|
elif marker == '+':
|
|
result.append('<span class="diff-new">%s</span>' % line)
|
|
elif marker == '?':
|
|
continue
|
|
|
|
return X.pre(_class = 'diff')(X.asIs('\n'.join(result)))
|
|
|
|
def getHtmlViewValue(self, slot, fields, **keywords):
|
|
fieldValue, translationBar = \
|
|
translation.getFieldValueAndTranslationBar(slot, fields)
|
|
if not fieldValue:
|
|
fieldValue = ''
|
|
if self.viewInTextArea:
|
|
textareaAttributes = self.getTextAreaAttributes()
|
|
layout = X.textarea(readonly = 'readonly',
|
|
**textareaAttributes)(fieldValue)
|
|
else:
|
|
virtualHost = context.getVar('virtualHost')
|
|
sectionLevel = context.getVar('sectionLevel') + 1
|
|
format = slot.getKind().getTextFormat(slot)
|
|
inline = context.getVar('inline', default = 0)
|
|
if format == 'docbook':
|
|
formattedText = parsers.makeHtmlFromDocBook(
|
|
fieldValue, inline = inline)
|
|
elif format == 'html':
|
|
formattedText = parsers.makeHtmlFromHtml(
|
|
fieldValue, inline = inline)
|
|
elif format == 'text':
|
|
formattedText = parsers.makeHtmlFromPreformattedText(
|
|
fieldValue, inline = inline)
|
|
elif format == 'rst':
|
|
formattedText = parsers.makeHtmlFromReStructuredText(
|
|
fieldValue, inline = inline,
|
|
sectionLevel = sectionLevel)
|
|
elif format == 'spip':
|
|
formattedText = parsers.makeHtmlFromSpip(
|
|
fieldValue, inline = inline,
|
|
sectionLevel = sectionLevel)
|
|
else:
|
|
formattedText = parsers.makeHtmlFromUnformattedText(
|
|
fieldValue, inline = inline)
|
|
formattedText = replaceSpecialTags(formattedText)
|
|
layout = X.asIs(formattedText)
|
|
|
|
if translationBar:
|
|
layout = X.array(layout, translationBar)
|
|
|
|
return layout
|
|
|
|
def getHtmlReadOnlyValue(self, slot, fields, **keywords):
|
|
fieldValue = slot.getValue() or ''
|
|
layout = X.array(self.getModelHiddenLayout(slot, fields))
|
|
if self.viewInTextArea:
|
|
textareaAttributes = self.getTextAreaAttributes()
|
|
layout += X.textarea(readonly = 'readonly',
|
|
**textareaAttributes)(fieldValue)
|
|
return layout
|
|
else:
|
|
sectionLevel = context.getVar('sectionLevel') + 1
|
|
format = slot.getKind().getTextFormat(slot)
|
|
inline = context.getVar('inline', default = 0)
|
|
if format == 'docbook':
|
|
formattedText = parsers.makeHtmlFromDocBook(
|
|
fieldValue, inline = inline)
|
|
elif format == 'html':
|
|
formattedText = parsers.makeHtmlFromHtml(
|
|
fieldValue, inline = inline)
|
|
elif format == 'text':
|
|
formattedText = parsers.makeHtmlFromPreformattedText(
|
|
fieldValue, inline = inline)
|
|
elif format == 'rst':
|
|
formattedText = parsers.makeHtmlFromReStructuredText(
|
|
fieldValue, inline = inline,
|
|
sectionLevel = sectionLevel)
|
|
elif format == 'spip':
|
|
formattedText = parsers.makeHtmlFromSpip(
|
|
fieldValue, inline = inline,
|
|
sectionLevel = sectionLevel)
|
|
else:
|
|
formattedText = parsers.makeHtmlFromUnformattedText(
|
|
fieldValue, inline = inline)
|
|
formattedText = replaceSpecialTags(formattedText)
|
|
return X.array(
|
|
self.getModelHiddenLayout(slot, fields),
|
|
X.asIs(formattedText))
|
|
return layout
|
|
|
|
def getTextAreaAttributes(self):
|
|
textareaAttributes = {}
|
|
if self.cols:
|
|
textareaAttributes['cols'] = self.cols
|
|
else:
|
|
textareaAttributes['cols'] = 80
|
|
if self.rows:
|
|
textareaAttributes['rows'] = self.rows
|
|
else:
|
|
textareaAttributes['rows'] = 10
|
|
return textareaAttributes
|
|
|
|
def getHtmlFormValue(self, slot, fields, **keywords):
|
|
fieldName = slot.getFieldName()
|
|
fieldValue = slot.getValue() or ''
|
|
|
|
textareaAttributes = self.getTextAreaAttributes()
|
|
|
|
layout = X.array()
|
|
layout += X.textarea(
|
|
name = fieldName, **textareaAttributes)(fieldValue)
|
|
|
|
if self.preview or self.apply:
|
|
buttonsBar = X.div(_class = 'field-value-buttons-bar')
|
|
layout += buttonsBar
|
|
if self.preview:
|
|
buttonsBar += X.buttonInForm('preview', 'applyButton')
|
|
if self.apply:
|
|
buttonsBar += X.buttonInForm('apply', 'applyButton')
|
|
|
|
if self.preview and fieldValue:
|
|
format = slot.getKind().getTextFormat(slot)
|
|
if format == 'docbook':
|
|
formattedText = parsers.makeHtmlFromDocBook(fieldValue)
|
|
elif format == 'html':
|
|
if not slot.getObject().getError(slot.getPath()):
|
|
formattedText = parsers.makeHtmlFromHtml(fieldValue)
|
|
else:
|
|
formattedText = '<strong>error in HTML</strong>'
|
|
elif format == 'text':
|
|
formattedText = parsers.makeHtmlFromPreformattedText(
|
|
fieldValue)
|
|
elif format == 'rst':
|
|
formattedText = parsers.makeHtmlFromReStructuredText(
|
|
fieldValue)
|
|
elif format == 'spip':
|
|
formattedText = parsers.makeHtmlFromSpip(fieldValue)
|
|
else:
|
|
formattedText = parsers.makeHtmlFromUnformattedText(
|
|
fieldValue)
|
|
formattedText = replaceSpecialTags(formattedText)
|
|
user = context.getVar('user')
|
|
if user is not None and user.spellcheckEntries \
|
|
and slot.getObject().hasSlotName('language'):
|
|
languageSlot = slot.getObject().getSlot('language')
|
|
formattedText = spellcheck(formattedText,
|
|
languageSlot.getValue())
|
|
if formattedText:
|
|
layout += X.div(_class = 'preview')(X.asIs(formattedText))
|
|
|
|
return layout
|
|
|
|
def submit(self, slot, fields):
|
|
value = WidgetMixin.submit(self, slot, fields)
|
|
if value is None:
|
|
return None
|
|
value = value.replace('\r\n', '\n')
|
|
value = value.replace(
|
|
'\x91', "'").replace('\x92', "'").replace(
|
|
'\x93', "'").replace('\x94', "'").replace(
|
|
'\x81', "'").replace('\x82', "'").replace(
|
|
'’', "'").replace('…', '...').replace(
|
|
'–', '--').replace('“', '"').replace(
|
|
'´', "'").replace('”', '"').replace(
|
|
'‘', "'")
|
|
return value
|
|
|
|
register(TextArea)
|
|
|
|
|
|
class Thing(ThingMixin, proxyWidgets.Thing):
|
|
pass
|
|
register(Thing)
|
|
|
|
|
|
class Time(TimeMixin, proxyWidgets.Time):
|
|
def getHtmlFormValue(self, slot, fields, **keywords):
|
|
fieldName = slot.getFieldName()
|
|
fieldValue = slot.getValue()
|
|
|
|
if type(fieldValue) is not types.StringType:
|
|
fieldValue = slot.getKind().convertValueToOtherType(fieldValue,
|
|
types.StringType)
|
|
|
|
layout = X.array()
|
|
|
|
layout += X.input(name = fieldName, type = 'text',
|
|
id = fieldName, value = fieldValue)
|
|
webTools.addContextualHeader('jscalendar')
|
|
#
|
|
# TODO: ifFormat should be based on kind dateFormat
|
|
layout.append(X.img(_class = 'button date-picker',
|
|
src = X.fileUrl('/javascript/jscalendar/img.png'),
|
|
id = '%s_trigger' % fieldName,
|
|
value = '...',
|
|
onload = """Calendar.setup({inputField: "%s",
|
|
ifFormat: "%s", button: "%s_trigger",
|
|
singleClick: true })""" % (
|
|
fieldName, slot.getKind().formatStringDay,
|
|
fieldName)))
|
|
return layout
|
|
|
|
register(Time)
|
|
|
|
|
|
class Token(WidgetMixin, proxyWidgets.Token):
|
|
pass
|
|
register(Token)
|
|
|
|
|
|
class UploadFile(WidgetMixin, proxyWidgets.UploadFile):
|
|
def getContentPathString(self, contentSlot):
|
|
contentPath = contentSlot.getPath()
|
|
return contentPath[5:].replace("']", '').replace('.', '/')
|
|
|
|
def getHtmlViewValue(self, slot, fields, **keywords):
|
|
value = slot.getValue()
|
|
object = slot.getObject()
|
|
|
|
legacyObject = 0
|
|
if value and type(value) is type(''):
|
|
legacyObject = 1
|
|
value = self.forgetLegacyUploadFile(slot, value)
|
|
|
|
if not value:
|
|
return ''
|
|
|
|
addedToUrl = ''
|
|
if value.dataFileName and '.' in value.dataFileName:
|
|
addedToUrl = '/%s' % urllib.quote(value.dataFileName)
|
|
|
|
if isTypeOfMimeType(value.dataType, 'image'):
|
|
uri = X.idUrl(object.id, 'thumbnail')
|
|
if slot.parent is not None:
|
|
uri.add('path', slot.getPath())
|
|
uri.add('width', 256)
|
|
uri.add('height', 256)
|
|
image = X.img(src = uri)
|
|
if legacyObject:
|
|
uri = X.idUrl(object.id, 'image%s' % addedToUrl)
|
|
else:
|
|
uri = X.idUrl(object.id, 'image%s%s' % (
|
|
self.getContentPathString(slot), addedToUrl))
|
|
return X.a(_class = 'image', href = uri)(image)
|
|
elif value:
|
|
if legacyObject:
|
|
uri = X.idUrl(object.id, 'download%s' % addedToUrl)
|
|
else:
|
|
uri = X.idUrl(object.id, 'download%s%s' % (
|
|
self.getContentPathString(slot), addedToUrl))
|
|
return X.a(href = uri)(_('download'))
|
|
return ''
|
|
|
|
def getHtmlReadOnlyValue(self, slot, fields, **keywords):
|
|
return X.array(
|
|
self.getModelHiddenLayout(slot, fields),
|
|
self.getRepresentation(slot, fields, **keywords) )
|
|
|
|
def forgetLegacyUploadFile(self, slot, value):
|
|
v = commonTools.newThing('other', 'Upload')
|
|
fileNameSlot = slot.getContainer().getSlot(
|
|
slot.name + 'FileName', parentSlot = slot.parent)
|
|
v.dataFileName = fileNameSlot.getValue()
|
|
v.data = value
|
|
typeSlot = slot.getContainer().getSlot(
|
|
slot.name + 'Type', parentSlot = slot.parent)
|
|
v.dataType = typeSlot.getValue()
|
|
return v
|
|
|
|
def getModelHiddenLayout(self, slot, fields):
|
|
value = slot.getValue()
|
|
if value and type(value) is type(''):
|
|
value = self.forgetLegacyUploadFile(slot, value)
|
|
|
|
if not value:
|
|
value = commonTools.newThing('other', 'Upload')
|
|
|
|
data = {
|
|
'data': value.data,
|
|
'type': value.dataType,
|
|
'fileName': value.dataFileName
|
|
}
|
|
|
|
sessionsProxy = getProxyForServerRole('sessions')
|
|
if context.getVar('session') is None:
|
|
req = context.getVar('req')
|
|
session = sessionsProxy.newSession(req.connection.remote_ip,
|
|
serverId = context.getVar('virtualHost').defaultDispatcherId)
|
|
sessionToken = session['sessionToken']
|
|
session['isDirty'] = 1
|
|
context.setVar('sessionToken', sessionToken)
|
|
context.setVar('session', session)
|
|
# TODO: how to deal here with cookies support ?
|
|
|
|
self.dataToken = sessionsProxy.addTemporaryData(data)
|
|
return X.input(name = slot.getFieldOptionName('dataToken'),
|
|
type = 'hidden', value = self.dataToken)
|
|
|
|
def getHtmlFormValue(self, slot, fields, **keywords):
|
|
fieldName = slot.getFieldName()
|
|
fieldValue = slot.getValue() or ''
|
|
|
|
layout = X.array()
|
|
layout += self.getModelHiddenLayout(slot, fields)
|
|
representation = self.getRepresentation(slot, fields, **keywords)
|
|
if representation:
|
|
layout += representation
|
|
layout += X.br()
|
|
layout += X.input(name = fieldName, type = 'file')
|
|
|
|
if self.apply:
|
|
layout += ' '
|
|
layout += X.buttonInForm('apply', 'applyButton')
|
|
|
|
return layout
|
|
|
|
def getRepresentation(self, slot, fields, **keywords):
|
|
value = slot.getValue()
|
|
if not value:
|
|
return ''
|
|
|
|
if type(value) is type(''):
|
|
value = self.forgetLegacyUploadFile(slot, value)
|
|
|
|
if not isTypeOfMimeType(value.dataType, 'image'):
|
|
return ''
|
|
|
|
uri = X.actionUrl('imageEdit/%s' % self.dataToken)
|
|
return X.img(src = uri)
|
|
|
|
def submit(self, slot, fields):
|
|
value = slot.getField(fields)
|
|
upload = commonTools.newThing('other', 'Upload')
|
|
dataToken = slot.getFieldOption(fields, 'dataToken')
|
|
sessionsProxy = getProxyForServerRole('sessions')
|
|
if value.value:
|
|
upload.data = value.value
|
|
upload.dataFileName = value.filename
|
|
if '\\' in upload.dataFileName:
|
|
upload.dataFileName = upload.dataFileName[
|
|
upload.dataFileName.rindex('\\')+1:]
|
|
upload.dataType = value.type
|
|
else:
|
|
data = sessionsProxy.getTemporaryData(dataToken)
|
|
if not data:
|
|
return None
|
|
upload.data = data['data']
|
|
upload.dataFileName = data['fileName']
|
|
upload.dataType = data['type']
|
|
|
|
# UploadFiles use Upload widget but not Upload kind
|
|
# (and it wants information about type and filename)
|
|
#
|
|
# This line (+ more in UploadFilesWeb.py (submitFields))
|
|
# is there while waiting for UploadFiles conversion
|
|
# to Upload kind.
|
|
context.setVar('UploadFilesXXX', upload)
|
|
|
|
sessionsProxy.delTemporaryData(dataToken)
|
|
return upload
|
|
register(UploadFile)
|
|
|
|
|
|
class Url(WidgetMixin, proxyWidgets.Url):
|
|
def getHtmlViewValue(self, slot, fields, **keywords):
|
|
fieldValue = slot.getValue() or ''
|
|
if fieldValue:
|
|
if fieldValue.startswith('http://'):
|
|
href = fieldValue
|
|
else:
|
|
href = 'http://%s' % fieldValue
|
|
return X.a(href = href)(fieldValue)
|
|
else:
|
|
return X.nbsp
|
|
|
|
def getHtmlFormValue(self, slot, fields, **keywords):
|
|
fieldName = slot.getFieldName()
|
|
fieldValue = slot.getValue() or ''
|
|
|
|
layout = X.array()
|
|
|
|
inputAttributes = {}
|
|
maxLength = slot.getKind().getTextMaxLength()
|
|
if maxLength is not None:
|
|
inputAttributes['maxlength'] = maxLength
|
|
if self.size is not None:
|
|
size = self.size
|
|
elif maxLength is not None:
|
|
size = min(80, maxLength)
|
|
else:
|
|
size = None
|
|
if size is not None:
|
|
inputAttributes['size'] = size
|
|
layout += X.input(name = fieldName, type = 'text',
|
|
value = fieldValue, **inputAttributes)
|
|
if self.apply:
|
|
layout += ' '
|
|
layout += X.buttonInForm('apply', 'applyButton')
|
|
return layout
|
|
register(Url)
|
|
|
|
|
|
class XSelect(Select, proxyWidgets.XSelect):
|
|
otherFieldLabel_defaultValue = N_('other:')
|
|
otherFieldLabel_kind_widget_fieldLabel = N_('Label')
|
|
|
|
def getHtmlValue(self, slot, fields, **keywords):
|
|
fieldName = slot.getFieldName()
|
|
fieldValue = slot.getValue()
|
|
if fieldValue is None:
|
|
fieldValue = ''
|
|
else:
|
|
fieldValue = str(fieldValue)
|
|
otherFieldLabel = self.otherFieldLabel or \
|
|
self.otherFieldLabel_defaultValue
|
|
otherFieldValue = slot.getFieldOption(fields, 'other', default = '')
|
|
kind = slot.getKind()
|
|
if kind.sortLabels:
|
|
values = kind.getSortedValues(slot)
|
|
else:
|
|
values = kind.getValues(slot)
|
|
groupNames, groupedValues = kind.getGroupedValues(slot)
|
|
if values is None:
|
|
raise Exception('Kind "%s" of slot "%s" has no values' % (
|
|
kind, slot))
|
|
if not fieldValue in values and (fieldValue or None not in values):
|
|
fieldValue = kind.defaultValue
|
|
if fieldValue is None:
|
|
fieldValue = ''
|
|
else:
|
|
fieldValue = str(fieldValue)
|
|
labels = self.getLabels(slot)
|
|
|
|
if not self.isInForm():
|
|
if labels.has_key(str(fieldValue)):
|
|
layout = self.makeModelTitleFromValue(slot, fields, fieldValue)
|
|
elif fieldValue == '__all__':
|
|
layout = _(self.allLabel)
|
|
elif otherFieldValue:
|
|
layout = X.asIs(_(str(otherFieldValue)))
|
|
else:
|
|
layout = None
|
|
elif self.isReadOnly(slot):
|
|
layout = X.array(
|
|
self.getModelHiddenLayout(slot, fields),
|
|
)
|
|
if labels.has_key(str(fieldValue)):
|
|
displayFieldValue = self.makeModelTitleFromValue(
|
|
slot, fields, fieldValue)
|
|
else:
|
|
displayFieldValue = _(str(fieldValue))
|
|
layout += displayFieldValue
|
|
else:
|
|
layout = X.array()
|
|
table = X.table(_class = 'field-value', id = '')
|
|
layout += table
|
|
selectAttributes = {}
|
|
selectAttributes['name'] = fieldName
|
|
select = X.select(**selectAttributes)
|
|
if not fieldValue in values and (fieldValue or None not in values):
|
|
if labels.has_key(fieldValue):
|
|
noneLabel = _(labels[fieldValue])
|
|
else:
|
|
noneLabel = _(self.noneLabel)
|
|
select += X.option(selected = 'selected', value = '')(
|
|
noneLabel)
|
|
groupNames = None
|
|
if hasattr(kind, 'getGroupedValues'):
|
|
groupNames, groupedValues = kind.getGroupedValues(slot)
|
|
if groupNames is not None:
|
|
for groupName in groupNames:
|
|
groupValues = groupedValues[groupName]
|
|
optgroup = X.optgroup(label = _(groupName))
|
|
select += optgroup
|
|
for value in groupValues:
|
|
optionAttributes = {}
|
|
if value is None:
|
|
value = ''
|
|
valueAsString = str(value)
|
|
if valueAsString == fieldValue:
|
|
optionAttributes['selected'] = 'selected'
|
|
if labels.has_key(valueAsString):
|
|
label = _(labels[valueAsString])
|
|
elif not value:
|
|
label = _(self.noneLabel)
|
|
elif value == '__all__':
|
|
label = _(self.allLabel)
|
|
else:
|
|
label = _(value)
|
|
optgroup += X.option(
|
|
value = value, **optionAttributes)(label)
|
|
else:
|
|
for value in values:
|
|
optionAttributes = {}
|
|
if value is None:
|
|
value = ''
|
|
valueAsString = str(value)
|
|
if valueAsString == fieldValue:
|
|
optionAttributes['selected'] = 'selected'
|
|
if labels.has_key(valueAsString):
|
|
label = _(labels[valueAsString])
|
|
elif not value:
|
|
label = _(self.noneLabel)
|
|
elif value == '__all__':
|
|
label = _(self.allLabel)
|
|
else:
|
|
label = _(value)
|
|
select += X.option(value = value, **optionAttributes)(
|
|
label)
|
|
table += X.tr(
|
|
_class = 'field-value', id = 'tooltip-%s' % fieldName)(
|
|
X.td(_class = 'field-value', colspan="2")(select))
|
|
inputAttributes = {}
|
|
maxLength = slot.getKind().getTextMaxLength()
|
|
if maxLength is not None:
|
|
inputAttributes['maxlength'] = maxLength
|
|
if self.size is not None:
|
|
size = self.size
|
|
elif maxLength is not None:
|
|
size = min(80, maxLength)
|
|
else:
|
|
size = None
|
|
if size is not None:
|
|
inputAttributes['size'] = size
|
|
table += X.tr(_class = 'field-value')(
|
|
X.td(_class = 'field-label')(X.asIs(_(otherFieldLabel))),
|
|
X.td(_class = 'field-value')(
|
|
X.input(
|
|
name = '%s_other' % fieldName, type = 'text',
|
|
value = otherFieldValue, **inputAttributes)))
|
|
if self.apply:
|
|
layout += ' '
|
|
layout += X.buttonInForm('apply', 'applyButton')
|
|
return layout
|
|
|
|
def getModelHiddenLayout(self, slot, fields):
|
|
fieldName = slot.getFieldName()
|
|
fieldValue = slot.getValue() or ''
|
|
return X.input(name = fieldName, type = 'hidden', value = fieldValue)
|
|
|
|
def makeModelTitleFromValue(self, slot, fields, value):
|
|
if value is None:
|
|
valueAsString = ''
|
|
else:
|
|
valueAsString = str(value)
|
|
layoutMode = context.getVar('layoutMode')
|
|
if layoutMode != 'edit':
|
|
if self.titles and self.titles.has_key(valueAsString):
|
|
return _(self.titles[valueAsString])
|
|
kind = slot.getKind()
|
|
title = kind.makeModelTitleFromValue(slot, fields, value)
|
|
if title:
|
|
return title
|
|
labels = self.getLabels(slot)
|
|
if labels and labels.has_key(valueAsString):
|
|
return _(labels[valueAsString])
|
|
return valueAsString
|
|
|
|
def submit(self, slot, fields):
|
|
otherFieldValue = slot.getFieldOption(fields, 'other', default = '')
|
|
if otherFieldValue:
|
|
return otherFieldValue
|
|
return WidgetMixin.submit(self, slot, fields)
|
|
register(XSelect)
|
|
|