Improvement in xhtml->odt conversion (pod) + new search param for appy root classes and param 'indexed' for fields.
This commit is contained in:
parent
cbd6fbbec5
commit
2b907fee32
113
gen/__init__.py
113
gen/__init__.py
|
@ -28,11 +28,20 @@ class Import:
|
|||
self.columnHeaders = columnHeaders
|
||||
self.sortMethod = sortMethod
|
||||
|
||||
class Search:
|
||||
'''Used for specifying a search for a given type.'''
|
||||
def __init__(self, name, sortBy='title', limit=None, **fields):
|
||||
self.name = name
|
||||
self.sortBy = sortBy
|
||||
self.limit = limit
|
||||
self.fields = fields # This is a dict whose keys are indexed field
|
||||
# names and whosse values are search values.
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
class Type:
|
||||
'''Basic abstract class for defining any appy type.'''
|
||||
def __init__(self, validator, multiplicity, index, default, optional,
|
||||
editDefault, show, page, group, move, searchable,
|
||||
editDefault, show, page, group, move, indexed, searchable,
|
||||
specificReadPermission, specificWritePermission, width,
|
||||
height, master, masterValue, focus):
|
||||
# The validator restricts which values may be defined. It can be an
|
||||
|
@ -48,7 +57,8 @@ class Type:
|
|||
# strings (thus creating a dictionary of values instead of a list),
|
||||
# specify a type specification for the index, like Integer() or
|
||||
# String(). Note that this concept of "index" has nothing to do with
|
||||
# the concept of "database index".
|
||||
# the concept of "database index" (see fields "indexed" and
|
||||
# "searchable" below). self.index is not yet used.
|
||||
self.index = index
|
||||
# Default value
|
||||
self.default = default
|
||||
|
@ -68,8 +78,11 @@ class Type:
|
|||
# The following attribute allows to move a field back to a previous
|
||||
# position (useful for content types that inherit from others).
|
||||
self.move = move
|
||||
# If specified "searchable", the field will be referenced in low-level
|
||||
# indexing mechanisms for fast access and search functionalities.
|
||||
# If indexed is True, a database index will be set on the field for
|
||||
# fast access.
|
||||
self.indexed = indexed
|
||||
# If specified "searchable", the field will be added to some global
|
||||
# index allowing to perform application-wide, keyword searches.
|
||||
self.searchable = searchable
|
||||
# Normally, permissions to read or write every attribute in a type are
|
||||
# granted if the user has the global permission to read or
|
||||
|
@ -108,12 +121,12 @@ class Type:
|
|||
class Integer(Type):
|
||||
def __init__(self, validator=None, multiplicity=(0,1), index=None,
|
||||
default=None, optional=False, editDefault=False, show=True,
|
||||
page='main', group=None, move=0, searchable=False,
|
||||
specificReadPermission=False, specificWritePermission=False,
|
||||
width=None, height=None, master=None, masterValue=None,
|
||||
focus=False):
|
||||
page='main', group=None, move=0, indexed=False,
|
||||
searchable=False, specificReadPermission=False,
|
||||
specificWritePermission=False, width=None, height=None,
|
||||
master=None, masterValue=None, focus=False):
|
||||
Type.__init__(self, validator, multiplicity, index, default, optional,
|
||||
editDefault, show, page, group, move, False,
|
||||
editDefault, show, page, group, move, indexed, False,
|
||||
specificReadPermission, specificWritePermission, width,
|
||||
height, master, masterValue, focus)
|
||||
self.pythonType = long
|
||||
|
@ -121,12 +134,12 @@ class Integer(Type):
|
|||
class Float(Type):
|
||||
def __init__(self, validator=None, multiplicity=(0,1), index=None,
|
||||
default=None, optional=False, editDefault=False, show=True,
|
||||
page='main', group=None, move=0, searchable=False,
|
||||
specificReadPermission=False, specificWritePermission=False,
|
||||
width=None, height=None, master=None, masterValue=None,
|
||||
focus=False):
|
||||
page='main', group=None, move=0, indexed=False,
|
||||
searchable=False, specificReadPermission=False,
|
||||
specificWritePermission=False, width=None, height=None,
|
||||
master=None, masterValue=None, focus=False):
|
||||
Type.__init__(self, validator, multiplicity, index, default, optional,
|
||||
editDefault, show, page, group, move, False,
|
||||
editDefault, show, page, group, move, indexed, False,
|
||||
specificReadPermission, specificWritePermission, width,
|
||||
height, master, masterValue, focus)
|
||||
self.pythonType = float
|
||||
|
@ -178,12 +191,12 @@ class String(Type):
|
|||
XHTML = 2
|
||||
def __init__(self, validator=None, multiplicity=(0,1), index=None,
|
||||
default=None, optional=False, editDefault=False, format=LINE,
|
||||
show=True, page='main', group=None, move=0, searchable=False,
|
||||
specificReadPermission=False, specificWritePermission=False,
|
||||
width=None, height=None, master=None, masterValue=None,
|
||||
focus=False):
|
||||
show=True, page='main', group=None, move=0, indexed=False,
|
||||
searchable=False, specificReadPermission=False,
|
||||
specificWritePermission=False, width=None, height=None,
|
||||
master=None, masterValue=None, focus=False):
|
||||
Type.__init__(self, validator, multiplicity, index, default, optional,
|
||||
editDefault, show, page, group, move, searchable,
|
||||
editDefault, show, page, group, move, indexed, searchable,
|
||||
specificReadPermission, specificWritePermission, width,
|
||||
height, master, masterValue, focus)
|
||||
self.format = format
|
||||
|
@ -204,12 +217,12 @@ class String(Type):
|
|||
class Boolean(Type):
|
||||
def __init__(self, validator=None, multiplicity=(0,1), index=None,
|
||||
default=None, optional=False, editDefault=False, show=True,
|
||||
page='main', group=None, move=0, searchable=False,
|
||||
specificReadPermission=False, specificWritePermission=False,
|
||||
width=None, height=None, master=None, masterValue=None,
|
||||
focus=False):
|
||||
page='main', group=None, move=0, indexed=False,
|
||||
searchable=False, specificReadPermission=False,
|
||||
specificWritePermission=False, width=None, height=None,
|
||||
master=None, masterValue=None, focus=False):
|
||||
Type.__init__(self, validator, multiplicity, index, default, optional,
|
||||
editDefault, show, page, group, move, searchable,
|
||||
editDefault, show, page, group, move, indexed, searchable,
|
||||
specificReadPermission, specificWritePermission, width,
|
||||
height, master, masterValue, focus)
|
||||
self.pythonType = bool
|
||||
|
@ -221,13 +234,13 @@ class Date(Type):
|
|||
def __init__(self, validator=None, multiplicity=(0,1), index=None,
|
||||
default=None, optional=False, editDefault=False,
|
||||
format=WITH_HOUR, startYear=time.localtime()[0]-10,
|
||||
endYear=time.localtime()[0]+10,
|
||||
show=True, page='main', group=None, move=0, searchable=False,
|
||||
endYear=time.localtime()[0]+10, show=True, page='main',
|
||||
group=None, move=0, indexed=False, searchable=False,
|
||||
specificReadPermission=False, specificWritePermission=False,
|
||||
width=None, height=None, master=None, masterValue=None,
|
||||
focus=False):
|
||||
Type.__init__(self, validator, multiplicity, index, default, optional,
|
||||
editDefault, show, page, group, move, searchable,
|
||||
editDefault, show, page, group, move, indexed, searchable,
|
||||
specificReadPermission, specificWritePermission, width,
|
||||
height, master, masterValue, focus)
|
||||
self.format = format
|
||||
|
@ -237,12 +250,12 @@ class Date(Type):
|
|||
class File(Type):
|
||||
def __init__(self, validator=None, multiplicity=(0,1), index=None,
|
||||
default=None, optional=False, editDefault=False, show=True,
|
||||
page='main', group=None, move=0, searchable=False,
|
||||
specificReadPermission=False, specificWritePermission=False,
|
||||
width=None, height=None, master=None, masterValue=None,
|
||||
focus=False, isImage=False):
|
||||
page='main', group=None, move=0, indexed=False,
|
||||
searchable=False, specificReadPermission=False,
|
||||
specificWritePermission=False, width=None, height=None,
|
||||
master=None, masterValue=None, focus=False, isImage=False):
|
||||
Type.__init__(self, validator, multiplicity, index, default, optional,
|
||||
editDefault, show, page, group, move, False,
|
||||
editDefault, show, page, group, move, indexed, False,
|
||||
specificReadPermission, specificWritePermission, width,
|
||||
height, master, masterValue, focus)
|
||||
self.isImage = isImage
|
||||
|
@ -253,12 +266,12 @@ class Ref(Type):
|
|||
editDefault=False, add=False, link=True, unlink=False,
|
||||
back=None, isBack=False, show=True, page='main', group=None,
|
||||
showHeaders=False, shownInfo=(), wide=False, select=None,
|
||||
maxPerPage=30, move=0, searchable=False,
|
||||
maxPerPage=30, move=0, indexed=False, searchable=False,
|
||||
specificReadPermission=False, specificWritePermission=False,
|
||||
width=None, height=None, master=None, masterValue=None,
|
||||
focus=False):
|
||||
Type.__init__(self, validator, multiplicity, index, default, optional,
|
||||
editDefault, show, page, group, move, False,
|
||||
editDefault, show, page, group, move, indexed, False,
|
||||
specificReadPermission, specificWritePermission, width,
|
||||
height, master, masterValue, focus)
|
||||
self.klass = klass
|
||||
|
@ -283,12 +296,13 @@ class Ref(Type):
|
|||
class Computed(Type):
|
||||
def __init__(self, validator=None, multiplicity=(0,1), index=None,
|
||||
default=None, optional=False, editDefault=False, show=True,
|
||||
page='main', group=None, move=0, searchable=False,
|
||||
specificReadPermission=False, specificWritePermission=False,
|
||||
width=None, height=None, method=None, plainText=True,
|
||||
master=None, masterValue=None, focus=False):
|
||||
page='main', group=None, move=0, indexed=False,
|
||||
searchable=False, specificReadPermission=False,
|
||||
specificWritePermission=False, width=None, height=None,
|
||||
method=None, plainText=True, master=None, masterValue=None,
|
||||
focus=False):
|
||||
Type.__init__(self, None, multiplicity, index, default, optional,
|
||||
False, show, page, group, move, False,
|
||||
False, show, page, group, move, indexed, False,
|
||||
specificReadPermission, specificWritePermission, width,
|
||||
height, master, masterValue, focus)
|
||||
self.method = method # The method used for computing the field value
|
||||
|
@ -302,12 +316,13 @@ class Action(Type):
|
|||
tool class. An action is rendered as a button.'''
|
||||
def __init__(self, validator=None, multiplicity=(1,1), index=None,
|
||||
default=None, optional=False, editDefault=False, show=True,
|
||||
page='main', group=None, move=0, searchable=False,
|
||||
specificReadPermission=False, specificWritePermission=False,
|
||||
width=None, height=None, action=None, result='computation',
|
||||
master=None, masterValue=None, focus=False):
|
||||
page='main', group=None, move=0, indexed=False,
|
||||
searchable=False, specificReadPermission=False,
|
||||
specificWritePermission=False, width=None, height=None,
|
||||
action=None, result='computation', master=None,
|
||||
masterValue=None, focus=False):
|
||||
Type.__init__(self, None, (0,1), index, default, optional,
|
||||
False, show, page, group, move, False,
|
||||
False, show, page, group, move, indexed, False,
|
||||
specificReadPermission, specificWritePermission, width,
|
||||
height, master, masterValue, focus)
|
||||
self.action = action # Can be a single method or a list/tuple of methods
|
||||
|
@ -351,12 +366,12 @@ class Info(Type):
|
|||
(text, html...) to the user.'''
|
||||
def __init__(self, validator=None, multiplicity=(1,1), index=None,
|
||||
default=None, optional=False, editDefault=False, show=True,
|
||||
page='main', group=None, move=0, searchable=False,
|
||||
specificReadPermission=False, specificWritePermission=False,
|
||||
width=None, height=None, master=None, masterValue=None,
|
||||
focus=False):
|
||||
page='main', group=None, move=0, indexed=False,
|
||||
searchable=False, specificReadPermission=False,
|
||||
specificWritePermission=False, width=None, height=None,
|
||||
master=None, masterValue=None, focus=False):
|
||||
Type.__init__(self, None, (0,1), index, default, optional,
|
||||
False, show, page, group, move, False,
|
||||
False, show, page, group, move, indexed, False,
|
||||
specificReadPermission, specificWritePermission, width,
|
||||
height, master, masterValue, focus)
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ from utils import stringify
|
|||
import appy.gen
|
||||
import appy.gen.descriptors
|
||||
from appy.gen.po import PoMessage
|
||||
from appy.gen import Date, String, State, Transition, Type
|
||||
from appy.gen import Date, String, State, Transition, Type, Search
|
||||
from appy.gen.utils import GroupDescr, PageDescr, produceNiceMessage
|
||||
TABS = 4 # Number of blanks in a Python indentation.
|
||||
|
||||
|
@ -433,10 +433,10 @@ class ArchetypesClassDescriptor(ClassDescriptor):
|
|||
self.name = self.getClassName(klass)
|
||||
self.generateSchema()
|
||||
|
||||
@staticmethod
|
||||
def getClassName(klass):
|
||||
'''Generates the name of the corresponding Archetypes class.'''
|
||||
return klass.__module__.replace('.', '_') + '_' + klass.__name__
|
||||
getClassName = staticmethod(getClassName)
|
||||
|
||||
def isAbstract(self):
|
||||
'''Is self.klass abstract?'''
|
||||
|
@ -475,6 +475,21 @@ class ArchetypesClassDescriptor(ClassDescriptor):
|
|||
res = self.isFolder(theClass.__bases__[0])
|
||||
return res
|
||||
|
||||
@staticmethod
|
||||
def getSearches(klass):
|
||||
'''Returns the list of searches that are defined on this class.'''
|
||||
res = []
|
||||
if klass.__dict__.has_key('search'):
|
||||
searches = klass.__dict__['search']
|
||||
if isinstance(searches, basestring): res.append(Search(searches))
|
||||
elif isinstance(searches, Search): res.append(searches)
|
||||
else:
|
||||
# It must be a list of searches.
|
||||
for search in searches:
|
||||
if isinstance(search, basestring):res.append(Search(search))
|
||||
else: res.append(search)
|
||||
return res
|
||||
|
||||
def addGenerateDocMethod(self):
|
||||
m = self.methods
|
||||
spaces = TABS
|
||||
|
|
|
@ -675,6 +675,16 @@ class Generator(AbstractGenerator):
|
|||
poMsgDescr = PoMessage('%s_%d_edit_descr' % (classDescr.name, i),
|
||||
'', ' ')
|
||||
self.labels.append(poMsgDescr)
|
||||
# Remember i18n labels for searches
|
||||
for search in classDescr.getSearches(classDescr.klass):
|
||||
searchLabelId = '%s_search_%s' % (classDescr.name, search.name)
|
||||
searchDescrId = '%s_descr' % searchLabelId
|
||||
for label in (searchLabelId, searchDescrId):
|
||||
default = ' '
|
||||
if label == searchLabelId: default = search.name
|
||||
poMsg = PoMessage(label, '', default)
|
||||
poMsg.produceNiceDefault()
|
||||
self.labels.append(poMsg)
|
||||
# Generate the resulting Archetypes class and schema.
|
||||
self.copyFile('ArchetypesTemplate.py', repls, destName=fileName)
|
||||
|
||||
|
|
|
@ -319,11 +319,10 @@ class AbstractMixin:
|
|||
if isinstance(fieldDescr, FieldDescr):
|
||||
fieldDescr = fieldDescr.__dict__
|
||||
appyType = fieldDescr['appyType']
|
||||
if isEdit and (appyType['type']=='Ref') and appyType['add']:
|
||||
return False
|
||||
if isEdit and (appyType['type']=='Ref') and appyType['add']:return False
|
||||
if isEdit and appyType['type']=='Action': return False
|
||||
if (fieldDescr['widgetType'] == 'backField') and \
|
||||
not self.getBRefs(fieldDescr['fieldRel']):
|
||||
return False
|
||||
not self.getBRefs(fieldDescr['fieldRel']): return False
|
||||
# Do not show field if it is optional and not selected in flavour
|
||||
if appyType['optional']:
|
||||
tool = self.getTool()
|
||||
|
|
|
@ -26,9 +26,10 @@
|
|||
function toggleViewableElements() {
|
||||
var rows = cssQuery('#importedElem');
|
||||
var newDisplay = 'table-row';
|
||||
if (isIe) newDisplay = 'block';
|
||||
if (importedElemsShown) newDisplay = 'none';
|
||||
for (var i=0; i<rows.length; i++) {
|
||||
rows[i].style.display = newDisplay;
|
||||
rows[i].style.display = newDisplay;
|
||||
}
|
||||
importedElemsShown = !importedElemsShown;
|
||||
}
|
||||
|
|
|
@ -103,7 +103,8 @@
|
|||
</div>
|
||||
|
||||
<div metal:define-macro="showActionField">
|
||||
<form name="executeAppyAction" action="skyn/do" method="POST">
|
||||
<form name="executeAppyAction"
|
||||
tal:attributes="action python: contextObj.absolute_url()+'/skyn/do'">
|
||||
<input type="hidden" name="action" value="ExecuteAppyAction"/>
|
||||
<input type="hidden" name="objectUid" tal:attributes="value contextObj/UID"/>
|
||||
<input type="hidden" name="fieldName" tal:attributes="value field/getName"/>
|
||||
|
@ -175,7 +176,7 @@
|
|||
<tal:computedField condition="python: (not isEdit) and (appyType['type'] == 'Computed')">
|
||||
<metal:cf use-macro="here/skyn/macros/macros/showComputedField" />
|
||||
</tal:computedField>
|
||||
<tal:actionField condition="python: (not isEdit) and (appyType['type'] == 'Action')">
|
||||
<tal:actionField condition="python: appyType['type'] == 'Action'">
|
||||
<metal:af use-macro="here/skyn/macros/macros/showActionField" />
|
||||
</tal:actionField>
|
||||
<tal:masterString condition="python: isEdit and (appyType['type'] in ('String', 'Boolean')) and (appyType['slaves'])">
|
||||
|
@ -311,6 +312,7 @@
|
|||
<tal:comment replace="nothing">"Static" javascripts</tal:comment>
|
||||
<script language="javascript">
|
||||
<!--
|
||||
var isIe = (navigator.appName == "Microsoft Internet Explorer");
|
||||
// AJAX machinery
|
||||
var xhrObjects = new Array(); // An array of XMLHttpRequest objects
|
||||
function XhrObject() { // Wraps a XmlHttpRequest object
|
||||
|
|
3177
pod/test/Tests.rtf
3177
pod/test/Tests.rtf
File diff suppressed because it is too large
Load diff
44
pod/test/contexts/XhtmlComplex4.py
Normal file
44
pod/test/contexts/XhtmlComplex4.py
Normal file
|
@ -0,0 +1,44 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
xhtmlInput = '''
|
||||
<p>Champ FCK</p>
|
||||
<ol>
|
||||
<li>aaaa
|
||||
<ol>
|
||||
<li>Azerty</li>
|
||||
<li>aaaa</li>
|
||||
</ol>
|
||||
</li>
|
||||
<li>edzfrgh</li>
|
||||
<li>Kupu</li>
|
||||
</ol>
|
||||
<table cellspacing="1" cellpadding="1" border="1" style="width: 210px; height: 66px;">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>a</td>
|
||||
<td>b</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>x</td>
|
||||
<td>vvv</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>bbb</td>
|
||||
<td>vvvvv</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p> </p>
|
||||
<p style="margin-left: 40px;">hghdghghgh</p>
|
||||
<ul>
|
||||
<li>aaa</li>
|
||||
<li> </li>
|
||||
<li>bvbb</li>
|
||||
</ul>
|
||||
<ol>
|
||||
<li>regrg</li>
|
||||
<li> </li>
|
||||
</ol>
|
||||
<p>vghriqghrghgfd hgkll hgjkf lghjfkd slhgjfd klhgjfds klghjfds s&é@èù vghriqghrghgfd hgkll hgjkf lghjfkd slhgjfd klhgjfds klghjfds s&é@èù vghriqghrghgfd hgkll hgjkf lghjfkd slhgjfd klhgjfds klghjfds s&é@èù vghriqghrghgfd hgkll hgjkf lghjfkd slhgjfd klhgjfds klghjfds s&é@èù vghriqghrghgfd hgkll hgjkf lghjfkd slhgjfd klhgjfds klghjfds s&é@èù vghriqghrghgfd hgkll hgjkf lghjfkd slhgjfd klhgjfds klghjfds s&é@èù vghriqghrghgfd hgkll hgjkf lghjfkd slhgjfd klhgjfds klghjfds s&é@èù</p>
|
||||
<p> </p>
|
||||
<p>vghriqghrghgfd hgkll hgjkf lghjfkd slhgjfd klhgjfds klghjfds s&é@èù vghriqghrghgfd hgkll hgjkf lghjfkd slhgjfd klhgjfds klghjfds s&é@èù vghriqghrghgfd hgkll hgjkf lghjfkd slhgjfd klhgjfds klghjfds s&é@èù vghriqghrghgfd hgkll hgjkf lghjfkd slhgjfd klhgjfds klghjfds s&é@èù vghriqghrghgfd hgkll hgjkf lghjfkd slhgjfd klhgjfds klghjfds s&é@èù vghriqghrghgfd hgkll hgjkf lghjfkd slhgjfd klhgjfds klghjfds s&é@èù vghriqghrghgfd hgkll hgjkf lghjfkd slhgjfd klhgjfds klghjfds s&é@</p>
|
||||
'''
|
BIN
pod/test/results/xhtmlComplex4.odt
Normal file
BIN
pod/test/results/xhtmlComplex4.odt
Normal file
Binary file not shown.
BIN
pod/test/templates/XhtmlComplex4.odt
Executable file
BIN
pod/test/templates/XhtmlComplex4.odt
Executable file
Binary file not shown.
|
@ -33,8 +33,8 @@ DEFAULT_ODT_STYLES = {'b': 'podBold', 'strong':'podBold', 'i': 'podItalic',
|
|||
INNER_TAGS = ('b', 'strong', 'i', 'em', 'sup', 'sub', 'span', 'div')
|
||||
TABLE_CELL_TAGS = ('td', 'th')
|
||||
OUTER_TAGS = TABLE_CELL_TAGS + ('li',)
|
||||
NOT_INSIDE_P = ('table', 'ol', 'ul') # Those elements can't be rendered inside
|
||||
# paragraphs.
|
||||
NOT_INSIDE_P = XHTML_HEADINGS + XHTML_LISTS + ('table',) # Those elements
|
||||
# can't be rendered inside paragraphs.
|
||||
NOT_INSIDE_LIST = ('table',)
|
||||
IGNORABLE_TAGS = ('meta', 'title', 'style')
|
||||
HTML_ENTITIES = {
|
||||
|
@ -247,7 +247,7 @@ class XhtmlEnvironment(XmlEnvironment):
|
|||
mustEndParagraph = True
|
||||
if self.creatingRootParagraph:
|
||||
mustStartParagraph = False
|
||||
if currentElem and not (currentElem in XHTML_PARAGRAPH_TAGS):
|
||||
if currentElem and (currentElem not in NOT_INSIDE_P+('p',)):
|
||||
mustEndParagraph = False
|
||||
if mustStartParagraph and mustEndParagraph and \
|
||||
not self.currentContent.strip():
|
||||
|
|
Loading…
Reference in a new issue