new "table" field

This commit is contained in:
Frédéric Péters 2009-03-26 10:43:57 +00:00
parent 51bd030283
commit f80bb44dd5
3 changed files with 156 additions and 1 deletions

View File

@ -144,6 +144,9 @@ class Field:
else:
setattr(self, attribute, el.text.encode(charset))
def get_rst_view_value(self, value, indent=''):
return indent + self.get_view_value(value)
class WidgetField(Field):
type = None
@ -651,6 +654,84 @@ class PageField(Field):
register_field_class(PageField)
class TableField(WidgetField):
key = 'table'
description = N_('Table')
in_listing = False # no way to represent data in a single cell
rows = None
columns = None
widget_class = TableWidget
def __init__(self, **kwargs):
self.rows = None
self.columns = None
WidgetField.__init__(self, **kwargs)
def perform_more_widget_changes(self, form, kwargs, edit = True):
kwargs['rows'] = self.rows
kwargs['columns'] = self.columns
def fill_admin_form(self, form):
WidgetField.fill_admin_form(self, form)
form.add(WidgetList, 'rows', title = _('Rows'), element_type = StringWidget,
value = self.rows, required = True,
element_kwargs = {'render_br': False, 'size': 50},
add_element_label = _('Add row'))
form.add(WidgetList, 'columns', title = _('Columns'), element_type = StringWidget,
value = self.columns, required = True,
element_kwargs = {'render_br': False, 'size': 50},
add_element_label = _('Add column'))
def get_admin_attributes(self):
return WidgetField.get_admin_attributes(self) + ['rows', 'columns']
def get_view_value(self, value):
r = TemplateIO(html=True)
r += htmltext('<table><thead><tr><td></td>')
for column in self.columns:
r += htmltext('<th>%s</th>') % column
r += htmltext('</tr></thead><tbody>')
for i, row in enumerate(self.rows):
r += htmltext('<tr><th>%s</th>') % row
for j, column in enumerate(self.columns):
r += htmltext('<td>')
if value:
r += value[i][j]
r += htmltext('</td>')
r += htmltext('</tr>')
r += htmltext('</tbody></table>')
return r.getvalue()
def get_rst_view_value(self, value, indent=''):
if not value:
return indent
r = []
max_width = 0
for column in self.columns:
max_width = max(max_width, len(column))
for i, row in enumerate(self.rows):
max_width = max(max_width, len(row))
for j, column in enumerate(self.columns):
max_width = max(max_width, len(value[i][j]))
r.append(' '.join(['='*max_width]*(len(self.columns)+1)))
r.append(' '.join([column.center(max_width) for column in ['/']+self.columns]))
r.append(' '.join(['='*max_width]*(len(self.columns)+1)))
for i, row in enumerate(self.rows):
r.append(' '.join([cell.center(max_width) for cell in [row] +
[value[i][x] for x in range(len(self.columns))]]))
r.append(' '.join(['='*max_width]*(len(self.columns)+1)))
return '\n'.join([indent + x for x in r])
register_field_class(TableField)
def get_field_class_by_type(type):
for k in field_classes:

View File

@ -344,7 +344,7 @@ class FormDef(StorableObject):
elif field.type == 'date':
details.append(' %s' % time.strftime(date_format(), data[field.id]))
else:
details.append(' %s' % field.get_view_value(data[field.id]))
details.append('%s' % field.get_rst_view_value(data[field.id], indent=' '))
details.append('')
return '\n'.join(details)

View File

@ -793,3 +793,77 @@ class WysiwygTextWidget(TextWidget):
htmlescape(self.value or '') +
htmltext("</textarea>"))
class TableWidget(CompositeWidget):
readonly = False
def __init__(self, name, value = None, rows = None, columns = None, **kwargs):
CompositeWidget.__init__(self, name, value, **kwargs)
self.rows = rows
self.columns = columns
widget_kwargs = {}
if kwargs.has_key('title'):
del kwargs['title']
if kwargs.has_key('readonly') and kwargs.get('readonly'):
del kwargs['readonly']
self.readonly = True
widget_kwargs['readonly'] = 'readonly'
for i, row in enumerate(rows):
for j, column in enumerate(columns):
widget = self.add(StringWidget, 'c-%s-%s' % (i, j), **widget_kwargs)
widget = self.get_widget('c-%s-%s' % (i, j))
if value and self.readonly:
if not get_request().form:
get_request().form = {}
get_request().form[widget.name] = value[i][j]
widget.set_value(value[i][j])
def render_content(self):
r = TemplateIO(html=True)
r += htmltext('<table><thead><tr><td></td>')
for column in self.columns:
r += htmltext('<th>%s</th>') % column
r += htmltext('</tr></thead><tbody>')
for i, row in enumerate(self.rows):
r += htmltext('<tr><th>%s</th>') % row
for j, column in enumerate(self.columns):
widget = self.get_widget('c-%s-%s' % (i, j))
r += htmltext('<td>')
r += widget.render_content()
r += htmltext('</td>')
r += htmltext('</tr>')
r += htmltext('</tbody></table>')
return r.getvalue()
def parse(self, request=None):
CompositeWidget.parse(self, request=request)
if request is None:
request = get_request()
if request.form or request.get_method() == 'POST':
if self.required and not self.value:
self.set_error(self.REQUIRED_ERROR)
return self.value
def _parse(self, request):
if self.readonly:
return
table = []
for i, row in enumerate(self.rows):
row = []
for j, column in enumerate(self.columns):
widget = self.get_widget('c-%s-%s' % (i, j))
row.append(widget.parse())
table.append(row)
self.value = table
def set_value(self, value):
self.value = value
if not value:
return
for i, row in enumerate(self.rows):
for j, column in enumerate(self.columns):
widget = self.get_widget('c-%s-%s' % (i, j))
widget.set_value(value[i][j])