675 lines
16 KiB
Python
675 lines
16 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.
|
|
|
|
|
|
__doc__ = """Glasnost Web Kinds"""
|
|
|
|
__version__ = '$Revision$'[11:-2]
|
|
|
|
|
|
import re
|
|
import time
|
|
import types
|
|
|
|
import glasnost.common.context as context
|
|
import glasnost.common.faults as faults
|
|
import glasnost.common.tools_new as commonTools
|
|
from glasnost.common import translation
|
|
|
|
import glasnost.proxy.kinds as proxyKinds
|
|
|
|
import things
|
|
from tools import *
|
|
import WebAPI
|
|
|
|
## import connectors # Do not remove!
|
|
import functions # Do not remove!
|
|
import modes # Do not remove!
|
|
import properties # Do not remove!
|
|
import uploads # Do not remove!
|
|
import values # Do not remove!
|
|
import widgets # Do not remove!
|
|
|
|
|
|
register = things.register
|
|
|
|
|
|
class KindMixin(things.ThingMixin):
|
|
hasToInitField = 1
|
|
hasToInitField_kind_importExport = 'private'
|
|
hasToInitField_kind_stateInEditMode = 'hidden'
|
|
hasToInitField_kind_stateInViewMode = 'hidden'
|
|
hasToInitField_kindName = 'Boolean'
|
|
|
|
hasToMakeFieldFromValue = 1
|
|
hasToMakeFieldFromValue_kind_importExport = 'private'
|
|
hasToMakeFieldFromValue_kind_stateInEditMode = 'hidden'
|
|
hasToMakeFieldFromValue_kind_stateInViewMode = 'hidden'
|
|
hasToMakeFieldFromValue_kindName = 'Boolean'
|
|
|
|
hasToRepairField = 1
|
|
hasToRepairField_kind_importExport = 'private'
|
|
hasToRepairField_kind_stateInEditMode = 'hidden'
|
|
hasToRepairField_kind_stateInViewMode = 'hidden'
|
|
hasToRepairField_kindName = 'Boolean'
|
|
|
|
hasToSubmitField = 1
|
|
hasToSubmitField_kind_importExport = 'private'
|
|
hasToSubmitField_kind_stateInEditMode = 'hidden'
|
|
hasToSubmitField_kind_stateInViewMode = 'hidden'
|
|
hasToSubmitField_kindName = 'Boolean'
|
|
|
|
preference = None
|
|
preference_kind_importExport = 'private'
|
|
preference_kind_stateInEditMode = 'hidden'
|
|
preference_kind_stateInViewMode = 'hidden'
|
|
preference_kindName = 'String'
|
|
|
|
## def getHelpAlias(self, slot, fields):
|
|
## return self.helpAlias
|
|
|
|
def getModelValueAsString(self, value):
|
|
if type(value) is types.StringType:
|
|
return value
|
|
return self.convertValueToOtherType(value, types.StringType)
|
|
|
|
def getModelValueFromFields(self, slot, fields):
|
|
widget = slot.getWidget()
|
|
kind = slot.getKind()
|
|
try:
|
|
value = widget.submit(slot, fields)
|
|
if type(value) != kind.pythonStorageType:
|
|
value = kind.convertValueFromOtherType(value)
|
|
except:
|
|
value = self.defaultValue
|
|
return value
|
|
|
|
def getOrderedFieldSlotNames(self, fields, parentSlot = None):
|
|
slotNames = things.ThingMixin.getOrderedFieldSlotNames(
|
|
self, fields, parentSlot = parentSlot)
|
|
# The field widgetName must be set before the field widget.
|
|
slotNames += ['widgetName', 'widget']
|
|
return slotNames
|
|
|
|
def newModelWidget(self, slot):
|
|
return commonTools.newThing('widget', self.widgetName)
|
|
|
|
|
|
class AbstractSequenceMixin(KindMixin):
|
|
def canAddItem(self, slot, fields):
|
|
return 1
|
|
|
|
def getItemsCount(self, slot, fields):
|
|
raise NotImplementedError
|
|
|
|
def isLabelImportant(self, slot):
|
|
raise NotImplementedError
|
|
|
|
|
|
class ChoiceMixin(KindMixin):
|
|
def makeModelTitleFromValue(self, slot, fields, value):
|
|
valueAsString = self.getModelValueAsString(value)
|
|
if self.titles and self.titles.has_key(valueAsString):
|
|
return _(self.titles[valueAsString])
|
|
return None
|
|
|
|
|
|
class IdMixin(KindMixin):
|
|
pass
|
|
|
|
|
|
class SequenceMixin(AbstractSequenceMixin):
|
|
## item_widget = None
|
|
## item_widget_kindName = 'Widget'
|
|
|
|
def canAddItem(self, slot, fields):
|
|
maxCount = self.getMaxCount(slot)
|
|
if maxCount is None:
|
|
return 1
|
|
count = self.getItemsCount(slot, fields)
|
|
return count < maxCount
|
|
|
|
def getItemsCount(self, slot, fields):
|
|
minCount = self.getMinCount(slot)
|
|
try:
|
|
count = max(minCount, len(slot.getValue() or []))
|
|
except ValueError:
|
|
pass
|
|
return count
|
|
|
|
def getMinCount(self, slot):
|
|
return self.fieldsCountMin
|
|
|
|
def isLabelImportant(self, slot):
|
|
return 0
|
|
|
|
class StringMixin(KindMixin):
|
|
pass
|
|
|
|
class ThingMixin(ChoiceMixin):
|
|
def getCreatedModelSlotAndValue(self, slot):
|
|
value = None
|
|
if slot.hasValue():
|
|
value = slot.getValue()
|
|
return self.repairModelSlotAndValue(slot, value)
|
|
|
|
def getModelValueFromFields(self, slot, fields):
|
|
value = ChoiceMixin.getModelValueFromFields(self, slot, fields)
|
|
if value is not None:
|
|
value = value.getThingName()
|
|
return value
|
|
|
|
def makeModelTitleFromValue(self, slot, fields, value):
|
|
object = slot.getObject()
|
|
label = _(self.getLabels(slot)[self.getModelValueAsString(value)])
|
|
return object.makeContentTitle(slot, label)
|
|
|
|
def newModelWidget(self, slot):
|
|
slot, value = self.getCreatedModelSlotAndValue(slot)
|
|
return value.newWidget(parentSlot = slot)
|
|
|
|
def repairModelSlotAndValue(self, slot, value):
|
|
if value is None and self.valueThingName is not None:
|
|
value = commonTools.newThing(
|
|
self.valueThingCategory, self.valueThingName)
|
|
slot = slot.detach(value)
|
|
return slot, value
|
|
|
|
|
|
class TimeMixin(KindMixin):
|
|
pass
|
|
|
|
class TokenMixin(KindMixin):
|
|
pass
|
|
|
|
|
|
class UsersSetMixin(SequenceMixin):
|
|
pass
|
|
|
|
|
|
class BaseKind(KindMixin, proxyKinds.BaseKind):
|
|
pass
|
|
register(BaseKind)
|
|
|
|
|
|
class AcceptedRoles(SequenceMixin, proxyKinds.AcceptedRoles):
|
|
pass
|
|
register(AcceptedRoles)
|
|
|
|
|
|
class Alias(StringMixin, proxyKinds.Alias):
|
|
pass
|
|
register(Alias)
|
|
|
|
|
|
class Amount(KindMixin, proxyKinds.Amount):
|
|
pass
|
|
register(Amount)
|
|
|
|
|
|
class Any(KindMixin, proxyKinds.Any):
|
|
pass
|
|
register(Any)
|
|
|
|
|
|
class ApplicationToken(TokenMixin, proxyKinds.ApplicationToken):
|
|
pass
|
|
register(ApplicationToken)
|
|
|
|
|
|
## class ArgumentPins(SequenceMixin, proxyKinds.ArgumentPins):
|
|
## pass
|
|
## register(ArgumentPins)
|
|
|
|
|
|
class AuthorsSet(UsersSetMixin, proxyKinds.AuthorsSet):
|
|
pass
|
|
register(AuthorsSet)
|
|
|
|
|
|
class Boolean(KindMixin, proxyKinds.Boolean):
|
|
def makeModelTitleFromValue(self, slot, fields, value):
|
|
valueAsString = str(value)
|
|
if self.titles and self.titles.has_key(valueAsString):
|
|
return _(self.titles[valueAsString])
|
|
return None
|
|
register(Boolean)
|
|
|
|
|
|
class Choice(ChoiceMixin, proxyKinds.Choice):
|
|
pass
|
|
register(Choice)
|
|
|
|
|
|
class Command(KindMixin, proxyKinds.Command):
|
|
def submitField2(self, slot, fields, **keywords):
|
|
error = 0
|
|
errorFields = {}
|
|
value = None
|
|
buttonName = slot.getFieldName()
|
|
if isButtonSelected(buttonName, fields):
|
|
command = context.getVar('command')
|
|
command.action = self.action
|
|
command.nextModeName = self.nextModeName
|
|
command.nextObjectId = self.nextObjectId
|
|
return (error, errorFields, value)
|
|
register(Command)
|
|
|
|
|
|
class CreationTime(TimeMixin, proxyKinds.CreationTime):
|
|
pass
|
|
register(CreationTime)
|
|
|
|
|
|
class Data(KindMixin, proxyKinds.Data):
|
|
pass
|
|
register(Data)
|
|
|
|
|
|
class Date(TimeMixin, proxyKinds.Date):
|
|
pass
|
|
register(Date)
|
|
|
|
|
|
class DispatcherId(KindMixin, proxyKinds.DispatcherId):
|
|
pass
|
|
register(DispatcherId)
|
|
|
|
|
|
class Duration(KindMixin, proxyKinds.Duration):
|
|
pass
|
|
register(Duration)
|
|
|
|
|
|
class Email(StringMixin, proxyKinds.Email):
|
|
pass
|
|
register(Email)
|
|
|
|
|
|
class Fault(ThingMixin, proxyKinds.Fault):
|
|
pass
|
|
register(Fault)
|
|
|
|
|
|
class Fields(KindMixin, proxyKinds.Fields):
|
|
pass
|
|
register(Fields)
|
|
|
|
|
|
class FilePath(StringMixin, proxyKinds.FilePath):
|
|
pass
|
|
register(FilePath)
|
|
|
|
|
|
class Fingerprint(StringMixin, proxyKinds.Fingerprint):
|
|
pass
|
|
register(Fingerprint)
|
|
|
|
|
|
class Float(KindMixin, proxyKinds.Float):
|
|
pass
|
|
register(Float)
|
|
|
|
|
|
class Id(IdMixin, proxyKinds.Id):
|
|
pass
|
|
register(Id)
|
|
|
|
|
|
## class InputConnector(ThingMixin, proxyKinds.InputConnector):
|
|
## pass
|
|
## register(InputConnector)
|
|
|
|
|
|
class Integer(KindMixin, proxyKinds.Integer):
|
|
pass
|
|
register(Integer)
|
|
|
|
|
|
class IntegerChoice(ChoiceMixin, proxyKinds.IntegerChoice):
|
|
pass
|
|
register(IntegerChoice)
|
|
|
|
|
|
class Kind(ThingMixin, proxyKinds.Kind):
|
|
pass
|
|
register(Kind)
|
|
|
|
|
|
class KindName(ChoiceMixin, proxyKinds.KindName):
|
|
kindSlotName = None
|
|
kindSlotName_kind_isRequired = 1
|
|
kindSlotName_kindName = 'SlotName'
|
|
|
|
def __init__(self, **attributes):
|
|
proxyKinds.KindName.__init__(self, **attributes)
|
|
self.labels = {}
|
|
for kindClass in commonTools.getAllThingClasses().values():
|
|
if kindClass.thingCategory != 'kind':
|
|
continue
|
|
value = kindClass.getThingName.im_func(kindClass)
|
|
self.labels[value] = kindClass.getThingPublicName.im_func(
|
|
kindClass)
|
|
|
|
def makeModelTitleFromValue(self, slot, fields, value):
|
|
object = slot.getObject()
|
|
label = _(self.getLabels(slot)[self.getModelValueAsString(value)])
|
|
return object.makeContentTitle(slot, label)
|
|
register(KindName)
|
|
|
|
|
|
class LanguageChoice(ChoiceMixin, proxyKinds.LanguageChoice):
|
|
pass
|
|
register(LanguageChoice)
|
|
|
|
|
|
class Link(KindMixin, proxyKinds.Link):
|
|
pass
|
|
register(Link)
|
|
|
|
|
|
class Mapping(KindMixin, proxyKinds.Mapping):
|
|
fieldsCountMin = 1 # FIXME: To rename?
|
|
fieldsCountMin_kindName = 'Integer'
|
|
|
|
keyDefaultValues = None
|
|
keyDefaultValues_kind_importExport = 'private'
|
|
keyDefaultValues_kind_stateInEditMode = 'hidden'
|
|
keyDefaultValues_kind_stateInViewMode = 'hidden'
|
|
keyDefaultValues_kind_itemKind_value_kindName = 'String'
|
|
keyDefaultValues_kind_label = N_('Default Values')
|
|
keyDefaultValues_kindName = 'Sequence'
|
|
|
|
## key_widget = None
|
|
## key_widget_kindName = 'Widget'
|
|
|
|
## value_widget = None
|
|
## value_widget_kindName = 'Widget'
|
|
|
|
def getItemsCount(self, slot, fields):
|
|
count = self.fieldsCountMin
|
|
try:
|
|
count = max(count, int(slot.getFieldOption(
|
|
fields, 'count', default = '0')))
|
|
except ValueError:
|
|
pass
|
|
return count
|
|
|
|
def canAddItem(self, slot, fields):
|
|
return not self.keyKind.isExportable()
|
|
register(Mapping)
|
|
|
|
|
|
class Marks(KindMixin, proxyKinds.Marks):
|
|
idsGetterName = None
|
|
idsGetterName_kindName = 'String'
|
|
register(Marks)
|
|
|
|
|
|
class ApprovalMarks(Marks):
|
|
defaultValue_kindName = 'ApprovalMarks'
|
|
register(ApprovalMarks)
|
|
|
|
|
|
class DistributionMarks(Marks):
|
|
defaultValue_kindName = 'DistributionMarks'
|
|
register(DistributionMarks)
|
|
|
|
|
|
class RankingMarks(Marks):
|
|
defaultValue_kindName = 'RankingMarks'
|
|
register(RankingMarks)
|
|
|
|
|
|
class RatingMarks(Marks):
|
|
defaultValue_kindName = 'RatingMarks'
|
|
register(RatingMarks)
|
|
|
|
|
|
class Memory(KindMixin, proxyKinds.Memory):
|
|
pass
|
|
register(Memory)
|
|
|
|
|
|
class Mode(ThingMixin, proxyKinds.Mode):
|
|
pass
|
|
register(Mode)
|
|
|
|
|
|
class ModificationTime(TimeMixin, proxyKinds.ModificationTime):
|
|
pass
|
|
register(ModificationTime)
|
|
|
|
|
|
## class OutputConnector(ThingMixin, proxyKinds.OutputConnector):
|
|
## pass
|
|
## register(OutputConnector)
|
|
|
|
|
|
class PairwiseMatrix(KindMixin, proxyKinds.PairwiseMatrix):
|
|
pass
|
|
register(PairwiseMatrix)
|
|
|
|
|
|
class Password(StringMixin, proxyKinds.Password):
|
|
pass
|
|
register(Password)
|
|
|
|
|
|
class Path(StringMixin, proxyKinds.Path):
|
|
pass
|
|
register(Path)
|
|
|
|
|
|
class Properties(SequenceMixin, proxyKinds.Properties):
|
|
pass
|
|
register(Properties)
|
|
|
|
|
|
class PythonIdentifier(StringMixin, proxyKinds.PythonIdentifier):
|
|
pass
|
|
register(PythonIdentifier)
|
|
|
|
|
|
class Rating(KindMixin, proxyKinds.Rating):
|
|
pass
|
|
register(Rating)
|
|
|
|
|
|
class ReadersSet(UsersSetMixin, proxyKinds.ReadersSet):
|
|
pass
|
|
register(ReadersSet)
|
|
|
|
|
|
## class ResultPins(SequenceMixin, proxyKinds.ResultPins):
|
|
## pass
|
|
## register(ResultPins)
|
|
|
|
|
|
class Script(StringMixin, proxyKinds.Script):
|
|
pass
|
|
register(Script)
|
|
|
|
|
|
class ScriptSourceCode(StringMixin, proxyKinds.ScriptSourceCode):
|
|
pass
|
|
register(ScriptSourceCode)
|
|
|
|
|
|
class Sequence(SequenceMixin, proxyKinds.Sequence):
|
|
pass
|
|
register(Sequence)
|
|
|
|
|
|
class ServerId(IdMixin, proxyKinds.ServerId):
|
|
pass
|
|
register(ServerId)
|
|
|
|
|
|
class ServerRole(ChoiceMixin, proxyKinds.ServerRole):
|
|
pass
|
|
register(ServerRole)
|
|
|
|
|
|
class SlotName(ChoiceMixin, proxyKinds.SlotName):
|
|
pass
|
|
register(SlotName)
|
|
|
|
|
|
class String(StringMixin, proxyKinds.String):
|
|
pass
|
|
register(String)
|
|
|
|
|
|
class Structure(AbstractSequenceMixin, proxyKinds.Structure):
|
|
def canAddItem(self, slot, fields):
|
|
return 0
|
|
|
|
def getItemsCount(self, slot, fields):
|
|
if self.parameters is None:
|
|
return 0
|
|
else:
|
|
return len(self.parameters)
|
|
|
|
def isLabelImportant(self, slot):
|
|
return 1
|
|
register(Structure)
|
|
|
|
|
|
class Thing(ThingMixin, proxyKinds.Thing):
|
|
pass
|
|
register(Thing)
|
|
|
|
|
|
class Time(TimeMixin, proxyKinds.Time):
|
|
pass
|
|
register(Time)
|
|
|
|
|
|
class Token(TokenMixin, proxyKinds.Token):
|
|
pass
|
|
register(Token)
|
|
|
|
|
|
class TranslationToAdd(KindMixin, proxyKinds.TranslationToAdd):
|
|
# TODO: could this class be moved in web/TranslationsWeb.py ?
|
|
pass
|
|
register(TranslationToAdd)
|
|
|
|
|
|
class TranslatorsSets(KindMixin, proxyKinds.TranslatorsSets):
|
|
pass
|
|
register(TranslatorsSets)
|
|
|
|
|
|
class Union(KindMixin, proxyKinds.Union):
|
|
pass
|
|
register(Union)
|
|
|
|
|
|
class Upload(ThingMixin, proxyKinds.Upload):
|
|
pass
|
|
register(Upload)
|
|
|
|
|
|
class UploadFile(Data):
|
|
defaultValue_kindName = 'UploadFile'
|
|
thingPublicCategory = None # N_('Compound')
|
|
register(UploadFile)
|
|
|
|
|
|
class UsersSet(UsersSetMixin, proxyKinds.UsersSet):
|
|
pass
|
|
register(UsersSet)
|
|
|
|
|
|
class UserToken(TokenMixin, proxyKinds.UserToken):
|
|
pass
|
|
register(UserToken)
|
|
|
|
|
|
class ValueHolder(ThingMixin, proxyKinds.ValueHolder):
|
|
pass
|
|
register(ValueHolder)
|
|
|
|
|
|
class Widget(ThingMixin, proxyKinds.Widget):
|
|
pass
|
|
register(Widget)
|
|
|
|
|
|
class WidgetName(ChoiceMixin, proxyKinds.WidgetName):
|
|
def __init__(self, **attributes):
|
|
proxyKinds.WidgetName.__init__(self, **attributes)
|
|
self.labels = {}
|
|
for widgetClass in commonTools.getAllThingClasses().values():
|
|
if widgetClass.thingCategory != 'widget':
|
|
continue
|
|
value = widgetClass.getThingName.im_func(widgetClass)
|
|
self.labels[value] = widgetClass.getThingPublicName.im_func(
|
|
widgetClass)
|
|
|
|
def makeModelTitleFromValue(self, slot, fields, value):
|
|
object = slot.getObject()
|
|
label = _(self.getLabels(slot)[self.getModelValueAsString(value)])
|
|
return object.makeContentTitle(slot, label)
|
|
register(WidgetName)
|
|
|
|
|
|
class WritersSet(UsersSetMixin, proxyKinds.WritersSet):
|
|
pass
|
|
register(WritersSet)
|
|
|
|
|
|
class XChoice(ChoiceMixin, proxyKinds.XChoice):
|
|
otherFieldLabel = None
|
|
## otherFieldLabel_kind_label = N_('Input Text Label')
|
|
otherFieldLabel_kindName = 'String'
|
|
|
|
def makeModelTitleFromValue(self, slot, fields, value):
|
|
valueAsString = self.getModelValueAsString(value)
|
|
if self.titles and self.titles.has_key(valueAsString):
|
|
return _(self.titles[valueAsString])
|
|
return valueAsString
|
|
register(XChoice)
|
|
|
|
|