This repository has been archived on 2023-02-21. You can view files and clone it, but cannot push or open issues or pull requests.
glasnost/shared/web/widgets.py

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(
'&#8217;', "'").replace('&#8230;', '...').replace(
'&#8211;', '--').replace('&#8220;', '"').replace(
'&#180;', "'").replace('&#8221;', '"').replace(
'&#8216;', "'")
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('&uarr;')))
#if i == 0:
# childWidget.children[-1].setAttribute(
# 'disabled', 'disabled')
childWidget.append(
X.button(type = 'button',
onclick = 'moveItemDown(this.parentNode)')(
X.asIs('&darr;')))
#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(
'&#8217;', "'").replace('&#8230;', '...').replace(
'&#8211;', '--').replace('&#8220;', '"').replace(
'&#180;', "'").replace('&#8221;', '"').replace(
'&#8216;', "'")
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)