Small bugfix while searching string fields and added the possibility to define a text-transform on String fields.
This commit is contained in:
parent
ae4bfc9970
commit
ca7b688c00
|
@ -276,13 +276,20 @@ class String(Type):
|
||||||
show=True, page='main', group=None, move=0, indexed=False,
|
show=True, page='main', group=None, move=0, indexed=False,
|
||||||
searchable=False, specificReadPermission=False,
|
searchable=False, specificReadPermission=False,
|
||||||
specificWritePermission=False, width=None, height=None,
|
specificWritePermission=False, width=None, height=None,
|
||||||
master=None, masterValue=None, focus=False, historized=False):
|
master=None, masterValue=None, focus=False, historized=False,
|
||||||
|
transform='none'):
|
||||||
Type.__init__(self, validator, multiplicity, index, default, optional,
|
Type.__init__(self, validator, multiplicity, index, default, optional,
|
||||||
editDefault, show, page, group, move, indexed, searchable,
|
editDefault, show, page, group, move, indexed, searchable,
|
||||||
specificReadPermission, specificWritePermission, width,
|
specificReadPermission, specificWritePermission, width,
|
||||||
height, master, masterValue, focus, historized)
|
height, master, masterValue, focus, historized)
|
||||||
self.format = format
|
self.format = format
|
||||||
self.isSelect = self.isSelection()
|
self.isSelect = self.isSelection()
|
||||||
|
# The following field has a direct impact on the text entered by the
|
||||||
|
# user. It applies a transformation on it, exactly as does the CSS
|
||||||
|
# "text-transform" property. Allowed values are those allowed for the
|
||||||
|
# CSS property: "none" (default), "uppercase", "capitalize" or
|
||||||
|
# "lowercase".
|
||||||
|
self.transform = transform
|
||||||
def isSelection(self):
|
def isSelection(self):
|
||||||
'''Does the validator of this type definition define a list of values
|
'''Does the validator of this type definition define a list of values
|
||||||
into which the user must select one or more values?'''
|
into which the user must select one or more values?'''
|
||||||
|
|
|
@ -173,7 +173,8 @@ class ToolMixin(AbstractMixin):
|
||||||
if isinstance(fieldValue, basestring) and \
|
if isinstance(fieldValue, basestring) and \
|
||||||
fieldValue.endswith('*'):
|
fieldValue.endswith('*'):
|
||||||
v = fieldValue[:-1]
|
v = fieldValue[:-1]
|
||||||
params[attrName] = {'query':(v,v+'Z'), 'range':'minmax'}
|
params[attrName] = {'query':(v,v+'z'), 'range':'min:max'}
|
||||||
|
# Warning: 'z' is higher than 'Z'!
|
||||||
elif type(fieldValue) in sequenceTypes:
|
elif type(fieldValue) in sequenceTypes:
|
||||||
if fieldValue and isinstance(fieldValue[0], basestring):
|
if fieldValue and isinstance(fieldValue[0], basestring):
|
||||||
# We have a list of string values (ie: we need to
|
# We have a list of string values (ie: we need to
|
||||||
|
@ -430,6 +431,8 @@ class ToolMixin(AbstractMixin):
|
||||||
day = int(day)-1
|
day = int(day)-1
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
transformMethods = {'uppercase': 'upper', 'lowercase': 'lower',
|
||||||
|
'capitalize': 'capitalize'}
|
||||||
def onSearchObjects(self):
|
def onSearchObjects(self):
|
||||||
'''This method is called when the user triggers a search from
|
'''This method is called when the user triggers a search from
|
||||||
search.pt.'''
|
search.pt.'''
|
||||||
|
@ -471,6 +474,14 @@ class ToolMixin(AbstractMixin):
|
||||||
day = rq.form['%s_to_day' % prefix]
|
day = rq.form['%s_to_day' % prefix]
|
||||||
toDate = self._getDateTime(year, month, day, False)
|
toDate = self._getDateTime(year, month, day, False)
|
||||||
attrValue = (fromDate, toDate)
|
attrValue = (fromDate, toDate)
|
||||||
|
elif attrType.startswith('string'):
|
||||||
|
# In the case of a string, it could be necessary to
|
||||||
|
# apply some text transform.
|
||||||
|
if len(attrType) > 6:
|
||||||
|
transform = attrType.split('-')[1]
|
||||||
|
if (transform != 'none') and attrValue:
|
||||||
|
exec 'attrValue = attrValue.%s()' % \
|
||||||
|
self.transformMethods[transform]
|
||||||
if isinstance(attrValue, list):
|
if isinstance(attrValue, list):
|
||||||
# It is a list of values. Check if we have an operator for
|
# It is a list of values. Check if we have an operator for
|
||||||
# the field, to see if we make an "and" or "or" for all
|
# the field, to see if we make an "and" or "or" for all
|
||||||
|
|
|
@ -26,7 +26,8 @@
|
||||||
<label tal:attributes="for widgetName" tal:content="python: tool.translate(appyType['label'])"></label><br>
|
<label tal:attributes="for widgetName" tal:content="python: tool.translate(appyType['label'])"></label><br>
|
||||||
<tal:comment replace="nothing">Show a simple search field for most String fields.</tal:comment>
|
<tal:comment replace="nothing">Show a simple search field for most String fields.</tal:comment>
|
||||||
<tal:simpleSearch condition="not: appyType/isSelect">
|
<tal:simpleSearch condition="not: appyType/isSelect">
|
||||||
<input type="text" tal:attributes="name widgetName"/>
|
<input type="text" tal:attributes="name python: '%s*string-%s' % (widgetName, appyType['transform']);
|
||||||
|
style python: 'text-transform:%s' % appyType['transform']"/>
|
||||||
</tal:simpleSearch>
|
</tal:simpleSearch>
|
||||||
<tal:comment replace="nothing">Show a multi-selection box for fields whose validator defines a list of values, with a "AND/OR" checkbox.</tal:comment>
|
<tal:comment replace="nothing">Show a multi-selection box for fields whose validator defines a list of values, with a "AND/OR" checkbox.</tal:comment>
|
||||||
<tal:selectSearch condition="appyType/isSelect">
|
<tal:selectSearch condition="appyType/isSelect">
|
||||||
|
|
|
@ -436,16 +436,20 @@ class FileWrapper:
|
||||||
convScript = '%s/converter.py' % os.path.dirname(appy.pod.__file__)
|
convScript = '%s/converter.py' % os.path.dirname(appy.pod.__file__)
|
||||||
cmd = '%s %s "%s" %s -p%d' % (tool.unoEnabledPython, convScript,
|
cmd = '%s %s "%s" %s -p%d' % (tool.unoEnabledPython, convScript,
|
||||||
filePath, format, tool.openOfficePort)
|
filePath, format, tool.openOfficePort)
|
||||||
errorMessage = executeCommand(cmd, ignoreLines='warning')
|
errorMessage = executeCommand(cmd)
|
||||||
|
# Even if we have an "error" message, it could be a simple warning.
|
||||||
|
# So we will continue here and, as a subsequent check for knowing if
|
||||||
|
# an error occurred or not, we will test the existence of the
|
||||||
|
# converted file (see below).
|
||||||
os.remove(filePath)
|
os.remove(filePath)
|
||||||
if errorMessage:
|
|
||||||
tool.log(CONVERSION_ERROR % (cmd, errorMessage), type='error')
|
|
||||||
return
|
|
||||||
# Return the name of the converted file.
|
# Return the name of the converted file.
|
||||||
baseName, ext = os.path.splitext(filePath)
|
baseName, ext = os.path.splitext(filePath)
|
||||||
if (ext == '.%s' % format):
|
if (ext == '.%s' % format):
|
||||||
filePath = '%s.res.%s' % (baseName, format)
|
filePath = '%s.res.%s' % (baseName, format)
|
||||||
else:
|
else:
|
||||||
filePath = '%s.%s' % (baseName, format)
|
filePath = '%s.%s' % (baseName, format)
|
||||||
|
if not os.path.exists(filePath):
|
||||||
|
tool.log(CONVERSION_ERROR % (cmd, errorMessage), type='error')
|
||||||
|
return
|
||||||
return filePath
|
return filePath
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
|
@ -337,6 +337,7 @@ class Renderer:
|
||||||
def callOpenOffice(self, resultOdtName, resultType):
|
def callOpenOffice(self, resultOdtName, resultType):
|
||||||
'''Call Open Office in server mode to convert or update the ODT
|
'''Call Open Office in server mode to convert or update the ODT
|
||||||
result.'''
|
result.'''
|
||||||
|
ooOutput = ''
|
||||||
try:
|
try:
|
||||||
if (not isinstance(self.ooPort, int)) and \
|
if (not isinstance(self.ooPort, int)) and \
|
||||||
(not isinstance(self.ooPort, long)):
|
(not isinstance(self.ooPort, long)):
|
||||||
|
@ -368,9 +369,7 @@ class Renderer:
|
||||||
cmd = '%s %s %s %s -p%d' % \
|
cmd = '%s %s %s %s -p%d' % \
|
||||||
(self.pyPath, convScript, qResultOdtName, resultType,
|
(self.pyPath, convScript, qResultOdtName, resultType,
|
||||||
self.ooPort)
|
self.ooPort)
|
||||||
convertOutput = executeCommand(cmd, ignoreLines='warning')
|
ooOutput = executeCommand(cmd)
|
||||||
if convertOutput:
|
|
||||||
raise PodError(CONVERT_ERROR % convertOutput)
|
|
||||||
except PodError, pe:
|
except PodError, pe:
|
||||||
# When trying to call OO in server mode for producing
|
# When trying to call OO in server mode for producing
|
||||||
# ODT (=forceOoCall=True), if an error occurs we still
|
# ODT (=forceOoCall=True), if an error occurs we still
|
||||||
|
@ -380,6 +379,7 @@ class Renderer:
|
||||||
print WARNING_INCOMPLETE_ODT % str(pe)
|
print WARNING_INCOMPLETE_ODT % str(pe)
|
||||||
else:
|
else:
|
||||||
raise pe
|
raise pe
|
||||||
|
return ooOutput
|
||||||
|
|
||||||
def finalize(self):
|
def finalize(self):
|
||||||
'''Re-zip the result and potentially call OpenOffice if target format is
|
'''Re-zip the result and potentially call OpenOffice if target format is
|
||||||
|
@ -414,8 +414,8 @@ class Renderer:
|
||||||
raise PodError(BAD_RESULT_TYPE % (
|
raise PodError(BAD_RESULT_TYPE % (
|
||||||
self.result, FILE_TYPES.keys()))
|
self.result, FILE_TYPES.keys()))
|
||||||
# Call OpenOffice to perform the conversion or document update
|
# Call OpenOffice to perform the conversion or document update
|
||||||
self.callOpenOffice(resultOdtName, resultType)
|
output = self.callOpenOffice(resultOdtName, resultType)
|
||||||
# I have the result. Move it to the correct name
|
# I (should) have the result. Move it to the correct name
|
||||||
resPrefix = os.path.splitext(resultOdtName)[0] + '.'
|
resPrefix = os.path.splitext(resultOdtName)[0] + '.'
|
||||||
if resultType == 'odt':
|
if resultType == 'odt':
|
||||||
# converter.py has (normally!) created a second file
|
# converter.py has (normally!) created a second file
|
||||||
|
@ -427,6 +427,8 @@ class Renderer:
|
||||||
# update indexes, sections, etc.
|
# update indexes, sections, etc.
|
||||||
else:
|
else:
|
||||||
resultName = resPrefix + resultType
|
resultName = resPrefix + resultType
|
||||||
|
if not os.path.exists(resultName):
|
||||||
|
raise PodError(CONVERT_ERROR % output)
|
||||||
os.rename(resultName, self.result)
|
os.rename(resultName, self.result)
|
||||||
finally:
|
finally:
|
||||||
os.chdir(self.curdir)
|
os.chdir(self.curdir)
|
||||||
|
|
|
@ -74,21 +74,10 @@ def getOsTempFolder():
|
||||||
return res
|
return res
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
def executeCommand(cmd, ignoreLines=None):
|
def executeCommand(cmd):
|
||||||
'''Executes command p_cmd and returns the content of its stderr.
|
'''Executes command p_cmd and returns the content of its stderr.'''
|
||||||
If p_ignoreLines is not None, we will remove from the result every line
|
|
||||||
starting with p_ignoreLines.'''
|
|
||||||
childStdIn, childStdOut, childStdErr = os.popen3(cmd)
|
childStdIn, childStdOut, childStdErr = os.popen3(cmd)
|
||||||
res = childStdErr.read()
|
res = childStdErr.read()
|
||||||
if res and ignoreLines:
|
|
||||||
# Remove every line starting with ignoreLines
|
|
||||||
keptLines = []
|
|
||||||
for line in res.split('\n'):
|
|
||||||
line = line.strip()
|
|
||||||
if not line or line.startswith(ignoreLines): continue
|
|
||||||
else:
|
|
||||||
keptLines.append(line)
|
|
||||||
res = '\n'.join(keptLines)
|
|
||||||
childStdIn.close(); childStdOut.close(); childStdErr.close()
|
childStdIn.close(); childStdOut.close(); childStdErr.close()
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue