2798 lines
87 KiB
Python
2798 lines
87 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 Common Kinds"""
|
|
|
|
__version__ = '$Revision$'[11:-2]
|
|
|
|
|
|
import base64
|
|
import copy
|
|
import locale
|
|
import marshal
|
|
import time
|
|
import types
|
|
|
|
import slots
|
|
import translation
|
|
import things
|
|
import system
|
|
from tools import *
|
|
import tools_new as commonTools
|
|
|
|
import connectors # Do not remove!
|
|
import functions # Do not remove!
|
|
import properties # Do not remove!
|
|
import uploads # Do not remove!
|
|
import values # Do not remove!
|
|
import views # Do not remove!
|
|
import widgets # Do not remove!
|
|
|
|
|
|
register = things.register
|
|
|
|
|
|
class BaseKind(things.BaseThing):
|
|
balloonHelp = None
|
|
balloonHelp_kind_label = N_('Balloon Help')
|
|
balloonHelp_kind_widgetName = 'TextArea'
|
|
balloonHelp_kindName = 'String'
|
|
|
|
category = None
|
|
category_kind_importExport = 'private'
|
|
category_kind_label = N_('Category')
|
|
category_kindName = 'String'
|
|
|
|
containerNames = None
|
|
containerNames_kind_importExport = 'private'
|
|
containerNames_kind_itemKind_valueName = 'KindName'
|
|
containerNames_kind_label = N_('Containers')
|
|
containerNames_kindName = 'Sequence'
|
|
|
|
defaultValue = None
|
|
defaultValue_kind_importExport = 'private'
|
|
defaultValue_kind_label = N_('Default Value')
|
|
defaultValue_kindName = None # To override
|
|
|
|
## helpAlias = None
|
|
## helpAlias_kind_label = N_('Help Alias')
|
|
## helpAlias_kindName = 'Alias'
|
|
|
|
hideLabel = 0
|
|
hideLabel_kind_importExport = 'private'
|
|
hideLabel_kind_label = N_('Hidden Label')
|
|
hideLabel_kindName = 'Boolean'
|
|
|
|
importExport = 'public'
|
|
importExport_kind_label = N_('Import/Export')
|
|
importExport_kind_labels = {
|
|
'from-server-only': N_('From Server Only'),
|
|
'private': N_('Private'),
|
|
'public': N_('Public'),
|
|
'to-server-only': N_('To Server Only'),
|
|
}
|
|
importExport_kind_values = [
|
|
'private',
|
|
'to-server-only',
|
|
'from-server-only',
|
|
'public',
|
|
]
|
|
importExport_kindName = 'Choice'
|
|
|
|
isAutomaticalyModified = 0
|
|
isAutomaticalyModified_kind_importExport = 'private'
|
|
isAutomaticalyModified_kindName = 'Boolean'
|
|
|
|
# When false, isPractical means that the kind can not be used to describe
|
|
# a real value, but only to describe an expected value.
|
|
isPractical = 1
|
|
isPractical_kind_importExport = 'private'
|
|
isPractical_kindName = 'Boolean'
|
|
|
|
isRequired = 0
|
|
isRequired_kind_label = N_('Mandatory')
|
|
## isRequired_kind_labels = {
|
|
## '0': N_('Optional'),
|
|
## '1': N_('Required'),
|
|
## }
|
|
isRequired_kindName = 'Boolean'
|
|
|
|
isTranslatable = 0
|
|
isTranslatable_kind_importExport = 'private'
|
|
isTranslatable_kind_label = N_('Translatable')
|
|
## isTranslatable_kind_labels = {
|
|
## '0': N_('Invariant'),
|
|
## '1': N_('Translatable'),
|
|
## }
|
|
isTranslatable_kindName = 'Boolean'
|
|
|
|
label = None
|
|
label_kind_label = N_('Label')
|
|
label_kindName = 'String'
|
|
|
|
labelPlural = None
|
|
labelPlural_kind_importExport = 'private'
|
|
labelPlural_kind_label = N_('Label (plural form)')
|
|
labelPlural_kindName = 'String'
|
|
|
|
name = None
|
|
name_kind_importExport = 'private'
|
|
name_kind_label = N_('Name')
|
|
name_kindName = 'String'
|
|
|
|
possibleWidgetNames = None
|
|
possibleWidgetNames_kind_importExport = 'private'
|
|
possibleWidgetNames_kind_itemKind_valueName = 'WidgetName'
|
|
possibleWidgetNames_kindName = 'Sequence'
|
|
|
|
stateInEditMode = 'read-write'
|
|
stateInEditMode_kind_label = N_('State In "Edit" Mode')
|
|
stateInEditMode_kind_labels = {
|
|
'hidden': N_('Hidden'),
|
|
'read-only': N_('Read Only'),
|
|
'read-write': N_('Read/Write'),
|
|
}
|
|
stateInEditMode_kind_values = [
|
|
'hidden',
|
|
'read-only',
|
|
'read-write',
|
|
]
|
|
stateInEditMode_kindName = 'Choice'
|
|
|
|
stateInUseMode = 'read-only'
|
|
stateInUseMode_kind_label = N_('State In "Use" Mode')
|
|
stateInUseMode_kind_labels = {
|
|
'hidden': N_('Hidden'),
|
|
'read-only': N_('Read Only'),
|
|
'read-write': N_('Read/Write'),
|
|
}
|
|
stateInUseMode_kind_values = [
|
|
'hidden',
|
|
'read-only',
|
|
'read-write',
|
|
]
|
|
stateInUseMode_kindName = 'Choice'
|
|
|
|
stateInViewMode = 'read-only'
|
|
stateInViewMode_kind_label = N_('State In "View" Mode')
|
|
stateInViewMode_kind_labels = {
|
|
'hidden': N_('Hidden'),
|
|
'read-only': N_('Read Only'),
|
|
}
|
|
stateInViewMode_kind_values = [
|
|
'hidden',
|
|
'read-only',
|
|
]
|
|
stateInViewMode_kindName = 'Choice'
|
|
|
|
thingCategory = 'kind'
|
|
|
|
useCustomStorage = 0
|
|
useCustomStorage_kind_importExport = 'private'
|
|
useCustomStorage_kindName = 'Boolean'
|
|
|
|
useFileStorage = 0
|
|
useFileStorage_kind_importExport = 'from-server-only'
|
|
useFileStorage_kind_label = N_('Storage')
|
|
useFileStorage_kind_labels = {
|
|
'0': N_('Internal'),
|
|
'1': N_('In External File'),
|
|
}
|
|
useFileStorage_kindName = 'Boolean'
|
|
|
|
widget = None
|
|
widget_kind_importExport = 'private'
|
|
widget_kind_valueThingNameSlotName = 'widgetName'
|
|
widget_kindName = 'Widget'
|
|
|
|
widgetName = 'InputText'
|
|
widgetName_kind_label = N_('Graphical Component')
|
|
widgetName_kind_valuesGetterName = 'getWidgetNameValues'
|
|
widgetName_kindName = 'WidgetName'
|
|
|
|
def __init__(self, **attributes):
|
|
things.BaseThing.__init__(self)
|
|
for name, value in attributes.items():
|
|
# Ensure that each argument has been declared as an attribute.
|
|
if not hasattr(self.__class__, name):
|
|
raise Exception('Undeclared attribute %s for %s' % (
|
|
name, self.__class__.__name__))
|
|
if getattr(self, name) == value:
|
|
continue
|
|
setattr(self, name, value)
|
|
|
|
def __str__(self):
|
|
return self.getName()
|
|
|
|
def accepts(self, kind):
|
|
"""Test whether the given kind is always compatible with self.
|
|
|
|
For example:
|
|
- Integer accepts Integer.
|
|
- Number accepts Integer.
|
|
- Integer doesn't accept Number.
|
|
"""
|
|
|
|
return self.includes(kind)
|
|
|
|
def acquireNonCoreValue(self, slot, objectDirectoryPath):
|
|
pass
|
|
|
|
def buildOptions(self, options):
|
|
for name, value in options.items():
|
|
# Ensure that each option has been declared as an attribute.
|
|
nameBase = name.split('_')[0]
|
|
if not hasattr(self.__class__, nameBase):
|
|
raise Exception('Undeclared attribute %s for %s' % (
|
|
name, self.__class__.__name__))
|
|
if hasattr(self, name) and getattr(self, name) == value:
|
|
continue
|
|
setattr(self, name, value)
|
|
|
|
def checkModelValue(self, slot, value):
|
|
assert self.isPractical
|
|
if self.isRequired and value is None:
|
|
raise faults.MissingSlotValue(slot)
|
|
|
|
def checkModelValueHolder(self, slot, valueHolder):
|
|
assert self.isPractical
|
|
if not self.accepts(valueHolder.kind):
|
|
raise faults.KindsIncompatibility(self, valueHolder.kind)
|
|
self.checkModelValue(slot, valueHolder.value)
|
|
|
|
def convertValueIds(
|
|
self, slot, value, sourceDispatcherId, destinationDispatcherId):
|
|
assert self.isPractical
|
|
return value
|
|
|
|
def equals(self, kind):
|
|
"""Test whether two kinds are equal."""
|
|
|
|
return self.getName() == kind.getName()
|
|
|
|
def exportValueToXmlRpc(self, slot, value):
|
|
assert self.isPractical
|
|
if type(value) in (types.StringType, types.UnicodeType):
|
|
value = utf8(value)
|
|
return value
|
|
|
|
def getBalloonHelp(self):
|
|
return self.balloonHelp
|
|
|
|
def getCmpFunction(self):
|
|
return cmp
|
|
|
|
def getModelLabel(self, slot):
|
|
if self.label:
|
|
return self.label
|
|
return slot.getLabel()
|
|
|
|
def getModelLabelPlural(self, slot):
|
|
if self.labelPlural:
|
|
return self.labelPlural
|
|
return self.getModelLabel(slot)
|
|
|
|
def getModelSlotByPath(self, slot, path):
|
|
if path.startswith('self'):
|
|
path = path[len('self'):]
|
|
if not path:
|
|
return slot
|
|
raise Exception('Path "%s" not found' % path)
|
|
|
|
def getName(cls):
|
|
if type(cls) == types.InstanceType:
|
|
cls = cls.__class__
|
|
if cls.name:
|
|
name = cls.name
|
|
else:
|
|
name = cls.getThingName.im_func(cls)
|
|
return name
|
|
|
|
def getOrderedLayoutSlotNames(self, parentSlot = None):
|
|
slotNames = things.BaseThing.getOrderedLayoutSlotNames(
|
|
self, parentSlot = parentSlot)
|
|
slotNames += [
|
|
'category', 'name', 'label', 'labelPlural', 'hideLabel',
|
|
'widgetName', 'widget', 'stateInEditMode', 'stateInViewMode',
|
|
'stateInUseMode', 'isRequired', 'defaultValue', 'balloonHelp',
|
|
## 'helpAlias',
|
|
'importExport', 'useFileStorage', 'useCommonStorage']
|
|
return slotNames
|
|
|
|
def getPossibleWidgetNames(self):
|
|
assert self.isPractical
|
|
if self.possibleWidgetNames is not None:
|
|
return self.possibleWidgetNames
|
|
return [self.widgetName]
|
|
|
|
def getWidgetNameValues(self, widgetNameSlot, fields):
|
|
kindSlot = widgetNameSlot.parent
|
|
return kindSlot.getValue().getPossibleWidgetNames()
|
|
|
|
def importValueFromXmlRpc(self, slot, value):
|
|
assert self.isPractical
|
|
if type(value) in (types.StringType, types.UnicodeType):
|
|
value = iso8859_15(value)
|
|
value = value.replace('\r\n', '\n') # MS-DOS return character
|
|
value = value.replace('\r', '\n') # MacOS return character
|
|
return value
|
|
|
|
def includes(self, kind):
|
|
"""Test whether the given kind is included in self.
|
|
|
|
For example:
|
|
- Integer includes Integer.
|
|
- Number includes Integer.
|
|
- Integer doesn't include Number.
|
|
"""
|
|
|
|
if self.equals(kind):
|
|
return 1
|
|
if kind.containerNames is None:
|
|
return 0
|
|
for kindContainerName in kind.containerNames:
|
|
if self.includes(commonTools.newThing(
|
|
'kind', kindContainerName)):
|
|
return 1
|
|
return 0
|
|
|
|
def intersects(self, kind):
|
|
"""Test whether the given kind has an intersection with self.
|
|
|
|
For example:
|
|
- Integer has an intersection with Integer.
|
|
- Number has an intersection with Integer.
|
|
- Integer has an intersection with Number.
|
|
"""
|
|
|
|
# To override, because the test below is incomplete.
|
|
return self.includes(kind) or kind.includes(self)
|
|
|
|
def isExportable(self):
|
|
raise NotImplementedError
|
|
|
|
def isImportable(self):
|
|
raise NotImplementedError
|
|
|
|
def isInCore(self, slot):
|
|
return not self.useCustomStorage and not self.useFileStorage
|
|
|
|
def mayAccept(self, kind):
|
|
"""Test whether the given kind may be compatible with self.
|
|
|
|
For example:
|
|
- Integer always accepts Integer.
|
|
- Number always accepts Integer.
|
|
- Integer may accept Number, because sometimes a Number is an Integer.
|
|
"""
|
|
|
|
return self.intersects(kind)
|
|
|
|
def releaseNonCoreValue(self, slot):
|
|
pass
|
|
|
|
def removeValueIds(self, slot, value, rolesToKeep):
|
|
return value
|
|
|
|
def repairValue(self, slot, value, toVersion):
|
|
assert self.isPractical
|
|
if toVersion == 5004:
|
|
if type(value) in (types.StringType, types.UnicodeType):
|
|
repairedValue = value.replace('\r\n', '\n')
|
|
repairedValue = repairedValue.replace('\r', '\n')
|
|
if repairedValue != value:
|
|
return repairedValue
|
|
return None
|
|
|
|
def saveNonCoreValue(self, slot, objectDirectoryPath):
|
|
pass
|
|
|
|
def setAutomaticalValue(self, slot, init = 0):
|
|
raise NotImplementedError
|
|
register(BaseKind)
|
|
|
|
|
|
class AbstractSequence(BaseKind):
|
|
maxCount = None
|
|
maxCount_kindName = 'Integer'
|
|
|
|
maxCountGetterName = None
|
|
maxCountGetterName_kindName = 'PythonIdentifier'
|
|
|
|
widgetName = 'Multi'
|
|
|
|
def checkModelValue(self, slot, value):
|
|
BaseKind.checkModelValue(self, slot, value)
|
|
if value:
|
|
if type(value) is not types.ListType:
|
|
raise faults.BadSlotValue(slot, value)
|
|
if self.maxCount and len(value) > self.maxCount:
|
|
raise faults.BadSlotValue(slot, value)
|
|
|
|
def convertValueIds(self, slot, value, sourceDispatcherId,
|
|
destinationDispatcherId):
|
|
try:
|
|
len(value)
|
|
except TypeError:
|
|
raise Exception('Unsized value (= %s) for slot %s' % (value, slot))
|
|
for i in range(len(value)):
|
|
itemSlot = self.getItemSlot(slot, i)
|
|
newItem = itemSlot.getKind().convertValueIds(
|
|
itemSlot, value[i], sourceDispatcherId,
|
|
destinationDispatcherId)
|
|
if newItem != value[i]:
|
|
value[i] = newItem
|
|
return value
|
|
|
|
def exportValueToXmlRpc(self, slot, value):
|
|
if value is None:
|
|
return []
|
|
exportedValue = []
|
|
for i in range(len(value)):
|
|
itemSlot = self.getItemSlot(slot, i)
|
|
exportedValue.append(itemSlot.getKind().exportValueToXmlRpc(
|
|
itemSlot, value[i]))
|
|
return exportedValue
|
|
|
|
def getItemKind(self, index):
|
|
raise NotImplementedError
|
|
|
|
def getItemSlot(self, slot, index):
|
|
return slots.Item(index, parent = slot)
|
|
|
|
def getModelSlotByPath(self, slot, path):
|
|
if path.startswith('self'):
|
|
path = path[len('self'):]
|
|
if not path:
|
|
return slot
|
|
if path[0] != '[' or not ']' in path:
|
|
raise Exception('Path "%s" not found' % path)
|
|
index = int(path[1:path.index(']')])
|
|
return self.getItemKind(index).getModelSlotByPath(
|
|
self.getItemSlot(slot, index), path[path.index(']') + 1:])
|
|
|
|
def importValueFromXmlRpc(self, slot, importedValue):
|
|
if importedValue is None:
|
|
return []
|
|
value = []
|
|
slot.value = value
|
|
for i in range(len(importedValue)):
|
|
itemSlot = self.getItemSlot(slot, i)
|
|
value.append(itemSlot.getKind().importValueFromXmlRpc(
|
|
itemSlot, importedValue[i]))
|
|
del slot.value
|
|
return value
|
|
|
|
def removeValueIds(self, slot, value, rolesToKeep):
|
|
indexesToDelete = []
|
|
for i in range(len(value)):
|
|
itemSlot = self.getItemSlot(slot, i)
|
|
newItem = itemSlot.getKind().removeValueIds(
|
|
itemSlot, value[i], rolesToKeep)
|
|
if newItem != value[i]:
|
|
indexesToDelete.append(i)
|
|
indexesToDelete.reverse()
|
|
for i in indexesToDelete:
|
|
del value[i]
|
|
if not value:
|
|
return None
|
|
return value
|
|
|
|
def repairValue(self, slot, value, toVersion):
|
|
if toVersion == 4000:
|
|
changed = 0
|
|
for i in range(len(value)):
|
|
itemSlot = self.getItemSlot(slot, i)
|
|
newItem = itemSlot.getKind().repairValue(
|
|
itemSlot, value[i], toVersion)
|
|
if newItem:
|
|
changed = 1
|
|
value[i] = newItem
|
|
if changed:
|
|
return value
|
|
return None
|
|
|
|
|
|
class Alias(BaseKind):
|
|
category = N_('Glasnost')
|
|
|
|
defaultValue_kindName = 'Alias'
|
|
|
|
name = N_('Alias')
|
|
|
|
register(Alias)
|
|
|
|
|
|
class Amount(BaseKind):
|
|
## category = N_('Numbers')
|
|
|
|
defaultValue_kindName = 'Amount'
|
|
|
|
name = N_('Amount')
|
|
|
|
def checkModelValue(self, slot, value):
|
|
BaseKind.checkModelValue(self, slot, value)
|
|
if value and type(value) is not types.IntType:
|
|
raise faults.BadSlotValue(slot, value)
|
|
|
|
register(Amount)
|
|
|
|
|
|
class Any(BaseKind):
|
|
category = N_('Glasnost')
|
|
|
|
defaultValue_kindName = 'Any'
|
|
|
|
isPractical = 0
|
|
|
|
name = N_('Any')
|
|
register(Any)
|
|
|
|
|
|
class Boolean(BaseKind):
|
|
category = N_('Numbers')
|
|
|
|
containerNames = ['Any']
|
|
|
|
defaultValue_kindName = 'Boolean'
|
|
|
|
labels = {
|
|
'0': N_('False'),
|
|
'1': N_('True'),
|
|
}
|
|
labels_kind_keyKind_value_stateInEditMode = 'read-only'
|
|
labels_kind_keyKind_valueName = 'String'
|
|
labels_kind_label = N_('Labels')
|
|
labels_kind_valueKind_valueName = 'String'
|
|
labels_kindName = 'Mapping'
|
|
|
|
name = N_('Boolean')
|
|
|
|
possibleWidgetNames = ['InputCheckBox', 'PushButton', 'Select']
|
|
|
|
sortLabels = 0
|
|
sortLabels_kindName = 'Boolean'
|
|
|
|
titles = None
|
|
titles_kind_importExport = 'private'
|
|
titles_kind_keyKind_value_stateInEditMode = 'read-only'
|
|
titles_kind_keyKind_valueName = 'String'
|
|
titles_kind_label = N_('Titles')
|
|
titles_kind_valueKind_valueName = 'String'
|
|
titles_kindName = 'Mapping'
|
|
|
|
values = [0, 1]
|
|
values_kind_importExport = 'private'
|
|
values_kind_itemKind_valueName = 'Boolean'
|
|
values_kindName = 'Sequence'
|
|
|
|
widgetName = 'InputCheckBox'
|
|
|
|
def checkModelValue(self, slot, value):
|
|
BaseKind.checkModelValue(self, slot, value)
|
|
if value and value not in self.values:
|
|
raise faults.BadSlotValue(slot, value)
|
|
|
|
def getGroupedValues(self, slot, fields):
|
|
return (None, None) # groupNames, groupedValues
|
|
|
|
def getLabels(self, slot, fields):
|
|
return self.labels
|
|
|
|
def getSortedValues(self, slot, fields):
|
|
values = self.getValues(slot, fields)
|
|
if values is not None:
|
|
values = values[:]
|
|
labels = self.getLabels(slot, fields)
|
|
values.sort(lambda x, y:
|
|
locale.strcoll(_(labels[x]), _(labels[y])))
|
|
return values
|
|
|
|
def getValues(self, slot, fields):
|
|
return self.values
|
|
|
|
def getOrderedLayoutSlotNames(self, parentSlot = None):
|
|
slotNames = BaseKind.getOrderedLayoutSlotNames(
|
|
self, parentSlot = parentSlot)
|
|
slotNames += ['values', 'labels', 'titles']
|
|
return slotNames
|
|
register(Boolean)
|
|
|
|
|
|
class Choice(BaseKind):
|
|
category = N_('Choice')
|
|
|
|
defaultValue_kindName = 'Choice'
|
|
|
|
groupedValues = None
|
|
groupedValues_kind_importExport = 'private'
|
|
groupedValues_kind_keyKind_valueName = 'String'
|
|
groupedValues_kind_valueKind_valueName = 'String'
|
|
groupedValues_kindName = 'Mapping'
|
|
|
|
groupedValuesGetterName = None
|
|
groupedValuesGetterName_kindName = 'PythonIdentifier'
|
|
|
|
groupNames = None
|
|
groupNames_kind_importExport = 'private'
|
|
groupNames_kind_itemKind_valueName = 'String'
|
|
groupNames_kindName = 'Sequence'
|
|
|
|
groupNamesGetterName = None
|
|
groupNamesGetterName_kindName = 'PythonIdentifier'
|
|
|
|
labels = None
|
|
labels_kind_keyKind_valueName = 'String'
|
|
labels_kind_label = N_('Labels')
|
|
labels_kind_valueKind_valueName = 'String'
|
|
labels_kindName = 'Mapping'
|
|
|
|
name = N_('Choice')
|
|
|
|
possibleWidgetNames = ['InputCheckBox', 'Select']
|
|
|
|
sortLabels = 1
|
|
sortLabels_kindName = 'Boolean'
|
|
|
|
titles = None
|
|
titles_kind_importExport = 'private'
|
|
titles_kind_keyKind_value_stateInEditMode = 'read-only'
|
|
titles_kind_keyKind_valueName = 'String'
|
|
titles_kind_label = N_('Titles')
|
|
titles_kind_valueKind_valueName = 'String'
|
|
titles_kindName = 'Mapping'
|
|
|
|
values = None
|
|
values_kind_importExport = 'private'
|
|
values_kind_itemKind_valueName = 'String'
|
|
values_kindName = 'Sequence'
|
|
|
|
valuesGetterName = None
|
|
valuesGetterName_kindName = 'PythonIdentifier'
|
|
|
|
widgetName = 'Select'
|
|
|
|
def checkModelValue(self, slot, value):
|
|
BaseKind.checkModelValue(self, slot, value)
|
|
if value and self.values and value not in self.values:
|
|
raise faults.BadSlotValue(slot, value)
|
|
|
|
def getGroupedValues(self, slot, fields):
|
|
if self.groupedValuesGetterName:
|
|
currentSlot = slot
|
|
while currentSlot is not None:
|
|
container = currentSlot.getContainer()
|
|
try:
|
|
groupedValuesGetter = getattr(container,
|
|
self.groupedValuesGetterName)
|
|
self.groupedValues = groupedValuesGetter(slot, fields)
|
|
if self.groupNamesGetterName:
|
|
groupNamesGetter = getattr(container,
|
|
self.groupNamesGetterName)
|
|
self.groupNames = groupNamesGetter(slot, fields)
|
|
break
|
|
except AttributeError:
|
|
currentSlot = currentSlot.parent
|
|
continue
|
|
return (self.groupNames, self.groupedValues)
|
|
|
|
def getLabels(self, slot, fields):
|
|
if self.labels:
|
|
return self.labels
|
|
labels = {}
|
|
values = self.getValues(slot, fields)
|
|
if values is not None:
|
|
for value in values:
|
|
labels[str(value)] = str(value)
|
|
return labels
|
|
|
|
def getSortedValues(self, slot, fields):
|
|
values = self.getValues(slot, fields)
|
|
if values is None:
|
|
return None
|
|
values = values[:]
|
|
sortedValues = []
|
|
if None in values:
|
|
sortedValues.append(None)
|
|
values.remove(None)
|
|
if '__all__' in values:
|
|
sortedValues.append('__all__')
|
|
values.remove('__all__')
|
|
labels = self.getLabels(slot, fields)
|
|
values.sort(lambda x, y: locale.strcoll(_(labels[x]), _(labels[y])))
|
|
sortedValues += values
|
|
return sortedValues
|
|
|
|
def getValues(self, slot, fields):
|
|
groupedValuesGetterName = self.groupedValuesGetterName
|
|
if groupedValuesGetterName is not None:
|
|
currentSlot = slot
|
|
while currentSlot is not None:
|
|
container = currentSlot.getContainer()
|
|
try:
|
|
groupedValuesGetter = getattr(container,
|
|
groupedValuesGetterName)
|
|
except AttributeError:
|
|
currentSlot = currentSlot.parent
|
|
continue
|
|
groupedValues = groupedValuesGetter(slot, fields)
|
|
assert type(groupedValues) is type({})
|
|
values = []
|
|
for group in groupedValues.keys():
|
|
assert type(groupedValues[group]) is type([])
|
|
values += groupedValues[group]
|
|
return values
|
|
return []
|
|
valuesGetterName = self.valuesGetterName
|
|
if valuesGetterName is not None:
|
|
currentSlot = slot
|
|
while currentSlot is not None:
|
|
container = currentSlot.getContainer()
|
|
try:
|
|
valuesGetter = getattr(container, valuesGetterName)
|
|
except AttributeError:
|
|
currentSlot = currentSlot.parent
|
|
continue
|
|
return valuesGetter(slot, fields)
|
|
return []
|
|
if self.groupedValues:
|
|
result = []
|
|
assert type(self.groupedValues) is type({})
|
|
for key in self.groupedValues.keys():
|
|
assert type(self.groupedValues[key]) is type([])
|
|
for value in self.groupedValues[key]:
|
|
result.append(value)
|
|
return result
|
|
if self.values:
|
|
return self.values
|
|
else:
|
|
return []
|
|
register(Choice)
|
|
|
|
|
|
class Data(BaseKind):
|
|
category = N_('Compound')
|
|
|
|
defaultValue_kindName = 'Data'
|
|
|
|
def exportValueToXmlRpc(self, slot, value):
|
|
if value:
|
|
value = base64.encodestring(value)
|
|
return value
|
|
|
|
def importValueFromXmlRpc(self, slot, value):
|
|
if value:
|
|
value = base64.decodestring(value)
|
|
return value
|
|
register(Data)
|
|
|
|
|
|
class Time(BaseKind):
|
|
category = N_('Date & Time')
|
|
|
|
defaultValue_kindName = 'Time'
|
|
|
|
formatString = '%Y-%m-%d %H:%M:%S'
|
|
formatString_kindName = 'String'
|
|
|
|
name = N_('Time')
|
|
|
|
widgetName = 'Time'
|
|
|
|
def checkModelValue(self, slot, value):
|
|
BaseKind.checkModelValue(self, slot, value)
|
|
if value and type(value) not in [types.IntType, types.FloatType]:
|
|
raise faults.BadSlotValue(slot, value)
|
|
register(Time)
|
|
|
|
|
|
class Date(Time):
|
|
requiredParts = ['year', 'month', 'day']
|
|
requiredParts_kind_itemKind_valueName = 'String'
|
|
requiredParts_kindName = 'Sequence'
|
|
|
|
name = N_('Date')
|
|
|
|
def repairValue(self, slot, value, toVersion):
|
|
if type(value) is types.StringType:
|
|
if value[-2:] == '00':
|
|
repairedValue = time.mktime(time.strptime(value[:-2], '%Y%m'))
|
|
else:
|
|
repairedValue = time.mktime(time.strptime(value, '%Y%m%d'))
|
|
if repairedValue != value:
|
|
return repairedValue
|
|
return None
|
|
register(Date)
|
|
|
|
|
|
class DispatcherId(BaseKind):
|
|
category = N_('Glasnost')
|
|
|
|
containerNames = ['Any', 'String']
|
|
|
|
defaultValue_kindName = 'DispatcherId'
|
|
|
|
name = N_('Dispatcher ID')
|
|
|
|
widget_size = 40
|
|
widgetName = 'InputText'
|
|
|
|
def checkModelValue(self, slot, value):
|
|
BaseKind.checkModelValue(self, slot, value)
|
|
if value and type(value) is not types.StringType:
|
|
raise faults.BadSlotValue(slot, value)
|
|
|
|
def convertValueIds(
|
|
self, slot, value, sourceDispatcherId, destinationDispatcherId):
|
|
return value.replace(sourceDispatcherId, destinationDispatcherId)
|
|
register(DispatcherId)
|
|
|
|
|
|
class Duration(BaseKind):
|
|
category = N_('Date & Time')
|
|
|
|
defaultValue_kindName = 'Duration'
|
|
|
|
requiredParts = ['day', 'hour', 'minute', 'second']
|
|
requiredParts_kind_itemKind_valueName = 'String'
|
|
requiredParts_kindName = 'Sequence'
|
|
|
|
name = N_('Duration')
|
|
|
|
widgetName = 'Duration'
|
|
register(Duration)
|
|
|
|
|
|
class Email(BaseKind):
|
|
category = N_('Text')
|
|
|
|
containerNames = ['Any', 'String']
|
|
|
|
defaultValue_kindName = 'Email'
|
|
|
|
name = N_('Email Address')
|
|
|
|
widgetName = 'Email'
|
|
|
|
def checkModelValue(self, slot, value):
|
|
BaseKind.checkModelValue(self, slot, value)
|
|
if value and type(value) is not types.StringType:
|
|
raise faults.BadSlotValue(slot, value)
|
|
if value and len(value) > 100:
|
|
raise faults.BadSlotValue(slot, value)
|
|
register(Email)
|
|
|
|
|
|
class Fields(BaseKind):
|
|
category = N_('Glasnost')
|
|
|
|
containerNames = ['Any']
|
|
|
|
defaultValue_kindName = 'Fields'
|
|
|
|
name = N_('Fields')
|
|
|
|
def exportValueToXmlRpc(self, slot, value):
|
|
return base64.encodestring(marshal.dumps(value))
|
|
|
|
def importValueFromXmlRpc(self, slot, valueImport):
|
|
return marshal.loads(base64.decodestring(valueImport))
|
|
register(Fields)
|
|
|
|
|
|
class Path(BaseKind):
|
|
category = N_('Text')
|
|
|
|
checkFilePath = 1
|
|
checkFilePath_kindName = 'Boolean'
|
|
|
|
containerNames = ['Any', 'String']
|
|
|
|
defaultValue_kindName = 'Path'
|
|
|
|
name = N_('Path')
|
|
|
|
def checkModelValue(self, slot, value):
|
|
BaseKind.checkModelValue(self, slot, value)
|
|
if value and type(value) is not types.StringType:
|
|
raise faults.BadSlotValue(slot, value)
|
|
register(Path)
|
|
|
|
|
|
class FilePath(Path):
|
|
category = N_('Text')
|
|
|
|
containerNames = ['Any', 'String']
|
|
|
|
defaultValue_kindName = 'FilePath'
|
|
|
|
name = N_('File Path')
|
|
|
|
def checkModelValue(self, slot, value):
|
|
BaseKind.checkModelValue(self, slot, value)
|
|
if value and type(value) is not types.StringType:
|
|
raise faults.BadSlotValue(slot, value)
|
|
register(FilePath)
|
|
|
|
|
|
class Fingerprint(BaseKind):
|
|
category = N_('Text')
|
|
|
|
containerNames = ['Any', 'String']
|
|
|
|
defaultValue_kindName = 'Fingerprint'
|
|
|
|
def checkModelValue(self, slot, value):
|
|
BaseKind.checkModelValue(self, slot, value)
|
|
if value and type(value) is not types.StringType:
|
|
raise faults.BadSlotValue(slot, value)
|
|
register(Fingerprint)
|
|
|
|
|
|
class Float(BaseKind):
|
|
category = N_('Numbers')
|
|
|
|
defaultValue_kindName = 'Float'
|
|
|
|
name = N_('Float Number')
|
|
|
|
def checkModelValue(self, slot, value):
|
|
BaseKind.checkModelValue(self, slot, value)
|
|
if value and type(value) not in [types.IntType, types.FloatType]:
|
|
raise faults.BadSlotValue(slot, value)
|
|
register(Float)
|
|
|
|
|
|
class FunctionName(Choice):
|
|
category = N_('Glasnost')
|
|
|
|
defaultValue_kindName = 'FunctionName'
|
|
|
|
name = N_('Function Name')
|
|
|
|
serverIdSlotName = None
|
|
serverIdSlotName_kindName = 'String'
|
|
|
|
def checkModelValue(self, slot, value):
|
|
Choice.checkModelValue(self, slot, value)
|
|
if value and type(value) is not types.StringType:
|
|
raise faults.BadSlotValue(slot, value)
|
|
|
|
def getValues(self, slot, fields):
|
|
if not self.serverIdSlotName:
|
|
return []
|
|
serverId = slot.getContainer().getSlot(
|
|
self.serverIdSlotName, parentSlot = slot.parent).getField(fields)
|
|
if not serverId:
|
|
return []
|
|
try:
|
|
serverRole = commonTools.extractRole(serverId)
|
|
except: # TODO: tighter check
|
|
return []
|
|
from glasnost.proxy.tools import getProxyForServerRole
|
|
try:
|
|
proxy = getProxyForServerRole(serverRole)
|
|
except: # TODO: tighter check
|
|
return []
|
|
if proxy is None:
|
|
return []
|
|
try:
|
|
functionDeclarations = proxy.getFunctionDeclarations()
|
|
except: # TODO: tighter check
|
|
return []
|
|
return functionDeclarations.keys()
|
|
register(FunctionName)
|
|
|
|
|
|
class Id(BaseKind):
|
|
category = N_('Glasnost')
|
|
|
|
containerNames = ['Any']
|
|
|
|
defaultValue_kindName = 'Id'
|
|
|
|
permanentIds = None
|
|
|
|
name = N_('Object ID')
|
|
|
|
serverRoles = None
|
|
serverRoles_kind_itemKind_valueName = 'ServerRole'
|
|
serverRoles_kindName = 'Sequence'
|
|
|
|
valuesGetterName = None
|
|
valuesGetterName_kindName = 'PythonIdentifier'
|
|
|
|
widgetName = 'SelectId'
|
|
|
|
def checkModelValue(self, slot, value):
|
|
BaseKind.checkModelValue(self, slot, value)
|
|
if value:
|
|
try:
|
|
commonTools.extractDispatcherId(value)
|
|
except:
|
|
raise faults.BadSlotValue(slot, value)
|
|
|
|
def convertValueIds(
|
|
self, slot, value, sourceDispatcherId, destinationDispatcherId):
|
|
return value.replace(sourceDispatcherId, destinationDispatcherId)
|
|
|
|
def equals(self, kind):
|
|
if not BaseKind.equals(self, kind):
|
|
return 0
|
|
return self.serverRoles == kind.serverRoles
|
|
|
|
def getServerRoles(self):
|
|
return self.serverRoles
|
|
|
|
def getValues(self, slot, fields):
|
|
valuesGetterName = self.valuesGetterName
|
|
if valuesGetterName is None:
|
|
raise 'FIXME: getValues called while valuesGetterName was not set'
|
|
currentSlot = slot
|
|
while currentSlot is not None:
|
|
container = currentSlot.getContainer()
|
|
try:
|
|
valuesGetter = getattr(container, valuesGetterName)
|
|
except AttributeError:
|
|
currentSlot = currentSlot.parent
|
|
continue
|
|
return valuesGetter(slot, fields)
|
|
|
|
return []
|
|
|
|
def includes(self, kind):
|
|
if BaseKind.includes(self, kind):
|
|
return 1
|
|
if self.getName() != kind.getName():
|
|
return 0
|
|
if not self.serverRoles:
|
|
return 1
|
|
if not kind.serverRoles:
|
|
return 0
|
|
for kindServerRole in kind.serverRoles:
|
|
if not kindServerRole in self.serverRoles:
|
|
return 0
|
|
return 1
|
|
|
|
def intersects(self, kind):
|
|
if BaseKind.intersects(self, kind):
|
|
return 1
|
|
if self.getName() != kind.getName():
|
|
return 0
|
|
if not self.serverRoles or not kind.serverRoles:
|
|
return 1
|
|
for kindServerRole in kind.serverRoles:
|
|
if kindServerRole in self.serverRoles:
|
|
return 1
|
|
return 0
|
|
|
|
def removeValueIds(self, slot, value, rolesToKeep):
|
|
if not commonTools.extractRole(value) in rolesToKeep:
|
|
return None
|
|
return value
|
|
|
|
def repairValue(self, slot, value, toVersion):
|
|
if toVersion == 4000:
|
|
return repairId(value)
|
|
return None
|
|
register(Id)
|
|
|
|
|
|
class Integer(BaseKind):
|
|
category = N_('Numbers')
|
|
|
|
containerNames = ['Any']
|
|
|
|
defaultValue_kindName = 'Integer'
|
|
|
|
max = None
|
|
max_kind_label = N_('Maximum')
|
|
max_kindName = 'Integer'
|
|
|
|
min = None
|
|
min_kind_label = N_('Minimum')
|
|
min_kindName = 'Integer'
|
|
|
|
name = N_('Integer Number')
|
|
|
|
def getOrderedLayoutSlotNames(self, parentSlot = None):
|
|
slotNames = BaseKind.getOrderedLayoutSlotNames(
|
|
self, parentSlot = parentSlot)
|
|
slotNames = slotNames[:]
|
|
i = slotNames.index('defaultValue')
|
|
slotNames[i:i] = ['min', 'max']
|
|
return slotNames
|
|
|
|
def checkModelValue(self, slot, value):
|
|
BaseKind.checkModelValue(self, slot, value)
|
|
if value and type(value) not in [types.IntType, types.LongType]:
|
|
raise faults.BadSlotValue(slot, value)
|
|
register(Integer)
|
|
|
|
|
|
class IntegerChoice(Choice):
|
|
defaultValue_kindName = 'IntegerChoice'
|
|
|
|
name = N_('Integer Choice')
|
|
|
|
titles_kind_keyKind_valueName = 'Integer'
|
|
|
|
values_kind_itemKind_valueName = 'Integer'
|
|
|
|
def checkModelValue(self, slot, value):
|
|
Choice.checkModelValue(self, slot, value)
|
|
if value and type(value) is not types.IntType:
|
|
raise faults.BadSlotValue(slot, value)
|
|
register(IntegerChoice)
|
|
|
|
|
|
class LanguageChoice(Choice):
|
|
category = N_('Choice')
|
|
|
|
containerNames = ['Any']
|
|
|
|
defaultValue_kindName = 'LanguageChoice'
|
|
|
|
name = N_('Language')
|
|
|
|
values = translation.languageKeys
|
|
register(LanguageChoice)
|
|
|
|
|
|
class Link(BaseKind):
|
|
## category = N_('Compound')
|
|
|
|
defaultValue_kindName = 'Link'
|
|
|
|
name = N_('Link')
|
|
|
|
def checkModelValue(self, slot, value):
|
|
BaseKind.checkModelValue(self, slot, value)
|
|
if value and (type(value) not in [types.ListType, types.TupleType]
|
|
or len(value) != 2):
|
|
raise faults.BadSlotValue(slot, value)
|
|
|
|
def convertValueIds(
|
|
self, slot, value, sourceDispatcherId, destinationDispatcherId):
|
|
name, url = value
|
|
if url.startswith('id:'):
|
|
url = url.replace(sourceDispatcherId, destinationDispatcherId)
|
|
return (name, url)
|
|
|
|
def removeValueIds(self, slot, value, rolesToKeep):
|
|
name, url = value
|
|
if url.startswith('id:') \
|
|
and not commonTools.extractRole(url[3:]) in rolesToKeep:
|
|
return None
|
|
return value
|
|
|
|
def repairValue(self, slot, value, toVersion):
|
|
if toVersion == 4000:
|
|
name, url = value
|
|
if url.startswith('id:'):
|
|
newId = repairId(url[3:])
|
|
if newId:
|
|
return (name, 'id:' + newId)
|
|
return None
|
|
register(Link)
|
|
|
|
|
|
class Mapping(BaseKind):
|
|
category = N_('Compound')
|
|
|
|
containerNames = ['Any']
|
|
|
|
defaultValue_kindName = 'Mapping'
|
|
|
|
deleteNullValues = 0
|
|
deleteNullValues_kindName = 'Boolean'
|
|
|
|
keyKind = None
|
|
keyKind_kind_isRequired = 1
|
|
keyKind_kindName = 'Kind'
|
|
|
|
name = N_('Mapping')
|
|
|
|
requiredCount = 0
|
|
requiredCount_kindName = 'Integer'
|
|
|
|
valueKind = None
|
|
valueKind_kind_isRequired = 1
|
|
valueKind_kindName = 'Kind'
|
|
|
|
widgetName = 'Mapping'
|
|
|
|
def buildKinds(self):
|
|
# Should be converted to a class method, when porting Glasnost to
|
|
# Python 2.2.
|
|
BaseKind.buildKinds(self)
|
|
|
|
if hasattr(self, 'keyKind_valueName') \
|
|
and self.keyKind_valueName is not None:
|
|
baseClasses = self.getC3ClassLinearization()
|
|
keyKindOptionNames = [key
|
|
for key in self.__dict__.keys()
|
|
if key.startswith('keyKind_value_')]
|
|
for baseClass in baseClasses:
|
|
for key in baseClass.__dict__.keys():
|
|
if key.startswith('keyKind_value_') \
|
|
and not key in keyKindOptionNames:
|
|
keyKindOptionNames.append(key)
|
|
keyKindOptions = {}
|
|
for keyKindOptionName in keyKindOptionNames:
|
|
keyKindOptions[keyKindOptionName[len('keyKind_value_'):]
|
|
] = getattr(self, keyKindOptionName)
|
|
keyKind = commonTools.newThing('kind', self.keyKind_valueName)
|
|
keyKind.buildOptions(keyKindOptions)
|
|
self.__class__.keyKind = keyKind
|
|
|
|
if hasattr(self, 'valueKind_valueName') \
|
|
and self.valueKind_valueName is not None:
|
|
baseClasses = self.getC3ClassLinearization()
|
|
valueKindOptionNames = [key
|
|
for key in self.__dict__.keys()
|
|
if key.startswith('valueKind_value_')]
|
|
for baseClass in baseClasses:
|
|
for key in baseClass.__dict__.keys():
|
|
if key.startswith('valueKind_value_') \
|
|
and not key in valueKindOptionNames:
|
|
valueKindOptionNames.append(key)
|
|
valueKindOptions = {}
|
|
for valueKindOptionName in valueKindOptionNames:
|
|
valueKindOptions[valueKindOptionName[len('valueKind_value_'):]
|
|
] = getattr(self, valueKindOptionName)
|
|
valueKind = commonTools.newThing('kind', self.valueKind_valueName)
|
|
valueKind.buildOptions(valueKindOptions)
|
|
self.__class__.valueKind = valueKind
|
|
|
|
def buildOptions(self, options):
|
|
baseClasses = self.getC3ClassLinearization()
|
|
keyKindOptionNames = [key
|
|
for key in self.__dict__.keys()
|
|
if key.startswith('keyKind_value_')]
|
|
for baseClass in baseClasses:
|
|
for key in baseClass.__dict__.keys():
|
|
if key.startswith('keyKind_value_') \
|
|
and not key in keyKindOptionNames:
|
|
keyKindOptionNames.append(key)
|
|
keyKindOptions = {}
|
|
for keyKindOptionName in keyKindOptionNames:
|
|
keyKindOptions[keyKindOptionName[len('keyKind_value_'):]
|
|
] = getattr(self, keyKindOptionName)
|
|
keyKindOptionNames = [key
|
|
for key in options.keys()
|
|
if key.startswith('keyKind_value_')]
|
|
for keyKindOptionName in keyKindOptionNames:
|
|
keyKindOptions[keyKindOptionName[len('keyKind_value_'):]
|
|
] = options[keyKindOptionName]
|
|
del options[keyKindOptionName]
|
|
if options.has_key('keyKind_valueName'):
|
|
keyKindName = options['keyKind_valueName']
|
|
del options['keyKind_valueName']
|
|
elif hasattr(self, 'keyKind_valueName'):
|
|
keyKindName = self.keyKind_valueName
|
|
else:
|
|
keyKindName = None
|
|
|
|
valueKindOptionNames = [key
|
|
for key in self.__dict__.keys()
|
|
if key.startswith('valueKind_value_')]
|
|
for baseClass in baseClasses:
|
|
for key in baseClass.__dict__.keys():
|
|
if key.startswith('valueKind_value_') \
|
|
and not key in valueKindOptionNames:
|
|
valueKindOptionNames.append(key)
|
|
valueKindOptions = {}
|
|
for valueKindOptionName in valueKindOptionNames:
|
|
valueKindOptions[valueKindOptionName[len('valueKind_value_'):]
|
|
] = getattr(self, valueKindOptionName)
|
|
valueKindOptionNames = [key
|
|
for key in options.keys()
|
|
if key.startswith('valueKind_value_')]
|
|
for valueKindOptionName in valueKindOptionNames:
|
|
valueKindOptions[valueKindOptionName[len('valueKind_value_'):]
|
|
] = options[valueKindOptionName]
|
|
del options[valueKindOptionName]
|
|
if options.has_key('valueKind_valueName'):
|
|
valueKindName = options['valueKind_valueName']
|
|
del options['valueKind_valueName']
|
|
elif hasattr(self, 'valueKind_valueName'):
|
|
valueKindName = self.valueKind_valueName
|
|
else:
|
|
valueKindName = None
|
|
|
|
BaseKind.buildOptions(self, options)
|
|
|
|
if keyKindName is not None:
|
|
keyKind = commonTools.newThing('kind', keyKindName)
|
|
keyKind.buildOptions(keyKindOptions)
|
|
self.keyKind = keyKind
|
|
|
|
if valueKindName is not None:
|
|
valueKind = commonTools.newThing('kind', valueKindName)
|
|
valueKind.buildOptions(valueKindOptions)
|
|
self.valueKind = valueKind
|
|
|
|
def checkModelValue(self, slot, value):
|
|
BaseKind.checkModelValue(self, slot, value)
|
|
if self.requiredCount > 0:
|
|
if value is None:
|
|
raise faults.MissingSlotValue(slot)
|
|
if len(value) < self.requiredCount:
|
|
raise faults.BadSlotValue(slot, value)
|
|
if value and type(value) is not types.DictType:
|
|
raise faults.BadSlotValue(slot, value)
|
|
|
|
def convertValueIds(
|
|
self, slot, value, sourceDispatcherId, destinationDispatcherId):
|
|
keyIndex = 0
|
|
for key, val in value.items():
|
|
keySlot = self.getItemKeySlot(slot, keyIndex)
|
|
newKey = keySlot.getKind().convertValueIds(
|
|
keySlot, key, sourceDispatcherId, destinationDispatcherId)
|
|
if newKey != key:
|
|
del value[key]
|
|
value[newKey] = val
|
|
keyIndex += 1
|
|
for key, val in value.items():
|
|
valueSlot = self.getItemValueSlot(slot, key)
|
|
newVal = valueSlot.getKind().convertValueIds(
|
|
valueSlot, val, sourceDispatcherId, destinationDispatcherId)
|
|
if newVal != val:
|
|
value[key] = newVal
|
|
return value
|
|
|
|
def exportValueToXmlRpc(self, slot, value):
|
|
if value is None:
|
|
return {}
|
|
exportedValue = {}
|
|
keyIndex = 0
|
|
try:
|
|
value.items()
|
|
except:
|
|
raise str((self, slot, value))
|
|
for key, itemValue in value.items():
|
|
keySlot = self.getItemKeySlot(slot, keyIndex)
|
|
exportedKey = keySlot.getKind().exportValueToXmlRpc(keySlot, key)
|
|
valueSlot = self.getItemValueSlot(slot, key)
|
|
exportedItemValue = valueSlot.getKind().exportValueToXmlRpc(
|
|
valueSlot, itemValue)
|
|
exportedValue[exportedKey] = exportedItemValue
|
|
keyIndex += 1
|
|
return exportedValue
|
|
|
|
def getItemKeyKind(self, index):
|
|
return self.keyKind
|
|
|
|
def getItemKeySlot(self, slot, index):
|
|
return slots.ItemKey(index, parent = slot)
|
|
|
|
def getItemKeyValueKind(self, key):
|
|
return self.valueKind
|
|
|
|
def getItemKeyValueSlot(self, slot):
|
|
return slots.ItemKeyValue(parent = slot)
|
|
|
|
def getItemValueKind(self, key):
|
|
return self.valueKind
|
|
|
|
def getItemValueSlot(self, slot, key):
|
|
return slots.ItemValue(key, parent = slot)
|
|
|
|
def getModelSlotByPath(self, slot, path):
|
|
if path.startswith('self'):
|
|
path = path[len('self'):]
|
|
if not path:
|
|
return slot
|
|
if path.startswith('.keys()[') and ']' in path:
|
|
index = int(path[len('.keys()['):path.index(']')])
|
|
return self.getItemKeyKind(index).getModelSlotByPath(
|
|
self.getItemKeySlot(slot, index), path[path.index(']') + 1:])
|
|
if path[0] != '[' or not ']' in path:
|
|
raise Exception('Path "%s" not found' % path)
|
|
key = eval(path[1:path.index(']')], {})
|
|
return self.getItemValueKind(key).getModelSlotByPath(
|
|
self.getItemValueSlot(slot, key), path[path.index(']') + 1:])
|
|
|
|
def importValueFromXmlRpc(self, slot, importedValue):
|
|
if importedValue is None:
|
|
return {}
|
|
value = {}
|
|
slot.value = value
|
|
keyIndex = 0
|
|
for importedKey, importedItemValue in importedValue.items():
|
|
keySlot = self.getItemKeySlot(slot, keyIndex)
|
|
key = keySlot.getKind().importValueFromXmlRpc(keySlot, importedKey)
|
|
valueSlot = self.getItemValueSlot(slot, key)
|
|
itemValue = valueSlot.getKind().importValueFromXmlRpc(
|
|
valueSlot, importedItemValue)
|
|
value[key] = itemValue
|
|
keyIndex += 1
|
|
del slot.value
|
|
return value
|
|
|
|
def removeValueIds(self, slot, value, rolesToKeep):
|
|
keyIndex = 0
|
|
for key, val in value.items():
|
|
keySlot = self.getItemKeySlot(slot, keyIndex)
|
|
newKey = keySlot.getKind().removeValueIds(
|
|
keySlot, key, rolesToKeep)
|
|
if newKey != key:
|
|
del value[key]
|
|
keyIndex += 1
|
|
for key, val in value.items():
|
|
valueSlot = self.getItemValueSlot(slot, key)
|
|
newVal = valueSlot.getKind().removeValueIds(
|
|
valueSlot, val, rolesToKeep)
|
|
if newVal != val:
|
|
del value[key]
|
|
if not value:
|
|
return None
|
|
return value
|
|
|
|
def repairValue(self, slot, value, toVersion):
|
|
if toVersion == 4000:
|
|
changed = 0
|
|
keyIndex = 0
|
|
for key, val in value.items():
|
|
keySlot = self.getItemKeySlot(slot, keyIndex)
|
|
newKey = keySlot.getKind().repairValue(keySlot, key, toVersion)
|
|
if newKey:
|
|
changed = 1
|
|
del value[key]
|
|
value[newKey] = val
|
|
keyIndex += 1
|
|
for key, val in value.items():
|
|
valueSlot = self.getItemValueSlot(slot, key)
|
|
newVal = valueSlot.getKind().repairValue(
|
|
valueSlot, val, toVersion)
|
|
if newVal:
|
|
changed = 1
|
|
value[key] = newVal
|
|
if changed:
|
|
return value
|
|
return None
|
|
register(Mapping)
|
|
|
|
|
|
class Marks(BaseKind):
|
|
## category = N_('Other')
|
|
|
|
defaultValue_kindName = 'Marks'
|
|
|
|
def convertValueIds(
|
|
self, slot, value, sourceDispatcherId, destinationDispatcherId):
|
|
for id, mark in value.items():
|
|
newId = id.replace(sourceDispatcherId, destinationDispatcherId)
|
|
if newId != id:
|
|
del value[id]
|
|
value[newId] = mark
|
|
return value
|
|
|
|
def exportValueToXmlRpc(self, slot, value):
|
|
exportedValue = {}
|
|
if value is not None:
|
|
for objectId, mark in value.items():
|
|
if mark is None:
|
|
exportedMark = -1
|
|
else:
|
|
exportedMark = mark
|
|
exportedValue[objectId] = exportedMark
|
|
return exportedValue
|
|
|
|
def importValueFromXmlRpc(self, slot, importedValue):
|
|
value = {}
|
|
slot.value = value
|
|
for objectId, importedMark in importedValue.items():
|
|
if importedMark == -1:
|
|
mark = None
|
|
else:
|
|
mark = importedMark
|
|
value[objectId] = mark
|
|
if not value:
|
|
value = None
|
|
del slot.value
|
|
return value
|
|
|
|
def removeValueIds(self, slot, value, rolesToKeep):
|
|
for id in value.keys():
|
|
if not commonTools.extractRole(id) in rolesToKeep:
|
|
del value[id]
|
|
if not value:
|
|
return None
|
|
return value
|
|
|
|
def repairValue(self, slot, value, toVersion):
|
|
if toVersion == 4000:
|
|
changed = 0
|
|
for id, mark in value.items():
|
|
newId = repairId(id)
|
|
if newId:
|
|
changed = 1
|
|
del value[id]
|
|
value[newId] = mark
|
|
if changed:
|
|
return value
|
|
return None
|
|
register(Marks)
|
|
|
|
|
|
class Memory(BaseKind):
|
|
## category = N_('Other')
|
|
|
|
defaultValue_kindName = 'Memory'
|
|
|
|
def checkModelValue(self, slot, value):
|
|
BaseKind.checkModelValue(self, slot, value)
|
|
if value and type(value) is not types.DictType:
|
|
raise faults.BadSlotValue(slot, value)
|
|
|
|
def convertValueIds(
|
|
self, slot, value, sourceDispatcherId, destinationDispatcherId):
|
|
for serverId, serverMemory in value.items():
|
|
newServerId = serverId.replace(
|
|
sourceDispatcherId, destinationDispatcherId)
|
|
if newServerId != serverId:
|
|
del value[serverId]
|
|
value[newServerId] = serverMemory
|
|
for i in range(len(serverMemory)):
|
|
itemId = serverMemory[i]
|
|
newItemId = itemId.replace(
|
|
sourceDispatcherId, destinationDispatcherId)
|
|
if newItemId != itemId:
|
|
serverMemory[i] = newItemId
|
|
return value
|
|
|
|
def removeValueIds(self, slot, value, rolesToKeep):
|
|
for serverId, serverMemory in value.items():
|
|
if not commonTools.extractRole(serverId) in rolesToKeep:
|
|
del value[serverId]
|
|
continue
|
|
indexesToDelete = []
|
|
for i in range(len(serverMemory)):
|
|
itemId = serverMemory[i]
|
|
if not commonTools.extractRole(itemId) in rolesToKeep:
|
|
indexesToDelete.append(i)
|
|
indexesToDelete.reverse()
|
|
for i in indexesToDelete:
|
|
del serverMemory[i]
|
|
if not serverMemory:
|
|
del value[serverId]
|
|
if not value:
|
|
return None
|
|
return value
|
|
register(Memory)
|
|
|
|
|
|
class PairwiseMatrix(BaseKind):
|
|
## category = N_('Other')
|
|
|
|
defaultValue_kindName = 'PairwiseMatrix'
|
|
|
|
def checkModelValue(self, slot, value):
|
|
BaseKind.checkModelValue(self, slot, value)
|
|
if value and type(value) is not types.DictType:
|
|
raise faults.BadSlotValue(slot, value)
|
|
|
|
def convertValueIds(
|
|
self, slot, value, sourceDispatcherId, destinationDispatcherId):
|
|
for id1, row in value.items():
|
|
newId1 = id1.replace(sourceDispatcherId, destinationDispatcherId)
|
|
if newId1 != id1:
|
|
del value[id1]
|
|
value[newId1] = row
|
|
for id2, score in row.items():
|
|
newId2 = id2.replace(
|
|
sourceDispatcherId, destinationDispatcherId)
|
|
if newId2 != id2:
|
|
del row[id2]
|
|
row[newId2] = score
|
|
return value
|
|
|
|
def removeValueIds(self, slot, value, rolesToKeep):
|
|
for id1, row in value.items():
|
|
if not commonTools.extractRole(id1) in rolesToKeep:
|
|
del value[id1]
|
|
continue
|
|
for id2, score in row.items():
|
|
if not commonTools.extractRole(id2) in rolesToKeep:
|
|
del row[id2]
|
|
if not row:
|
|
del value[id1]
|
|
if not value:
|
|
return None
|
|
return value
|
|
|
|
def repairValue(self, slot, value, toVersion):
|
|
if toVersion == 4000:
|
|
changed = 0
|
|
for id1, row in value.items():
|
|
newId1 = repairId(id1)
|
|
if newId1:
|
|
changed = 1
|
|
del value[id1]
|
|
value[newId1] = row
|
|
for id2, score in row.items():
|
|
newId2 = repairId(id2)
|
|
if newId2:
|
|
changed = 1
|
|
del row[id2]
|
|
row[newId2] = score
|
|
if changed:
|
|
return value
|
|
return None
|
|
register(PairwiseMatrix)
|
|
|
|
|
|
class Password(BaseKind):
|
|
category = N_('Text')
|
|
|
|
defaultValue_kindName = 'Password'
|
|
|
|
name = N_('Password')
|
|
|
|
widgetName = 'InputPassword'
|
|
|
|
def checkModelValue(self, slot, value):
|
|
BaseKind.checkModelValue(self, slot, value)
|
|
if value and type(value) is not types.StringType:
|
|
raise faults.BadSlotValue(slot, value)
|
|
register(Password)
|
|
|
|
|
|
class PythonIdentifier(BaseKind):
|
|
category = N_('Text')
|
|
|
|
defaultValue_kindName = 'PythonIdentifier'
|
|
|
|
name = N_('Python Identifier')
|
|
|
|
def checkModelValue(self, slot, value):
|
|
BaseKind.checkModelValue(self, slot, value)
|
|
if value and type(value) is not types.StringType:
|
|
raise faults.BadSlotValue(slot, value)
|
|
register(PythonIdentifier)
|
|
|
|
|
|
class Rating(BaseKind):
|
|
## category = N_('Other')
|
|
|
|
defaultValue_kindName = 'Rating'
|
|
|
|
def checkModelValue(self, slot, value):
|
|
BaseKind.checkModelValue(self, slot, value)
|
|
if value and type(value) is not types.DictType:
|
|
raise faults.BadSlotValue(slot, value)
|
|
|
|
def convertValueIds(
|
|
self, slot, value, sourceDispatcherId, destinationDispatcherId):
|
|
for k in ['wins', 'losses', 'ties']:
|
|
v = value[k]
|
|
for i in range(len(v)):
|
|
id = v[i]
|
|
newId = id.replace(sourceDispatcherId, destinationDispatcherId)
|
|
if newId != id:
|
|
v[i] = newId
|
|
return value
|
|
|
|
def removeValueIds(self, slot, value, rolesToKeep):
|
|
for k in ['wins', 'losses', 'ties']:
|
|
v = value[k]
|
|
r = range(len(v))
|
|
r.reverse()
|
|
for i in r:
|
|
id = v[i]
|
|
if not commonTools.extractRole(id) in rolesToKeep:
|
|
del v[i]
|
|
return value
|
|
|
|
def repairValue(self, slot, value, toVersion):
|
|
if toVersion == 4000:
|
|
changed = 0
|
|
for k in ['wins', 'losses', 'ties']:
|
|
v = value[k]
|
|
for i in range(len(v)):
|
|
id = v[i]
|
|
newId = repairId(id)
|
|
if newId:
|
|
changed = 1
|
|
v[i] = newId
|
|
if changed:
|
|
return value
|
|
return None
|
|
register(Rating)
|
|
|
|
|
|
class Sequence(AbstractSequence):
|
|
category = N_('Compound')
|
|
|
|
containerNames = ['Any']
|
|
|
|
defaultValue_kindName = 'Sequence'
|
|
|
|
itemKind = None
|
|
itemKind_kind_isRequired = 1
|
|
itemKind_kindName = 'Kind'
|
|
itemKind_valueName = None
|
|
|
|
name = N_('Sequence')
|
|
|
|
requiredCount = 0
|
|
requiredCount_kindName = 'Integer'
|
|
|
|
def buildKinds(self):
|
|
# Should be converted to a class method, when porting Glasnost to
|
|
# Python 2.2.
|
|
AbstractSequence.buildKinds(self)
|
|
|
|
if hasattr(self, 'itemKind_valueName') \
|
|
and self.itemKind_valueName is not None:
|
|
baseClasses = self.getC3ClassLinearization()
|
|
itemKindOptionNames = [key
|
|
for key in self.__dict__.keys()
|
|
if key.startswith('itemKind_value_')]
|
|
for baseClass in baseClasses:
|
|
for key in baseClass.__dict__.keys():
|
|
if key.startswith('itemKind_value_') \
|
|
and not key in itemKindOptionNames:
|
|
itemKindOptionNames.append(key)
|
|
itemKindOptions = {}
|
|
for itemKindOptionName in itemKindOptionNames:
|
|
itemKindOptions[itemKindOptionName[len('itemKind_value_'):]
|
|
] = getattr(self, itemKindOptionName)
|
|
itemKind = commonTools.newThing('kind', self.itemKind_valueName)
|
|
itemKind.buildOptions(itemKindOptions)
|
|
self.__class__.itemKind = itemKind
|
|
|
|
def buildOptions(self, options):
|
|
baseClasses = self.getC3ClassLinearization()
|
|
itemKindOptionNames = [key
|
|
for key in self.__dict__.keys()
|
|
if key.startswith('itemKind_value_')]
|
|
for baseClass in baseClasses:
|
|
for key in baseClass.__dict__.keys():
|
|
if key.startswith('itemKind_value_') \
|
|
and not key in itemKindOptionNames:
|
|
itemKindOptionNames.append(key)
|
|
itemKindOptions = {}
|
|
for itemKindOptionName in itemKindOptionNames:
|
|
itemKindOptions[itemKindOptionName[len('itemKind_value_'):]
|
|
] = getattr(self, itemKindOptionName)
|
|
itemKindOptionNames = [key
|
|
for key in options.keys()
|
|
if key.startswith('itemKind_value_')]
|
|
for itemKindOptionName in itemKindOptionNames:
|
|
itemKindOptions[itemKindOptionName[len('itemKind_value_'):]
|
|
] = options[itemKindOptionName]
|
|
del options[itemKindOptionName]
|
|
if options.has_key('itemKind_valueName'):
|
|
itemKindName = options['itemKind_valueName']
|
|
del options['itemKind_valueName']
|
|
else:
|
|
itemKindName = self.itemKind_valueName
|
|
|
|
AbstractSequence.buildOptions(self, options)
|
|
|
|
if itemKindName is not None:
|
|
itemKind = commonTools.newThing('kind', itemKindName)
|
|
itemKind.buildOptions(itemKindOptions)
|
|
self.itemKind = itemKind
|
|
|
|
def getItemKind(self, index):
|
|
return self.itemKind
|
|
|
|
def getModelLabel(self, slot):
|
|
if self.label:
|
|
return self.label
|
|
return self.itemKind.getModelLabelPlural(self.getItemSlot(slot, 0))
|
|
|
|
def getModelLabelPlural(self, slot):
|
|
if self.labelPlural:
|
|
return self.labelPlural
|
|
return self.itemKind.getModelLabelPlural(self.getItemSlot(slot, 0))
|
|
|
|
def includes(self, kind):
|
|
if AbstractSequence.includes(self, kind):
|
|
return 1
|
|
if not isinstance(kind, Sequence):
|
|
return 0
|
|
if self.itemKind is None:
|
|
return 1
|
|
if kind.itemKind is None:
|
|
return 0
|
|
return self.itemKind.includes(kind.itemKind)
|
|
|
|
def intersects(self, kind):
|
|
if AbstractSequence.intersects(self, kind):
|
|
return 1
|
|
if not isinstance(kind, Sequence):
|
|
return 0
|
|
if self.itemKind is None or kind.itemKind is None:
|
|
return 1
|
|
return self.itemKind.intersects(kind.itemKind)
|
|
register(Sequence)
|
|
|
|
|
|
class AcceptedRoles(Sequence):
|
|
balloonHelp = N_('Select accepted types of items.')
|
|
|
|
containerNames = ['Any', 'Sequence']
|
|
|
|
defaultValue_kindName = 'AcceptedRoles'
|
|
|
|
itemKind_value_allowAll = 1
|
|
itemKind_value_allowNone = 1
|
|
itemKind_valueName = 'ServerRole'
|
|
|
|
label = N_('Accepted Types')
|
|
|
|
name = N_('Accepted Roles')
|
|
|
|
requiredCount = 1
|
|
register(AcceptedRoles)
|
|
|
|
|
|
class ArgumentPins(Sequence):
|
|
defaultValue_kindName = 'ArgumentPins'
|
|
|
|
itemKind_valueName = 'OutputConnector'
|
|
|
|
label = N_('Argument Pins')
|
|
|
|
name = N_('Argument Pins')
|
|
|
|
def exportValueToXmlRpc(self, slot, value):
|
|
if value is None:
|
|
return []
|
|
exportedValue = []
|
|
for argumentNumber in range(len(value)):
|
|
if value[argumentNumber] is None:
|
|
itemExport = 0
|
|
else:
|
|
itemSlot = self.getItemSlot(slot, argumentNumber)
|
|
itemExport = itemSlot.getKind().exportValueToXmlRpc(
|
|
itemSlot, value[argumentNumber])
|
|
exportedValue.append(itemExport)
|
|
return exportedValue
|
|
|
|
def importValueFromXmlRpc(self, slot, importedValue):
|
|
if not importedValue:
|
|
return None
|
|
value = []
|
|
slot.value = value
|
|
for argumentNumber in range(len(importedValue)):
|
|
if importedValue[argumentNumber] == 0:
|
|
item = None
|
|
else:
|
|
itemSlot = self.getItemSlot(slot, argumentNumber)
|
|
item = itemSlot.getKind().importValueFromXmlRpc(
|
|
itemSlot, importedValue[argumentNumber])
|
|
value.append(item)
|
|
del slot.value
|
|
return value
|
|
register(ArgumentPins)
|
|
|
|
|
|
class UsersSet(Sequence):
|
|
balloonHelp = N_('Choose the user(s) of this object.')
|
|
|
|
containerNames = ['Any', 'Sequence']
|
|
|
|
defaultValue_kindName = 'UsersSet'
|
|
|
|
itemKind_value_permanentIds = [system.generalPublicId]
|
|
itemKind_value_serverRoles = ['groups', 'people']
|
|
itemKind_valueName = 'Id'
|
|
|
|
label = N_('Users')
|
|
|
|
name = N_('Users')
|
|
|
|
requiredCount = 1
|
|
register(UsersSet)
|
|
|
|
|
|
class AuthorsSet(UsersSet):
|
|
balloonHelp = N_('Choose the author(s) for this object.')
|
|
|
|
containerNames = ['Any', 'Sequence', 'UsersSet']
|
|
|
|
defaultValue_kindName = 'AuthorsSet'
|
|
|
|
label = N_('Authors')
|
|
|
|
name = N_('Authors')
|
|
register(AuthorsSet)
|
|
|
|
|
|
class Properties(Sequence):
|
|
importExport = 'private'
|
|
|
|
itemKind_value_valueThingCategory = 'other'
|
|
itemKind_value_valueThingName = 'Property'
|
|
itemKind_valueName = 'Thing'
|
|
|
|
label = N_('Properties')
|
|
|
|
name = N_('Properties')
|
|
|
|
def exportValueToXmlRpc(self, slot, value):
|
|
if value is None:
|
|
return []
|
|
exportedValue = []
|
|
for i in range(len(value)):
|
|
property = value[i]
|
|
propertySlot = self.getPropertySlot(slot, property.name)
|
|
exportedProperty = propertySlot.getKind().exportValueToXmlRpc(
|
|
propertySlot, property)
|
|
exportedValue.append(exportedProperty)
|
|
return exportedValue
|
|
|
|
def getItemSlot(self, slot, index):
|
|
return slots.PropertiesItem(index, parent = slot)
|
|
|
|
def getModelSlotByPath(self, slot, path):
|
|
if path.startswith('self'):
|
|
path = path[len('self'):]
|
|
if not path:
|
|
return slot
|
|
if path[0] != '[' or not ']' in path:
|
|
raise Exception('Path "%s" not found' % path)
|
|
key = eval(path[1:path.index(']')], {})
|
|
if type(key) in (types.StringType, types.UnicodeType):
|
|
# Key is a property name.
|
|
# FIXME: We should raise Exception('Path "%s" not found' % path),
|
|
# when there is no property named key.
|
|
kind = slot.getContainer().getDirectPropertyValueKind(key)
|
|
if kind is None:
|
|
kind = slot.getContainer().getPropertyValueKind(key)
|
|
kind = copy.deepcopy(kind)
|
|
property = commonTools.newThing('other', 'Property')
|
|
property.kind = kind
|
|
property.kindName = kind.getThingName()
|
|
property.name = key
|
|
return property.getSlotByPath(
|
|
path[path.index(']') + 1:],
|
|
parentSlot = slot.getContainer().getPropertySlot(
|
|
key, parentSlot = slot.parent))
|
|
else:
|
|
# Key is an integer index.
|
|
return self.getItemKind(key).getModelSlotByPath(
|
|
self.getItemSlot(slot, key), path[path.index(']') + 1:])
|
|
|
|
def getPropertySlot(self, slot, name):
|
|
return slots.Property(name, parent = slot)
|
|
|
|
def importValueFromXmlRpc(self, slot, importedValue):
|
|
if importedValue is None:
|
|
return []
|
|
value = []
|
|
slot.value = value
|
|
for i in range(len(importedValue)):
|
|
importedProperty = importedValue[i]
|
|
propertyName = importedProperty['name']
|
|
propertySlot = self.getPropertySlot(slot, propertyName)
|
|
value.append(propertySlot.getKind().importValueFromXmlRpc(
|
|
propertySlot, importedProperty))
|
|
del slot.value
|
|
return value
|
|
register(Properties)
|
|
|
|
|
|
class ReadersSet(UsersSet):
|
|
balloonHelp = N_(
|
|
'Select the people and groups who are allowed to read the item.')
|
|
|
|
containerNames = ['Any', 'Sequence', 'UsersSet']
|
|
|
|
defaultValue_kindName = 'ReadersSet'
|
|
|
|
label = N_('Readers')
|
|
|
|
name = N_('Readers')
|
|
register(ReadersSet)
|
|
|
|
|
|
class ResultPins(Sequence):
|
|
defaultValue_kindName = 'ResultPins'
|
|
|
|
itemKind_value_itemKind_value_itemKind_valueName = 'InputConnector'
|
|
itemKind_value_itemKind_valueName = 'Sequence'
|
|
itemKind_valueName = 'Sequence'
|
|
|
|
label = N_('Result Pins')
|
|
|
|
name = N_('Result Pins')
|
|
|
|
def convertValueIds(self, slot, value, sourceDispatcherId,
|
|
destinationDispatcherId):
|
|
for resultNumber in range(len(value)):
|
|
resultPin = value[resultNumber]
|
|
if resultPin is None:
|
|
continue
|
|
resultPinSlot = self.getItemSlot(slot, resultNumber)
|
|
for depth in range(len(resultPin)):
|
|
resultConnectors = resultPin[depth]
|
|
if resultConnectors is None:
|
|
continue
|
|
resultConnectorsSlot = self.getItemSlot(resultPinSlot, depth)
|
|
for index in range(len(resultConnectors)):
|
|
resultConnector = resultConnectors[index]
|
|
if resultConnector is None:
|
|
continue
|
|
resultConnectorSlot = self.getItemSlot(
|
|
resultConnectorsSlot, index)
|
|
resultConnectorSlot.getKind().convertValueIds(
|
|
resultConnectorSlot, resultConnector,
|
|
sourceDispatcherId, destinationDispatcherId)
|
|
return value
|
|
|
|
def exportValueToXmlRpc(self, slot, value):
|
|
if value is None:
|
|
return []
|
|
resultPinsExport = []
|
|
for resultNumber in range(len(value)):
|
|
resultPin = value[resultNumber]
|
|
if resultPin is None:
|
|
resultPinExport = 0
|
|
else:
|
|
resultPinSlot = self.getItemSlot(slot, resultNumber)
|
|
resultPinExport = []
|
|
for depth in range(len(resultPin)):
|
|
resultConnectors = resultPin[depth]
|
|
if resultConnectors is None:
|
|
resultConnectorsExport = 0
|
|
else:
|
|
resultConnectorsSlot = self.getItemSlot(
|
|
resultPinSlot, depth)
|
|
resultConnectorsExport = []
|
|
for index in range(len(resultConnectors)):
|
|
resultConnector = resultConnectors[index]
|
|
if resultConnector is None:
|
|
resultConnectorExport = 0
|
|
else:
|
|
resultConnectorSlot = self.getItemSlot(
|
|
resultConnectorsSlot, index)
|
|
resultConnectorExport = \
|
|
commonTools.newThing(
|
|
'kind', 'InputConnector'
|
|
).exportValueToXmlRpc(
|
|
resultConnectorSlot, resultConnector)
|
|
resultConnectorsExport.append(
|
|
resultConnectorExport)
|
|
resultPinExport.append(resultConnectorsExport)
|
|
resultPinsExport.append(resultPinExport)
|
|
return resultPinsExport
|
|
|
|
def importValueFromXmlRpc(self, slot, resultPinsImport):
|
|
if not resultPinsImport:
|
|
return None
|
|
resultPins = []
|
|
for resultNumber in range(len(resultPinsImport)):
|
|
resultPinImport = resultPinsImport[resultNumber]
|
|
if resultPinImport == 0:
|
|
resultPin = None
|
|
else:
|
|
resultPinSlot = self.getItemSlot(slot, resultNumber)
|
|
resultPin = []
|
|
for depth in range(len(resultPinImport)):
|
|
resultConnectorsImport = resultPinImport[depth]
|
|
if resultConnectorsImport == 0:
|
|
resultConnectors = None
|
|
else:
|
|
resultConnectorsSlot = self.getItemSlot(
|
|
resultPinSlot, depth)
|
|
resultConnectors = []
|
|
for index in range(len(resultConnectorsImport)):
|
|
resultConnectorImport = resultConnectorsImport[
|
|
index]
|
|
if resultConnectorImport == 0:
|
|
resultConnector = None
|
|
else:
|
|
resultConnectorSlot = self.getItemSlot(
|
|
resultConnectorsSlot, index)
|
|
resultConnector = \
|
|
commonTools.newThing(
|
|
'kind', 'InputConnector'
|
|
).importValueFromXmlRpc(
|
|
resultConnectorSlot,
|
|
resultConnectorImport)
|
|
resultConnectors.append(resultConnector)
|
|
resultPin.append(resultConnectors)
|
|
resultPins.append(resultPin)
|
|
return resultPins
|
|
|
|
def removeValueIds(self, slot, value, rolesToKeep):
|
|
for resultNumber in range(len(value)):
|
|
resultPin = value[resultNumber]
|
|
if resultPin is None:
|
|
continue
|
|
resultPinSlot = self.getItemSlot(slot, resultNumber)
|
|
for depth in range(len(resultPin)):
|
|
resultConnectors = resultPin[depth]
|
|
if resultConnectors is None:
|
|
continue
|
|
resultConnectorsSlot = self.getItemSlot(resultPinSlot, depth)
|
|
indexesToDelete = []
|
|
for index in range(len(resultConnectors)):
|
|
resultConnector = resultConnectors[index]
|
|
if resultConnector is None:
|
|
continue
|
|
resultConnectorSlot = self.getItemSlot(
|
|
resultConnectorsSlot, index)
|
|
newConnector = resultConnectorSlot.getKind(
|
|
).removeValueIds(resultConnectorSlot,
|
|
resultConnector, rolesToKeep)
|
|
if newConnector != resultConnector:
|
|
indexesToDelete.append(index)
|
|
indexesToDelete.reverse()
|
|
for index in indexesToDelete:
|
|
del resultConnectors[index]
|
|
if not resultConnectors:
|
|
resultPin[depth] = None
|
|
# FIXME: To do : Simplify the result.
|
|
return value
|
|
register(ResultPins)
|
|
|
|
|
|
class ServerId(Id):
|
|
category = N_('Glasnost')
|
|
|
|
containerNames = ['Any', 'String']
|
|
|
|
defaultValue_kindName = 'ServerId'
|
|
|
|
name = N_('Server ID')
|
|
|
|
## widgetName = 'SelectServerId'
|
|
widget_size = 40
|
|
widgetName = 'InputText'
|
|
|
|
def removeValueIds(self, slot, value, rolesToKeep):
|
|
return value
|
|
register(ServerId)
|
|
|
|
|
|
class ServerRole(Choice):
|
|
allowAll = 0
|
|
allowAll_kindName = 'Boolean'
|
|
|
|
allowNone = 0
|
|
allowNone_kindName = 'Boolean'
|
|
|
|
category = N_('Glasnost')
|
|
|
|
containerNames = ['Any', 'String']
|
|
|
|
defaultValue_kindName = 'ServerRole'
|
|
|
|
name = N_('Server Role')
|
|
|
|
def getLabels(self, slot, fields):
|
|
roles = self.getValues(slot, fields)
|
|
labels = {}
|
|
for role in roles:
|
|
if role in [None, '__all__']:
|
|
continue
|
|
common = getCommonForServerRole(role)
|
|
if common is None:
|
|
label = role
|
|
else:
|
|
label = common.objectsNameCapitalized
|
|
labels[role] = label
|
|
return labels
|
|
|
|
def getValues(self, slot, fields):
|
|
from glasnost.proxy.DispatcherProxy import getRegisteredRoles
|
|
values = []
|
|
if self.allowNone:
|
|
values.append(None)
|
|
if self.allowAll:
|
|
values.append('__all__')
|
|
values += getRegisteredRoles(context.getVar('dispatcherId'))
|
|
return values
|
|
register(ServerRole)
|
|
|
|
|
|
class SlotName(Choice):
|
|
category = N_('Glasnost')
|
|
|
|
defaultValue_kindName = 'SlotName'
|
|
|
|
name = N_('Slot Name')
|
|
register(SlotName)
|
|
|
|
|
|
class Source(BaseKind):
|
|
category = N_('Glasnost')
|
|
|
|
defaultValue_kindName = 'Source'
|
|
|
|
def checkModelValue(self, slot, value):
|
|
BaseKind.checkModelValue(self, slot, value)
|
|
if value and type(value) is not types.StringType:
|
|
raise faults.BadSlotValue(slot, value)
|
|
|
|
def convertValueIds(
|
|
self, slot, value, sourceDispatcherId, destinationDispatcherId):
|
|
return value.replace(sourceDispatcherId, destinationDispatcherId)
|
|
|
|
def removeValueIds(self, slot, value, rolesToKeep):
|
|
if not commonTools.extractRole(value) in rolesToKeep:
|
|
return None
|
|
return value
|
|
register(Source)
|
|
|
|
|
|
class String(BaseKind):
|
|
category = N_('Text')
|
|
|
|
containerNames = ['Any']
|
|
|
|
defaultValue_kindName = 'String'
|
|
|
|
isTranslatable = 1
|
|
isTranslatable_kind_importExport = 'public'
|
|
|
|
name = N_('String')
|
|
|
|
possibleWidgetNames = ['InputText', 'TextArea']
|
|
|
|
useFileStorage_kind_importExport = 'public'
|
|
|
|
def checkModelValue(self, slot, value):
|
|
BaseKind.checkModelValue(self, slot, value)
|
|
if value and type(value) is not types.StringType:
|
|
raise faults.BadSlotValue(slot, value)
|
|
|
|
def getCmpFunction(self):
|
|
return locale.strcoll
|
|
register(String)
|
|
|
|
|
|
class Structure(AbstractSequence):
|
|
category = N_('Compound')
|
|
|
|
containerNames = ['Any']
|
|
|
|
defaultValue_kindName = 'Structure'
|
|
|
|
name = N_('Structure')
|
|
|
|
parameters = None
|
|
parameters_kind_itemKind_value_valueThingCategory = 'other'
|
|
parameters_kind_itemKind_value_valueThingName = 'Parameter'
|
|
parameters_kind_itemKind_valueName = 'Thing'
|
|
parameters_kindName = 'Sequence'
|
|
|
|
def getItemKind(self, index):
|
|
if self.parameters is None or index >= len(self.parameters):
|
|
return None
|
|
return self.parameters[index].kind
|
|
register(Structure)
|
|
|
|
|
|
class Thing(BaseKind):
|
|
category = N_('Compound')
|
|
|
|
containerNames = ['Any']
|
|
|
|
defaultValue_kindName = 'Thing'
|
|
|
|
name = N_('Thing')
|
|
|
|
valueThingCategory = None
|
|
valueThingCategory_kindName = 'String'
|
|
|
|
valueThingName = None
|
|
valueThingName_kindName = 'String'
|
|
|
|
valueThingNameSlotName = None
|
|
valueThingNameSlotName_kindName = 'PythonIdentifier'
|
|
|
|
def checkModelValue(self, slot, value):
|
|
BaseKind.checkModelValue(self, slot, value)
|
|
if value and type(value) is not types.InstanceType:
|
|
raise faults.BadSlotValue(slot, value)
|
|
|
|
def convertValueIds(self, slot, value, sourceDispatcherId,
|
|
destinationDispatcherId):
|
|
if value is None:
|
|
return None
|
|
value.convertIds(
|
|
sourceDispatcherId, destinationDispatcherId, parentSlot = slot)
|
|
return value
|
|
|
|
def equals(self, kind):
|
|
if not BaseKind.equals(self, kind):
|
|
return 0
|
|
return self.valueThingCategory == kind.valueThingCategory \
|
|
and self.valueThingName == kind.valueThingName
|
|
|
|
def exportValueToXmlRpc(self, slot, value):
|
|
if value is None:
|
|
return None
|
|
return value.exportToXmlRpc(parentSlot = slot)
|
|
|
|
def getModelSlotByPath(self, slot, path):
|
|
value = slot.getValue()
|
|
if value is None:
|
|
value = commonTools.newThing(
|
|
self.valueThingCategory, self.getValueThingName(slot))
|
|
slot = slot.detach(value)
|
|
return value.getSlotByPath(path, parentSlot = slot)
|
|
|
|
def getValueThingName(self, slot):
|
|
if self.valueThingNameSlotName is not None:
|
|
container = slot.getContainer()
|
|
valueThingName = container.getSlot(
|
|
self.valueThingNameSlotName, parentSlot = slot.parent
|
|
).getValue()
|
|
if valueThingName is not None:
|
|
return valueThingName
|
|
return self.valueThingName
|
|
|
|
def getValueThingNameFromFields(self, slot, fields):
|
|
if self.valueThingNameSlotName is not None:
|
|
container = slot.getContainer()
|
|
valueThingName = container.getSlot(
|
|
self.valueThingNameSlotName, parentSlot = slot.parent
|
|
).getField(fields)
|
|
if valueThingName is not None:
|
|
return valueThingName
|
|
return self.valueThingName
|
|
|
|
def importValueFromXmlRpc(self, slot, importedValue):
|
|
if importedValue is None:
|
|
return None
|
|
value = commonTools.newThing(
|
|
importedValue['__thingCategory__'],
|
|
importedValue['__thingName__'])
|
|
slot.value = value
|
|
value.importFromXmlRpc(importedValue, parentSlot = slot)
|
|
del slot.value
|
|
return value
|
|
|
|
def includes(self, kind):
|
|
if BaseKind.includes(self, kind):
|
|
return 1
|
|
if self.getName() != kind.getName():
|
|
return 0
|
|
if self.valueThingCategory is None:
|
|
return 1
|
|
if self.valueThingCategory != kind.valueThingCategory:
|
|
return 0
|
|
if self.valueThingName is None:
|
|
return 1
|
|
return self.valueThingName == kind.valueThingName
|
|
|
|
def intersects(self, kind):
|
|
if BaseKind.intersects(self, kind):
|
|
return 1
|
|
if self.getName() != kind.getName():
|
|
return 0
|
|
if self.valueThingCategory is None or kind.valueThingCategory is None:
|
|
return 1
|
|
if self.valueThingCategory != kind.valueThingCategory:
|
|
return 0
|
|
if self.valueThingName is None or kind.valueThingName is None:
|
|
return 1
|
|
return self.valueThingName == kind.valueThingName
|
|
|
|
def removeValueIds(self, slot, value, rolesToKeep):
|
|
if value is None:
|
|
return None
|
|
value.removeIds(rolesToKeep, parentSlot = slot)
|
|
return value
|
|
|
|
def repairValue(self, slot, value, toVersion):
|
|
if toVersion == 4000:
|
|
changed = value.repair(toVersion, parentSlot = slot)
|
|
if changed:
|
|
return value
|
|
return None
|
|
register(Thing)
|
|
|
|
|
|
class Union(BaseKind):
|
|
category = N_('Glasnost')
|
|
|
|
containerNames = ['Any']
|
|
|
|
defaultValue_kindName = 'Union'
|
|
|
|
isPractical = 0
|
|
|
|
items = None
|
|
items_kind_itemKind_valueName = 'Kind'
|
|
items_kind_label = N_('Items')
|
|
items_kindName = 'Sequence'
|
|
|
|
name = N_('Union')
|
|
|
|
def equals(self, kind):
|
|
if not BaseKind.equals(self, kind):
|
|
return 0
|
|
if not self.items or not kind.items:
|
|
return 0
|
|
if len(self.items) != len(kind.items):
|
|
return 0
|
|
for item in self.items:
|
|
for kindItem in kind.items:
|
|
if item.equals(kindItem):
|
|
break
|
|
else:
|
|
return 0
|
|
return 1
|
|
|
|
def includes(self, kind):
|
|
if BaseKind.includes(self, kind):
|
|
return 1
|
|
if self.items is not None:
|
|
for item in self.items:
|
|
if item.includes(kind):
|
|
return 1
|
|
return 0
|
|
|
|
def intersects(self, kind):
|
|
if BaseKind.intersects(self, kind):
|
|
return 1
|
|
if self.getName() != kind.getName():
|
|
if not self.items or not kind.items:
|
|
return 0
|
|
for item in self.items:
|
|
for kindItem in kind.items:
|
|
if item.intersects(kindItem):
|
|
return 1
|
|
return 0
|
|
if self.items is not None:
|
|
for item in self.items:
|
|
if item.intersects(kind):
|
|
return 1
|
|
return 0
|
|
register(Union)
|
|
|
|
|
|
class CreationTime(Time):
|
|
## defaultValue = 'now'
|
|
defaultValue_kindName = 'CreationTime'
|
|
|
|
importExport = 'from-server-only'
|
|
|
|
isAutomaticalyModified = 1
|
|
|
|
stateInEditMode = 'read-only'
|
|
|
|
label = N_('Creation Time')
|
|
|
|
name = N_('Creation Time')
|
|
|
|
def setAutomaticalValue(self, slot, init = 0):
|
|
if init:
|
|
slot.setValue(time.time())
|
|
register(CreationTime)
|
|
|
|
|
|
class ModificationTime(Time):
|
|
## defaultValue = 'now'
|
|
defaultValue_kindName = 'ModificationTime'
|
|
|
|
importExport = 'from-server-only'
|
|
|
|
isAutomaticalyModified = 1
|
|
|
|
stateInEditMode = 'read-only'
|
|
|
|
label = N_('Modification Time')
|
|
|
|
name = N_('Modification Time')
|
|
|
|
def setAutomaticalValue(self, slot, init = 0):
|
|
slot.setValue(time.time())
|
|
register(ModificationTime)
|
|
|
|
|
|
class Token(BaseKind):
|
|
category = N_('Text')
|
|
|
|
containerNames = ['Any', 'String']
|
|
|
|
defaultValue_kindName = 'Token'
|
|
|
|
name = N_('Token')
|
|
|
|
def checkModelValue(self, slot, value):
|
|
BaseKind.checkModelValue(self, slot, value)
|
|
if value and type(value) is not types.StringType:
|
|
raise faults.BadSlotValue(slot, value)
|
|
register(Token)
|
|
|
|
|
|
class ApplicationToken(Token):
|
|
containerNames = ['Any', 'String', 'Token']
|
|
|
|
defaultValue_kindName = 'ApplicationToken'
|
|
|
|
name = N_('Application Token')
|
|
register(ApplicationToken)
|
|
|
|
|
|
class UserToken(Token):
|
|
containerNames = ['Any', 'String', 'Token']
|
|
|
|
defaultValue_kindName = 'UserToken'
|
|
|
|
name = N_('User Token')
|
|
register(UserToken)
|
|
|
|
|
|
class TranslationToAdd(BaseKind):
|
|
category = None
|
|
|
|
defaultValue_kindName = 'TranslationToAdd'
|
|
register(TranslationToAdd)
|
|
|
|
|
|
class TranslatorsSets(BaseKind):
|
|
defaultValue_kindName = 'TranslatorsSets'
|
|
|
|
def checkModelValue(self, slot, value):
|
|
BaseKind.checkModelValue(self, slot, value)
|
|
if value and type(value) is not types.DictType:
|
|
raise faults.BadSlotValue(slot, value)
|
|
|
|
def convertValueIds(
|
|
self, slot, value, sourceDispatcherId, destinationDispatcherId):
|
|
for translationName, translatorsSet in value.items():
|
|
if translatorsSet:
|
|
for i in range(len(translatorsSet)):
|
|
id = translatorsSet[i]
|
|
newId = id.replace(
|
|
sourceDispatcherId, destinationDispatcherId)
|
|
if newId != id:
|
|
translatorsSet[i] = newId
|
|
return value
|
|
|
|
def removeValueIds(self, slot, value, rolesToKeep):
|
|
for translationName, translatorsSet in value.items():
|
|
if translatorsSet:
|
|
r = range(len(translatorsSet))
|
|
r.reverse()
|
|
for i in r:
|
|
id = translatorsSet[i]
|
|
if not commonTools.extractRole(id) in rolesToKeep:
|
|
del translatorsSet[i]
|
|
if not translatorsSet:
|
|
del value[translationName]
|
|
if not value:
|
|
return None
|
|
return value
|
|
|
|
def repairValue(self, slot, value, toVersion):
|
|
if toVersion == 4000:
|
|
changed = 0
|
|
for translationName, translatorsSet in value.items():
|
|
if translatorsSet:
|
|
for i in range(len(translatorsSet)):
|
|
id = translatorsSet[i]
|
|
newId = repairId(id)
|
|
if newId:
|
|
changed = 1
|
|
translatorsSet[i] = newId
|
|
if changed:
|
|
return value
|
|
return None
|
|
register(TranslatorsSets)
|
|
|
|
|
|
class WritersSet(UsersSet):
|
|
balloonHelp = N_(
|
|
'Select the people and groups who are allowed to modify the item.')
|
|
|
|
containerNames = ['Any', 'Sequence', 'UsersSet']
|
|
|
|
defaultValue_kindName = 'WritersSet'
|
|
|
|
label = N_('Writers')
|
|
|
|
name = N_('Writers')
|
|
register(WritersSet)
|
|
|
|
|
|
class XChoice(Choice):
|
|
category = N_('Choice')
|
|
|
|
defaultValue_kindName = 'XChoice'
|
|
|
|
name = N_('Extended Choice')
|
|
|
|
widgetName = 'XSelect'
|
|
|
|
def checkModelValue(self, slot, value):
|
|
BaseKind.checkModelValue(self, slot, value)
|
|
|
|
def getGroupedValues(self, slot, fields):
|
|
return (self.groupNames, self.groupedValues)
|
|
|
|
register(XChoice)
|
|
|
|
|
|
class Fault(Thing):
|
|
category = N_('Glasnost')
|
|
|
|
defaultValue_kindName = 'Fault'
|
|
|
|
name = N_('Fault')
|
|
|
|
valueThingCategory = 'other'
|
|
|
|
valueThingName = 'Fault'
|
|
register(Fault)
|
|
|
|
|
|
class InputConnector(Thing):
|
|
category = N_('Glasnost')
|
|
|
|
defaultInput_kindName = 'InputConnector'
|
|
|
|
name = N_('Input Connector')
|
|
|
|
valueThingCategory = 'other'
|
|
|
|
valueThingName = 'InputConnector'
|
|
register(InputConnector)
|
|
|
|
|
|
class Kind(Thing):
|
|
defaultValue_kindName = 'Kind'
|
|
|
|
name = N_('Kind')
|
|
|
|
valueThingCategory = 'kind'
|
|
|
|
valueThingName = 'BaseKind'
|
|
register(Kind)
|
|
|
|
|
|
class KindName(Choice):
|
|
defaultValue_kindName = 'KindName'
|
|
|
|
name = N_('Kind Name')
|
|
|
|
## def __init__(self, **attributes):
|
|
## Choice.__init__(self, **attributes)
|
|
## self.values = [
|
|
## kindClass.getThingName.im_func(kindClass)
|
|
## for kindClass in commonTools.getAllThingClasses().values()
|
|
## if kindClass.thingCategory == 'kind']
|
|
|
|
def getGroupedValues(self, slot, fields):
|
|
categories = []
|
|
groupedValues = {}
|
|
for kindClass in commonTools.getAllThingClasses().values():
|
|
if kindClass.thingCategory != 'kind':
|
|
continue
|
|
if kindClass.category is None:
|
|
continue
|
|
if not kindClass.category in categories:
|
|
categories.append(kindClass.category)
|
|
groupedValues[kindClass.category] = []
|
|
groupedValues[kindClass.category].append(
|
|
kindClass.getThingName.im_func(kindClass))
|
|
return (categories, groupedValues) # groupNames, groupedValues
|
|
|
|
def getValues(self, slot, fields):
|
|
return [
|
|
kindClass.getThingName.im_func(kindClass)
|
|
for kindClass in commonTools.getAllThingClasses().values()
|
|
if kindClass.thingCategory == 'kind' \
|
|
and kindClass.category is not None]
|
|
register(KindName)
|
|
|
|
|
|
class OutputConnector(Thing):
|
|
category = N_('Glasnost')
|
|
|
|
defaultOutput_kindName = 'OutputConnector'
|
|
|
|
name = N_('Output Connector')
|
|
|
|
valueThingCategory = 'other'
|
|
|
|
valueThingName = 'OutputConnector'
|
|
register(OutputConnector)
|
|
|
|
|
|
class Upload(Thing):
|
|
category = N_('Compound')
|
|
|
|
defaultValue_kindName = 'Upload'
|
|
|
|
name = N_('Upload')
|
|
|
|
valueThingCategory = 'other'
|
|
|
|
valueThingName = 'Upload'
|
|
register(Upload)
|
|
|
|
|
|
class ValueHolder(Thing):
|
|
category = N_('Glasnost')
|
|
|
|
defaultValue_kindName = 'ValueHolder'
|
|
|
|
name = N_('Value Holder')
|
|
|
|
valueThingCategory = 'other'
|
|
|
|
valueThingName = 'ValueHolder'
|
|
register(ValueHolder)
|
|
|
|
|
|
class Widget(Thing):
|
|
defaultValue_kindName = 'Widget'
|
|
|
|
name = N_('Widget')
|
|
|
|
valueThingCategory = 'widget'
|
|
|
|
valueThingName = 'BaseWidget'
|
|
register(Widget)
|
|
|
|
|
|
class WidgetName(Choice):
|
|
defaultValue_kindName = 'WidgetName'
|
|
|
|
name = N_('Widget Name')
|
|
|
|
def getValues(self, slot, fields):
|
|
values = Choice.getValues(self, slot, fields)
|
|
if values:
|
|
return values
|
|
else:
|
|
return ['InputText']
|
|
register(WidgetName)
|
|
|