This repository has been archived on 2023-02-21. You can view files and clone it, but cannot push or open issues or pull requests.
expression/src/modules/xforms/descriptions.py

1189 lines
40 KiB
Python

# -*- coding: UTF-8 -*-
# Glasnost-XML
# By: Frederic Peters <fpeters@entrouvert.be>
# Emmanuel Raviart <eraviart@entrouvert.com>
#
# Copyright (C) 2003 Entr'ouvert & Emmanuel Raviart
# Copyright (C) 2004 Entr'ouvert, Frederic Peters & Emmanuel Raviart
#
# 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.
"""Descriptions Module
A description contains all informations, methods, etc, needed to properly
layout a XML data holder.
"""
import libxml2
import context
import dataholders
import elements
import html
import locations
import modules
import parsers
import xforms
class Control(elements.Element):
"""XForms Control."""
_inForm = False
isFieldLabelNeeded = True
def fillButtonLayout(self, layout):
"""Add the control to a buttons bar."""
return self.fillFieldValueLayout(self, layout)
def fillFieldChildLayout(self, layout):
filled = False
relevant = self.relevant
if not self.inForm and not relevant:
returnfilled
if relevant and self.isFieldLabelNeeded:
labelLayout = self.getFieldLabelLayout()
layout.append(labelLayout)
## balloonHelp = slot.getKind().balloonHelp
## if balloonHelp and not self.isReadOnly(slot):
## layout += X.div(_class = 'formHelp')(X.asIs(
## helpTextRegEx.sub(r'<a href="/help/\2">\1</a>', _(balloonHelp))))
cellLayout = self.getFieldValueLayout()
## if cellLayout is not None:
## if isinstance(cellLayout, X.array):
## tooltipCell = [x for x in cellLayout.children if x][0]
## else:
## tooltipCell = cellLayout
## if self.colSpan:
## cellLayout.setAttribute('class', ' '.join(
## [cellLayout.getAttribute('class'), 'fullwidth']))
## if slot.getObject().getError(slot.getPath()) and \
## not context.getVar('hideErrors'):
## layout.setAttribute('class', ' '.join(
## [layout.getAttribute('class'), 'error']))
## layout += self.getErrorLayout(slot, fields)
if cellLayout is not None:
layout.append(cellLayout)
filled = True
return filled
def fillFieldLayout(self, layout):
# See WidgetMixin.getEditFieldLayout.
filled = False
if not self.inForm and not self.relevant:
return filled
divLayout = html.div(class_ = "field")
if self.fillFieldChildLayout(divLayout):
layout.append(divLayout)
filled = True
return filled
def fillFieldValueFormLayout(self, layout):
filled = False
errorLayout = self.getErrorLayout()
if errorLayout is not None:
layout.append(errorLayout)
filled = True
helpLayout = self.getHelpLayout()
if helpLayout is not None:
layout.append(helpLayout)
filled = True
layout.append(html.input(
name = self.fieldName, type = "text", value = self.fieldValue))
filled = True
return filled
def fillFieldValueLayout(self, layout):
filled = False
if self.inForm:
if self.relevant:
if self.readOnly:
filled = self.fillFieldValueReadOnlyLayout(layout)
else:
filled = self.fillFieldValueFormLayout(layout)
else:
filled = self.fillHiddenLayout(layout)
else:
if self.relevant:
filled = self.fillFieldValueStaticLayout(layout)
return filled
def fillFieldValueReadOnlyLayout(self, layout):
filled = False
filled = self.fillHiddenLayout(layout) or filled
filled = self.fillFieldValueStaticLayout(layout) or filled
return filled
def fillFieldValueStaticLayout(self, layout):
filled = False
htmlValueNodes = self.htmlValueNodes
if htmlValueNodes:
for htmlValueNode in htmlValueNodes:
layout.append(htmlValueNode)
filled = True
return filled
def fillHiddenLayout(self, layout):
layout.append(html.input(
name = self.fieldName, type = "hidden", value = self.fieldValue))
return True
def getAppearance(self):
nodes = self.evaluateXpath("@appearance")
if nodes:
return nodes[0].content
else:
return None
def getChildInstanceDataXpath(self):
return self.instanceDataXpath
def getErrorLayout(self):
# FIXME
return None
def getFieldLabelLayout(self):
# See WidgetMixin.getHtmlFieldLabel
label = self.label
if label is None:
return None
labelLayout = html.span(
html.label(_(label), _(":"), " ", for_ = self.fieldName),
class_ = "label")
## if slot.getKind().isRequired and self.isInForm() \
## and not self.isReadOnly(slot):
## return X.array(label,
## X.span(_class = 'fieldRequired',
## title = _('Required'))(_('(Required)')))
return labelLayout
def getFieldName(self):
return self.instanceDataXpath
def getFieldValue(self):
valueNode = self.valueNode
if valueNode is None:
fieldValue = ""
else:
valueType = self.valueType
fieldValue = valueType.convertValueNodeToHtmlAttributeValue(
valueNode)
return fieldValue
def getFieldValueLayout(self):
# See WidgetMixin.getHtmlFieldValue.
layout = []
if not self.fillFieldValueLayout(layout):
return None
# We have to enclose the field value in a tag with class 'cell' but we
# want a nice markup so we can't simply <div class="cell"> v </div> and
# go away with this.
attributes = {"class_": "cell"}
return html.enclose(*layout, **attributes)
def getHelpLayout(self):
return None
def getHtmlValueNodes(self):
valueNode = self.valueNode
if valueNode is None:
return []
valueType = self.valueType
return valueType.convertValueNodeToHtmlNodes(valueNode)
def getInstanceDataXpath(self):
modelIdNodes = self.evaluateXpath("@model")
if modelIdNodes:
xpath = ""
else:
parentInstanceDataXpath = self.parent.childInstanceDataXpath
refNodes = self.evaluateXpath("@ref")
if not refNodes:
xpath = parentInstanceDataXpath
else:
ref = refNodes[0].content
if parentInstanceDataXpath:
xpath = "%s/%s" % (parentInstanceDataXpath, ref)
else:
xpath = ref
return xpath
def getLabel(self):
labelNodes = self.evaluateXpath("xforms:label")
if not labelNodes:
return None
labelNode = labelNodes[0]
refNodes = self.evaluateXpath("@ref", labelNode)
if refNodes:
ref = refNodes[0].content
#labelNodes = self.getValueNodes(subXpath = ref)
valueNode = self.valueNode
if valueNode is None:
return None
currentActionHandler = context.getVar("currentActionHandler")
labelNodes = currentActionHandler.evaluateXpath(
ref, contextNode = valueNode)
if not labelNodes:
return None
labelNode = labelNodes[0]
label = labelNode.content
translatable = labelNode.nsProp(
"translatable", "http://abracadabra.entrouvert.org/0.0")
if translatable in ("1", "true"):
label = _(label)
return label
def getModel(self):
modelId = self.modelId
if modelId is None:
return None
return self.dataHolder.getModel(modelId)
def getModelId(self):
modelIdNodes = self.evaluateXpath("@model")
if modelIdNodes:
return modelIdNodes[0].content
if self.parent is None:
return None
return self.parent.modelId
def getValueNode(self):
valueNodes = self.getValueNodes()
if not valueNodes:
return None
return valueNodes[0]
def getValueNodes(self):
return context.getVar("currentActionHandler").evaluateXpath(
self.instanceDataXpath)
def getValueType(self):
return context.getVar("currentActionHandler").getTypeAtXpath(
self.instanceDataXpath)
def isInForm(self):
if self._inForm:
return True
parent = self.parent
if parent is None:
return False
return parent.inForm
def isReadOnly(self):
model = self.model
if model is not None and model.isReadOnly(self.instanceDataXpath):
return True
parent = self.parent
if parent is None:
return False
return parent.readOnly
def isRelevant(self):
model = self.model
if model is not None \
and not model.isRelevant(self.instanceDataXpath):
return False
parent = self.parent
if parent is None:
return True
return parent.relevant
def setFieldValue(self, fieldValue):
valueNode = self.valueNode
# FIXME
# assert valueNode is not None
# FIXME: Handle None fieldValue properly.
if valueNode is not None and fieldValue is not None:
valueNode.setContent(fieldValue)
def setInForm(self, inForm):
self._inForm = inForm
def setValueNode(self, valueNode):
nodes = context.getVar("currentActionHandler").evaluateXpath(
self.instanceDataXpath)
if nodes:
node = nodes[0]
node.replaceNode(valueNode)
node.freeNode()
else:
self.node.addChild(valueNode)
def submit(self):
fieldStorage = context.getVar("fieldStorage")
fieldName = self.fieldName
if fieldStorage.has_key(fieldName):
value = fieldStorage.getvalue(fieldName)
else:
value = None
valueType = self.valueType
if valueType is None:
context.getVar("logger").info(
"""Missing type for value "%s" in field "%s".""" % (
value, fieldName))
context.getVar("currentActionHandler").setContentAtXpath(
self.instanceDataXpath,
valueType.convertFieldStorageValueToContent(value))
appearance = property(getAppearance)
childInstanceDataXpath = property(getChildInstanceDataXpath)
fieldName = property(getFieldName)
fieldValue = property(getFieldValue, setFieldValue)
htmlValueNodes = property(getHtmlValueNodes)
inForm = property(isInForm, setInForm)
instanceDataXpath = property(getInstanceDataXpath)
label = property(getLabel)
model = property(getModel)
modelId = property(getModelId)
readOnly = property(isReadOnly)
relevant = property(isRelevant)
valueNode = property(getValueNode, setValueNode)
valueType = property(getValueType)
class ActionButton(Control):
fieldValue = None
isFieldLabelNeeded = False
def fillButtonLayout(self, layout):
filled = False
if not self.relevant:
return filled
action = self.action
currentActionHandler = context.getVar('currentActionHandler')
if currentActionHandler.walk([action, 'exists']) \
and currentActionHandler.walk([action, 'isAuthorized']):
if self.inForm:
# self.fieldName doesn't exist for buttons.
layout.append(html.input(
class_ = 'button', name = self.action, type = 'submit',
value = self.label))
filled = True
else:
layout.append(html.a(
self.label, class_ = 'button',
href = currentActionHandler.dataHolder.getActionUri(
self.action)))
filled = True
return filled
def fillFieldValueFormLayout(self, layout):
layout.append(self.getErrorLayout())
layout.append(self.getHelpLayout())
currentActionHandler = context.getVar('currentActionHandler')
layout.append(html.a(
self.label,
href = currentActionHandler.dataHolder.getActionUri(self.action)))
return True
def fillFieldValueStaticLayout(self, layout):
currentActionHandler = context.getVar('currentActionHandler')
layout.append(html.a(
self.label,
href = currentActionHandler.dataHolder.getActionUri(self.action)))
return True
def fillHiddenLayout(self, layout):
return False
def getAction(self):
actionNodes = self.evaluateXpath('yep:action')
if not actionNodes:
return None
actionNode = actionNodes[0]
refNodes = self.evaluateXpath('@ref', actionNode)
if not refNodes:
return actionNodes[0].content
ref = refNodes[0].content
#actionNodes = self.getValueNodes(subXpath = ref)
valueNode = self.valueNode
if valueNode is None:
return None
currentActionHandler = context.getVar('currentActionHandler')
actionNodes = currentActionHandler.evaluateXpath(
ref, contextNode = valueNode)
if not actionNodes:
return None
return actionNodes[0].content
action = property(getAction)
class Custom(Control):
def fillFieldValueLayout(self, layout):
currentActionHandler = context.getVar('currentActionHandler')
return getattr(currentActionHandler, self.functionName)(self, layout)
def getFunctionName(self):
nodes = self.evaluateXpath('@function')
if nodes:
return nodes[0].content
else:
return None
def submit(self):
pass
functionName = property(getFunctionName)
class Description(elements.Element):
externalModelLocations = None
def fillInstancePageBodyLayout(self, layout, inForm = False):
"""Layout page body."""
pageName = context.getVar('pageName')
pageNode = self.getPageNode(pageName)
if pageNode is None:
return False
bodyNodes = self.evaluateXpath('yep:body', pageNode)
if bodyNodes:
controlNodes = self.evaluateXpath('*', bodyNodes[0])
for controlNode in controlNodes:
control = newControl(controlNode, dataHolder = self)
control.inForm = inForm
control.fillFieldValueLayout(layout)
return True
else:
context.getVar('logger').info(
"""Missing body description for page named "%s".""" % pageName)
return False
def fillInstancePageLayout(self, layout):
pageName = context.getVar('pageName')
pageNode = self.getPageNode(pageName)
if pageNode is None:
return False
inForm = self.instanceLayoutRequiresForm()
if inForm:
currentActionHandler = context.getVar('currentActionHandler')
pageLayout = html.form(
action = currentActionHandler.dataHolder.getActionUri('submit'),
enctype = 'multipart/form-data', method = 'post')
layout.append(pageLayout)
if not context.getVar('canUseCookie'):
session = context.getVar('session')
if session is not None:
pageLayout.append(html.input(
name = 'sessionToken', type = 'hidden',
value = session.dataHolder.localId))
pageLayout.append(html.input(
name = 'pageName', type = 'hidden', value = pageName))
else:
pageLayout = layout
self.fillInstancePageBodyLayout(pageLayout, inForm = inForm)
# Layout page buttons bar.
buttonsBarLayout = html.div(class_ = 'buttons-bar')
actionButtonsBarLayout = html.span(class_ = 'action-buttons-bar')
buttonsBarLayout.append(actionButtonsBarLayout)
actionButtonsBarNodes = self.evaluateXpath(
'yep:actionButtonsBar', pageNode)
buttonsBarFilled = False
if actionButtonsBarNodes:
controlNodes = self.evaluateXpath(
'*', actionButtonsBarNodes[0])
for controlNode in controlNodes:
control = newControl(controlNode, dataHolder = self)
control.inForm = inForm
if control.fillButtonLayout(actionButtonsBarLayout):
buttonsBarFilled = True
if buttonsBarFilled:
pageLayout.append(buttonsBarLayout)
return True
def getModel(self, id):
modelNodes = self.evaluateXpath('xforms:model[@id = "%s"]' % id)
if modelNodes:
modelNode = modelNodes[0]
return xforms.Model(modelNode, self)
if self.externalModelLocations:
for externalModelLocation in self.externalModelLocations:
externalDescriptions = dataholders.walkToLocation(
externalModelLocation)
model = externalDescriptions.getModel(id)
if model is not None:
return model
return None
def getPageNames(self):
pageNameNodes = self.evaluateXpath('yep:page/@name')
return [pageNameNode.content for pageNameNode in pageNameNodes]
def getPageNode(self, pageName):
if pageName is None:
pageName = 'view'
pageNodes = self.evaluateXpath('yep:page[@name = "%s"]' % pageName)
if not pageNodes:
context.getVar('logger').info(
"""Missing description for page named "%s".""" % pageName)
return None
return pageNodes[0]
def instanceLayoutRequiresForm(self):
pageName = context.getVar('pageName')
pageNode = self.getPageNode(pageName)
if pageNode is None:
return False
pageTypeNodes = self.evaluateXpath('@type', contextNode = pageNode)
if pageTypeNodes:
pageType = pageTypeNodes[0].content
else:
pageType = None
return pageType == 'form'
def loadExternalModels(self):
externalModelLocationNodes = self.evaluateXpath('xforms:model/@src')
self.externalModelLocations = [
externalModelLocationNode.content
for externalModelLocationNode in externalModelLocationNodes]
for externalModelLocation in self.externalModelLocations:
dataholders.walkToLocation(externalModelLocation)
def submit(self):
pageName = context.getVar('pageName')
pageNode = self.getPageNode(pageName)
if pageNode is None:
context.getVar('logger').info(
"""Missing page named "%s".""" % pageName)
return
bodyNodes = self.evaluateXpath('yep:body', pageNode)
if not bodyNodes:
context.getVar('logger').info(
"""Missing body description for page named "%s"."""
% pageName)
controlNodes = self.evaluateXpath('*', bodyNodes[0])
for controlNode in controlNodes:
control = newControl(controlNode, dataHolder = self)
control.submit()
class DescriptionHolder(dataholders.Xml):
def setupXml(self):
dataholders.Xml.setupXml(self)
self.rootElement.loadExternalModels()
class Group(Control):
def fillButtonLayout(self, layout):
filled = False
if not self.inForm and not self.relevant:
return False
controlNodes = self.evaluateXpath('*')
for controlNode in controlNodes:
if controlNode.name == 'label':
continue
control = newControl(controlNode, parent = self)
if control.fillButtonLayout(layout):
filled = True
return filled
def fillFieldValueLayout(self, layout):
# See ThingMixin.getEditLayout.
filled = False
if not self.inForm and not self.relevant:
return filled
controlNodes = self.evaluateXpath('*')
for controlNode in controlNodes:
if controlNode.name == 'label':
continue
control = newControl(controlNode, parent = self)
if control.fillFieldLayout(layout):
filled = True
return filled
def submit(self):
controlNodes = self.evaluateXpath('*')
for controlNode in controlNodes:
if controlNode.name == 'label':
continue
control = newControl(controlNode, parent = self)
control.submit()
class Input(Control):
def fillFieldValueStaticLayout(self, layout):
if self.appearance == 'title':
layout.append(html.h2(self.fieldValue))
return True
return Control.fillFieldValueStaticLayout(self, layout)
def fillFieldValueFormLayout(self, layout):
filled = False
errorLayout = self.getErrorLayout()
if errorLayout is not None:
layout.append(errorLayout)
filled = True
helpLayout = self.getHelpLayout()
if helpLayout is not None:
layout.append(helpLayout)
filled = True
fieldName = self.fieldName
valueTypeName = self.valueType.name
if valueTypeName == 'xsd:date':
layout.append(html.input(
id = fieldName, maxlength = '10', name = fieldName,
size = '10', type = 'text', value = self.fieldValue))
layout.append(html.img(
id= '%s_trigger' % fieldName,
src = locations.getUri('/javascript/jscalendar/img.png'),
style = 'cursor: pointer;',
title = _('Date Selector'),
onload = """Calendar.setup({
inputField: "%s",
ifFormat: "%%d/%%m/%%Y",
button: "%s_trigger",
singleClick: true
})
""" % (fieldName, fieldName),
onmouseout="this.style.background=''",
onmouseover = "this.style.background='';"))
else:
layout.append(html.input(
name = fieldName, type = "text", value = self.fieldValue))
filled = True
return filled
# FIXME: Label is not a control.
class Label(Control):
def fillFieldChildLayout(self, layout):
label = self.label
if label is None:
label = N_("Unknown Label")
layout.append(label)
return True
class Repeat(Control):
index = None
fieldValue = None
def fillFieldValueFormLayout(self, layout):
## kind = slot.getKind()
## countName = slot.getFieldOptionName('count')
## count = kind.getItemsCount(slot, fields)
countName = "FIXME"
count = 0
valueNodes = self.getValueNodes()
count = max(1, count, len(valueNodes))
layout.append(self.getErrorLayout())
layout.append(self.getHelpLayout())
layout.append(html.input(
name = countName, type = "hidden", value = str(count)))
## if self.inline:
## fieldset = X.ul(_class = 'multi inline')
## else:
## fieldset = X.ul(_class = 'multi')
ul = html.ul(class_ = "multi")
layout.append(html.div(ul))
for i in range(count):
if i >= len(valueNodes):
self.index = None
else:
self.index = i
controlNodes = self.evaluateXpath("*")
li = html.li()
ul.append(li)
for controlNode in controlNodes:
control = newControl(controlNode, parent = self)
if control.isFieldLabelNeeded:
control.fillFieldLayout(li)
else:
control.fillFieldValueLayout(li)
## if kind.canAddItem(slot, fields):
## addButtonName = slot.getFieldOptionName('addButton')
## layout += X.buttonInForm('add', addButtonName)
## if self.apply:
## layout += X.buttonInForm('apply', 'applyButton')
return True
def fillFieldValueStaticLayout(self, layout):
filled = False
valueNodes = self.getValueNodes()
if not valueNodes:
return filled
ul = html.ul(class_ = "multi")
for i in range(len(valueNodes)):
self.index = i
controlNodes = self.evaluateXpath("*")
li = html.li()
ul.append(li)
for controlNode in controlNodes:
control = newControl(controlNode, parent = self)
if control.isFieldLabelNeeded:
if control.fillFieldLayout(li):
filled = True
else:
if control.fillFieldValueLayout(li):
filled = True
if filled:
layout.append(ul)
return filled
def fillHiddenLayout(self, layout):
filled = False
countName = "FIXME"
count = 0
valueNodes = self.getValueNodes()
count = max(0, count, len(valueNodes))
layout.append(html.input(
name = countName, type = "hidden", value = str(count)))
for i in range(len(valueNodes)):
self.index = i
controlNodes = self.evaluateXpath("*")
for controlNode in controlNodes:
control = newControl(controlNode, parent = self)
if control.fillHiddenLayout(layout):
filled = True
return filled
def getChildInstanceDataXpath(self):
return "%s[%d]" % (self.instanceDataXpath, self.index + 1)
childInstanceDataXpath = property(getChildInstanceDataXpath)
class Secret(Control):
def fillFieldValueFormLayout(self, layout):
layout.append(self.getErrorLayout())
layout.append(self.getHelpLayout())
layout.append(html.input(
name = self.fieldName, type = "password", value = self.fieldValue))
return True
def fillFieldValueStaticLayout(self, layout):
layout.append("*" * len(self.fieldValue))
return True
class Select(Control):
def fillFieldValueFormLayout(self, layout):
layout.append(self.getErrorLayout())
layout.append(self.getHelpLayout())
ul = html.ul()
layout.append(ul)
valueNode = self.valueNode
if valueNode is None:
value = None
else:
value = valueNode.content
if value is None:
itemValues = []
else:
itemValues = value.split(" ")
fieldName = self.fieldName
itemNodes = self.evaluateXpath("xforms:item")
for itemNode in itemNodes:
itemValueNodes = self.evaluateXpath("xforms:value", itemNode)
if not itemValueNodes:
continue
itemValue = itemValueNodes[0].content
if not itemValue:
continue
labelValueNodes = self.evaluateXpath("xforms:label", itemNode)
if labelValueNodes:
itemLabel = labelValueNodes[0].content
else:
itemLabel = None
if not itemLabel:
itemLabel = itemValue
itemFieldName = "%s_%s" % (fieldName, itemValue)
if itemValue in itemValues:
attributes = {"checked": "checked"}
else:
attributes = {}
ul.append(html.li(
html.input(
name = itemFieldName, type = "checkbox", value = itemValue,
**attributes),
html.label(_(itemLabel), for_ = itemFieldName)))
return True
def fillFieldValueStaticLayout(self, layout):
filled = False
ul = html.ul()
valueNode = self.valueNode
if valueNode is None:
value = None
else:
value = valueNode.content
if value is None:
itemValues = []
else:
itemValues = value.split(" ")
itemNodes = self.evaluateXpath("xforms:item")
for itemNode in itemNodes:
itemValueNodes = self.evaluateXpath("xforms:value", itemNode)
if not itemValueNodes:
continue
itemValue = itemValueNodes[0].content
if not itemValue in itemValues:
continue
labelValueNodes = self.evaluateXpath("xforms:label", itemNode)
if labelValueNodes:
itemLabel = labelValueNodes[0].content
else:
itemLabel = None
if not itemLabel:
itemLabel = itemValue
ul.append(html.li(_(itemLabel)))
filled = True
if filled:
layout.append(ul)
return filled
def submit(self):
fieldStorage = context.getVar("fieldStorage")
fieldName = self.fieldName
itemNodes = self.evaluateXpath("xforms:item")
splitedValue = []
for itemNode in itemNodes:
itemValueNodes = self.evaluateXpath("xforms:value", itemNode)
if not itemValueNodes:
continue
itemValue = itemValueNodes[0].content
if not itemValue:
continue
itemFieldName = "%s_%s" % (fieldName, itemValue)
if fieldStorage.has_key(itemFieldName) \
and fieldStorage.getvalue(itemFieldName) == itemValue:
splitedValue.append(itemValue)
context.getVar("currentActionHandler").setContentAtXpath(
self.instanceDataXpath, " ".join(splitedValue))
class Select1(Control):
def fillFieldValueFormLayout(self, layout):
layout.append(self.getErrorLayout())
layout.append(self.getHelpLayout())
appearance = self.appearance
valueNode = self.valueNode
if valueNode is None:
value = None
else:
value = valueNode.content
fieldName = self.fieldName
if appearance == "full":
ul = html.ul()
layout.append(ul)
else: # appearance == "minimal"
select = html.select(name = fieldName)
layout.append(select)
itemNodes = self.evaluateXpath("xforms:item")
for itemNode in itemNodes:
itemValueNodes = self.evaluateXpath("xforms:value", itemNode)
if not itemValueNodes:
continue
itemValue = itemValueNodes[0].content
if not itemValue:
continue
labelValueNodes = self.evaluateXpath("xforms:label", itemNode)
if labelValueNodes:
itemLabel = labelValueNodes[0].content
else:
itemLabel = None
if not itemLabel:
itemLabel = itemValue
if appearance == "full":
if itemValue == value:
attributes = {"checked": "checked"}
else:
attributes = {}
ul.append(html.li(
html.input(
name = fieldName, type = "radio", value = itemValue,
**attributes),
html.label(_(itemLabel), for_ = fieldName)))
else: # appearance == "minimal"
if itemValue == value:
attributes = {"selected": "selected"}
else:
attributes = {}
select.append(html.option(
_(itemLabel), value = itemValue, **attributes))
return True
def fillFieldValueStaticLayout(self, layout):
valueNode = self.valueNode
if valueNode is None:
value = None
else:
value = valueNode.content
labelNodes = self.evaluateXpath(
"""xforms:item[xforms:value = "%s"]/xforms:label""" % value)
if labelNodes:
label = labelNodes[0].content
else:
label = value
layout.append(_(label))
return True
def submit(self):
fieldStorage = context.getVar("fieldStorage")
fieldName = self.fieldName
if fieldStorage.has_key(fieldName):
value = fieldStorage.getvalue(fieldName)
else:
value = ""
valueNodes = self.evaluateXpath("xforms:item/xforms:value")
values = [valueNode.content for valueNode in valueNodes]
if value in values:
context.getVar("currentActionHandler").setContentAtXpath(
self.instanceDataXpath, value)
class Spip(Control):
def getFieldLabelLayout(self):
return None
def fillFieldChildLayout(self, layout):
filled = False
cellLayout = self.getFieldValueLayout()
if cellLayout is not None:
layout.append(cellLayout)
filled = True
return filled
def fillFieldValueLayout(self, layout):
return self.fillFieldValueStaticLayout(layout)
def fillFieldValueStaticLayout(self, layout):
filled = False
content = self.node.content
if content:
htmlText = "<spip>%s</spip>" % parsers.makeHtmlFromSpip(content)
doc = libxml2.htmlParseDoc(htmlText, 'UTF-8')
node = doc.getRootElement().children
while node is not None:
layout.append(node)
node = node.next
filled = True
return filled
def submit(self):
pass
class Submit(Control):
fieldValue = None
isFieldLabelNeeded = False
def fillButtonLayout(self, layout):
filled = False
if not self.relevant:
return filled
# Unlike Submit Control, a Trigger never submits the form even inside
# a form.
if self.inForm:
# self.fieldName doesn't exist for buttons.
## layout.append(html.input(
## class_ = "button", name = self.fieldName, type = "submit",
## value = self.label))
layout.append(html.input(
class_ = "button", name = self.getSubmissionId(),
type = "submit", value = self.label))
filled = True
else:
layout.append(html.a(
self.label, class_ = "button",
href = self.getSubmissionActionUri()))
filled = True
return filled
def fillFieldValueFormLayout(self, layout):
layout.append(self.getErrorLayout())
layout.append(self.getHelpLayout())
layout.append(html.a(self.label, href = self.getSubmissionActionUri()))
return True
def fillFieldValueStaticLayout(self, layout):
layout.append(html.a(self.label, href = self.getSubmissionActionUri()))
return True
def fillHiddenLayout(self, layout):
return False
def getSubmissionActionUri(self):
submissionId = self.getSubmissionId()
submissionNode = self.model.getSubmission(submissionId)
if submissionNode is None:
return None
actionNodes = self.evaluateXpath("@action", submissionNode)
if not actionNodes:
return None
return locations.getUri(actionNodes[0].content)
def getSubmissionId(self):
submissionIdNodes = self.evaluateXpath("@submission")
if submissionIdNodes:
submissionId = submissionIdNodes[0].content
else:
submissionId = None
return submissionId
class TextArea(Control):
def fillFieldValueFormLayout(self, layout):
filled = False
errorLayout = self.getErrorLayout()
if errorLayout is not None:
layout.append(errorLayout)
filled = True
helpLayout = self.getHelpLayout()
if helpLayout is not None:
layout.append(helpLayout)
filled = True
if self.appearance == "full":
attributes = {"cols": "80", "rows": "10"}
else:
attributes = {}
layout.append(html.textarea(
self.fieldValue, name = self.fieldName, **attributes))
filled = True
return filled
def getFieldValueLayout(self):
layout = Control.getFieldValueLayout(self)
if layout is None:
return None
if self.appearance == "full":
layoutClass = layout.getAttribute("class")
if layoutClass:
layoutClass = "%s %s" % (layoutClass, "fullwidth")
else:
layoutClass = "fullwidth"
layout.setAttribute("class", layoutClass)
return layout
class Trigger(Control):
fieldValue = None
isFieldLabelNeeded = False
def fillButtonLayout(self, layout):
if not self.relevant:
return False
# Unlike Submit Control, a Trigger never submits the form even inside
# a form.
layout.append(html.a(
self.label, class_ = "button",
href = self.getLoadResourceUri()))
return True
def fillFieldValueFormLayout(self, layout):
layout.append(self.getErrorLayout())
layout.append(self.getHelpLayout())
layout.append(html.a(self.label, href = self.getLoadResourceUri()))
return True
def fillFieldValueStaticLayout(self, layout):
layout.append(html.a(self.label, href = self.getLoadResourceUri()))
return True
def fillHiddenLayout(self, layout):
return False
def getLoadResourceUri(self):
loadNodes = self.evaluateXpath(
"""xforms:load[@ev:event="DOMActivate"]""")
if not loadNodes:
return None
loadNode = loadNodes[0]
resourceNodes = self.evaluateXpath("@resource", loadNode)
if not resourceNodes:
refNodes = self.evaluateXpath("@ref", loadNode)
if not refNodes:
return None
ref = refNodes[0].content
## resourceNodes = self.getValueNodes(subXpath = ref)
valueNode = self.valueNode
if valueNode is None:
return None
currentActionHandler = context.getVar("currentActionHandler")
resourceNodes = currentActionHandler.evaluateXpath(
ref, contextNode = valueNode)
if not resourceNodes:
return None
resource = resourceNodes[0].content
return locations.getUri(resource)
controlClasses = {
"actionButton": ActionButton,
"custom": Custom,
"spip": Spip,
"xforms:group": Group,
"xforms:input": Input,
"xforms:label": Label,
"xforms:repeat": Repeat,
"xforms:secret": Secret,
"xforms:select": Select,
"xforms:select1": Select1,
"xforms:textarea": TextArea,
"xforms:trigger": Trigger,
"xforms:submit": Submit,
}
namespaceNames = {
"http://abracadabra.entrouvert.org/0.0": None,
"http://www.w3.org/2002/xforms": "xforms",
}
def newControl(node, dataHolder = None, parent = None):
name = None
while True:
namespaceUri = node.ns().content
if not namespaceUri in namespaceNames:
raise Exception(
"Unknown XML namespace URI = \"%s\"" % namespaceUri)
namespaceName = namespaceNames[namespaceUri]
if namespaceName is None:
name = node.name
else:
name = "%s:%s" % (namespaceName, node.name)
if name != "copy":
break
# The node is a copy of a real node => get real node instead.
if dataHolder is None:
description = parent.dataHolder
else:
description = dataHolder
originalIdNodes = description.evaluateXpath("@original", node)
originalId = originalIdNodes[0].content
originalNodes = description.evaluateXpath(
"//*[@yep:id = '%s']" % originalId)
node = originalNodes[0]
return controlClasses[name](
node, dataHolder = dataHolder, parent = parent)
modules.registerElementClass(
"http://abracadabra.entrouvert.org/0.0", "description", Description)
modules.registerXmlClass("description", DescriptionHolder)