class TextAreaWidget(Widget): """Textarea widget """ property_names = Widget.property_names +\ ['width', 'height', 'extra'] default = fields.TextAreaField( 'default', title='Default', description=("Default value of the text in the widget."), default="", width=20, height=3, required=0) width = fields.IntegerField( 'width', title='Width', description=("The width (columns) in characters. Required."), default=40, required=1) height = fields.IntegerField( 'height', title="Height", description=("The height (rows) in characters. Required."), default=5, required=1) def render(self, field, key, value, REQUEST): width = field.get_value('width') height = field.get_value('height') extra = field.get_value('extra') css_class = field.get_value('css_class') kw = { 'name': key, 'css_class': css_class, 'cols': width, 'rows': height, 'contents': cgi.escape(value) } if not extra or not id_value_re.search(extra): kw['id'] = field.generate_field_html_id(key) contents = render_element("textarea", **kw) return render_element("div", contents=contents, css_class=css_class) def render_view(self, field, value): return render_value(value)
class LabelWidget(Widget): """Widget that is a label only. It simply returns its default value. """ property_names = [ 'title', 'description', 'default', 'css_class', 'hidden', 'extra' ] default = fields.TextAreaField('default', title="Label text", description="Label text to render", default="", width=20, height=3, required=0) def render(self, field, key, value, REQUEST): return render_element("div", css_class=field.get_value('css_class'), contents=field.get_value('default')) # XXX should render view return the same information as render? def render_view(self, field, value): return field.get_value('default')
def create_settings_form(): """Create settings form for ZMIForm. """ form = BasicForm('manage_settings') title = fields.StringField('title', title="Title", required=0, default="") description = fields.TextAreaField('description', title="Description", required=0, default="") row_length = fields.IntegerField('row_length', title='Number of groups in row (in order tab)', required=1, default=4) name = fields.StringField('name', title="Form name", required=0, default="") pt = fields.StringField('pt', title="Page Template", required=0, default="") action = fields.StringField('action', title='Form action', required=0, default="") update_action = fields.StringField('update_action', title='Form update action', required=0, default="") update_action_title = fields.StringField('update_action_title', title="Update Action Title", required=0, default="") method = fields.ListField('method', title='Form method', items=[('POST', 'POST'), ('GET', 'GET')], required=1, size=1, default='POST') enctype = fields.ListField('enctype', title='Form enctype', items=[('No enctype', ""), ('application/x-www-form-urlencoded', 'application/x-www-form-urlencoded'), ('multipart/form-data', 'multipart/form-data')], required=0, size=1, default=None) encoding = fields.StringField('encoding', title='Encoding of pages the form is in', default="UTF-8", required=1) stored_encoding = fields.StringField('stored_encoding', title='Encoding of form properties', default='UTF-8', required=1) unicode_mode = fields.CheckBoxField('unicode_mode', title='Form properties are unicode', default=0, required=1) edit_order = fields.LinesField('edit_order', title='Setters for these properties should be' '<br /> called by edit() in the defined order') form.add_fields([title, description, row_length, name, pt, action, update_action, update_action_title, method, enctype, encoding, stored_encoding, unicode_mode, edit_order]) return form
class MatrixBoxWidget(Widget.Widget): """ An UI widget which displays a matrix Don't forget that you can use tales expressions for every field, so this is really usefull if you want to use fonctions instead of predefined variables. A function is provided to - access a cell - modify a cell """ property_names = Widget.Widget.property_names +\ ['cell_base_id', 'cell_portal_type', 'lines', 'columns', 'tabs', 'as_cell_range_script_id', 'getter_method', 'editable_attributes', 'global_attributes', 'cell_getter_method', 'update_cell_range', 'url_cells' ] default = fields.TextAreaField( 'default', title='Default', description=("Default value of the text in the widget."), default="", width=20, height=3, required=0) as_cell_range_script_id = fields.StringField( 'as_cell_range_script_id', title='Cell range method', description=( "Method returning columns, lines and tabs. The method is passed" " matrixbox=True, base_id=base_id as arguments."), default='', required=0) columns = fields.ListTextAreaField( 'columns', title="Columns", description=( "This defines columns of the matrixbox. " "This should be a list of couples, " "couple[0] is the variation, and couple[1] is the name displayed " "to the user.\n" "For example (('color/blue', 'Bleu'), ('color/red','Red')).\n" " Deprecated, use cell range method instead"), default=[], required=0) lines = fields.ListTextAreaField( 'lines', title="Lines", description= ("This defines lines of the matrixbox. This should be a list of couples, " "couple[0] is the variation, and couple[1] is the name displayed " "to the user.\n" "For example (('size/baby/02','baby/02'),('size/baby/03','baby/03')).\n" "Deprecated, use cell range method instead"), default=[], required=0) tabs = fields.ListTextAreaField( 'tabs', title="Tabs", description=( "This defines tabs. You can use it with the same way as Lines " "and Columns.\n" "This is used only if you have more than 2 kinds of variations.\n" "Deprecated, use cell range method instead"), default=[], required=0) # XXX ListTextAreaField ? cell_range = fields.ListTextAreaField( 'cell_range', title="Cell Range", description=("This defines the range of the matrix."), default=[], required=0) getter_method = fields.StringField( 'getter_method', title='Getter method', description= ("You can specify a specific method in order to retrieve the context. " "This field can be empty, if so the MatrixBox will use the default " "context."), default='', required=0) cell_getter_method = fields.StringField( 'cell_getter_method', title='Cell Getter method', description= ("You can specify a method in order to retrieve cells. This field can " "be empty, if so the MatrixBox will use the default method : getCell." ), default='', required=0) new_cell_method = fields.MethodField( 'new_cell_method', title='New Cell method', description=( "You can specify a specific method in order to create cells. " "This field can be empty, if so the MatrixBox will use the default " "method : newCell."), default='', required=0) editable_attributes = fields.ListTextAreaField( 'editable_attributes', title="Editable Properties", description=( "A list of attributes which are set by hidden fields called " "matrixbox_attribute_name. This is used " "when we want to specify a computed value for each cell"), default=[], required=0) global_attributes = fields.ListTextAreaField( 'global_attributes', title="Global Properties", description=( "An optional list of globals attributes which are set by hidden " "fields and which are applied to each cell. " "This is used if we want to set the same value for every cell"), default=[], required=0) cell_base_id = fields.StringField( 'cell_base_id', title='Base id for cells', description=( "The Base id for cells : this is the name used to store cells, " "we usually use names like : 'movement', 'path', ... "), default='cell', required=0) cell_portal_type = fields.StringField( 'cell_portal_type', title='Portal Type for cells', description=( "The Portal Type for cells : This is the portal type used to " "create a new cell."), default='Mapped Value', required=0) update_cell_range = fields.CheckBoxField( 'update_cell_range', title="Update Cell Range", description=("The cell range should be updated upon edit."), default=0) url_cells = fields.ListTextAreaField( 'url_cells', title="URL Cells", description=( "An optional list of cells which can provide a custom URL." "If no url cell is used, then no link is displayed."), default=[], required=0) def render(self, field, key, value, REQUEST, render_format='html', render_prefix=None): """ This is where most things happen. This method renders a list of items """ # First grasp the variables we may need here = REQUEST['here'] form = field.aq_parent field_title = field.get_value('title') cell_base_id = field.get_value('cell_base_id') context = here getter_method_id = field.get_value('getter_method') if getter_method_id not in (None, ''): context = getattr(here, getter_method_id)() if context is None: return '' as_cell_range_script_id = field.get_value('as_cell_range_script_id') extra_dimension_category_list_list = [None] if as_cell_range_script_id: lines = [] columns = [] tabs = [] dimension_list = guarded_getattr(context, as_cell_range_script_id)( matrixbox=True, base_id=cell_base_id) len_dimension_list = len(dimension_list) if len_dimension_list: if len_dimension_list == 1: lines, = dimension_list elif len_dimension_list == 2: lines, columns = dimension_list elif len_dimension_list >= 3: lines, columns, tabs = dimension_list[:3] if len_dimension_list > 3: extra_dimension_list = dimension_list[3:] extra_dimension_category_label_dict = {} extra_dimension_category_index_dict = {} for extra_dimension in extra_dimension_list: for index, (category, label) in enumerate(extra_dimension): extra_dimension_category_label_dict[ category] = label extra_dimension_category_index_dict[ category] = index from Products.ERP5Type.Utils import cartesianProduct extra_dimension_category_list_list = cartesianProduct( [[category for category, label in extra_dimension] for extra_dimension in extra_dimension_list]) else: lines = field.get_value('lines') columns = field.get_value('columns') tabs = field.get_value('tabs') field_errors = REQUEST.get('field_errors', {}) cell_getter_method_id = field.get_value('cell_getter_method') if cell_getter_method_id not in (None, ''): cell_getter_method = getattr(context, cell_getter_method_id) else: cell_getter_method = context.getCell editable_attributes = field.get_value('editable_attributes') url_cells = field.get_value('url_cells') url_cell_dict = dict(url_cells) # This is required when we have no tabs if len(tabs) == 0: tabs = [(None, None)] # This is required when we have no columns if len(columns) == 0: columns = [(None, None)] column_ids = [x[0] for x in columns] line_ids = [x[0] for x in lines] tab_ids = [x[0] for x in tabs] editable_attribute_ids = [x[0] for x in editable_attributes] # THIS MUST BE REMOVED - WHY IS THIS BAD ? # IT IS BAD BECAUSE TAB_IDS DO NOT DEFINE A RANGE.... # here.setCellRange(line_ids, column_ids, base_id=cell_base_id) # result for the list render list_result = [] url = REQUEST.URL list_html = '' for extra_dimension_category_list in extra_dimension_category_list_list: if extra_dimension_category_list is None: extra_dimension_label = '' extra_dimension_position = () extra_dimension_index = '' extra_dimension_category_list = [] else: extra_dimension_label = ',' + ','.join([ extra_dimension_category_label_dict[category] for category in extra_dimension_category_list ]) extra_dimension_position = tuple([ extra_dimension_category_index_dict[category] for category in extra_dimension_category_list ]) extra_dimension_index = '_' + '_'.join( map(str, extra_dimension_position)) # Create one table per tab k = 0 kwd = dict(base_id=cell_base_id) for tab in tabs: tab_id = tab[0] if (tab_id is not None) and \ (not isinstance(tab_id, (list, tuple))): tab_id = [tab_id] if render_format == 'list': list_result_tab = [[tab[1]]] # Create the header of the table - this should probably become DTML first_tab = tab[1] or '' header = """\ <!-- Matrix Content --> <div class="matrixbox_label_tab">%s</div> <div class="MatrixContent"> <table> """ % (first_tab + extra_dimension_label) # Create the footer. This should be replaced by DTML # And work as some kind of parameter footer = """\ <tr> <td colspan="%i" class="Data footer"> </td> </tr> </table> </div> """ % (len(columns) + 1) list_header = """\ <tr class="matrixbox_label_line"><td class=\"Data\"></td> """ for cname in columns: first_column = cname[1] or '' list_header = list_header + ( "<td class=\"Data\">%s</td>\n" % first_column) if render_format == 'list': list_result_tab[0].append(cname[1]) list_header = list_header + "</tr>" # Build Lines i = 0 j = 0 list_body = '' for l in lines: if not i % 2: td_css = 'DataA' else: td_css = 'DataB' list_body = list_body + '\n<tr class=\"%s\"><td class=\"matrixbox_label_column\">%s</td>' % ( td_css, str(l[1])) j = 0 if render_format == 'list': list_result_lines = [str(l[1])] for c in columns: has_error = False column_id = c[0] if (column_id is not None) and \ (not isinstance(column_id, (list, tuple))): column_id = [column_id] if column_id is None: kw = [l[0]] elif tab_id is None: kw = [l[0], c[0]] else: kw = [l[0], c[0] ] + tab_id + extra_dimension_category_list cell = cell_getter_method(*kw, **kwd) REQUEST['cell'] = cell REQUEST['cell_index'] = kw cell_body = '' cell_url = None for attribute_id in editable_attribute_ids: if attribute_id in url_cell_dict: url_method_id = url_cell_dict[attribute_id] if url_method_id not in (None, ''): url_method = getattr( cell, url_method_id, None) if url_method is not None: try: cell_url = url_method( brain=cell, cell_index=kw, cell_position=( (i, j, k) + extra_dimension_position)) except (ConflictError, RuntimeError): raise except: LOG('MatrixBox', WARNING, 'Could not evaluate the url ' 'method %r with %r' % (url_method, cell), error=sys.exc_info()) else: LOG( 'MatrixBox', WARNING, 'Could not find the url method %s' % (url_method_id, )) my_field_id = '%s_%s' % (field.id, attribute_id) if form.has_field(my_field_id): my_field = form.get_field(my_field_id) key = my_field.id + '_cell_%s_%s_%s%s' % ( i, j, k, extra_dimension_index) default_value = my_field.get_value( 'default', cell=cell, cell_index=kw, cell_position=((i, j, k) + extra_dimension_position)) display_value = default_value if field_errors: # Display previous value in case of any error in this form because # we have no cell to get value from display_value = REQUEST.get( 'field_%s' % key, default_value) if cell is not None: if render_format == 'html': cell_html = my_field.render( value=display_value, REQUEST=REQUEST, key=key) if cell_url: # don't make a link if widget is editable if not my_field.get_value( 'editable', cell=cell, cell_index=kw, cell_position=( (i, j, k) + extra_dimension_position )): cell_html = "<a href='%s'>%s</a>" % ( cell_url, cell_html) if key in field_errors: # Display error message if this cell has an error has_error = True cell_body += '<span class="input">%s</span>%s' % ( cell_html, translateString( field_errors[key]. error_text)) else: cell_body += '<span class="input">%s</span>' % ( cell_html) else: if render_format == 'html': if key in field_errors: # Display error message if this cell has an error has_error = True cell_body += '<span class="input">%s</span>%s' % ( my_field.render( value=display_value, REQUEST=REQUEST, key=key), translateString( field_errors[key]. error_text)) else: cell_body += '<span class="input">%s</span>' %\ my_field.render( value=display_value, REQUEST=REQUEST, key=key) if render_format == 'list': # list rendering doesn't make difference when cell exists or not list_result_lines.append({ 'default': default_value, 'value': display_value, 'key': key, 'type': my_field.meta_type if my_field.meta_type != "ProxyField" else my_field. getRecursiveTemplateField().meta_type, 'field_id': my_field.id, 'error_text': u"%s" % (translateString( field_errors[key].error_text) if key in field_errors else '') }) css = td_css if has_error: css = 'error' list_body = list_body + \ ('<td class=\"%s\">%s</td>' % (css, cell_body)) j += 1 list_body = list_body + '</tr>' i += 1 if render_format == 'list': list_result_tab.append(list_result_lines) list_html += header + list_header + \ list_body + footer k += 1 if render_format == 'list': list_result.append(list_result_tab) # XXX Does not leave garbage in REQUEST['cell'], because some other # fields also use that key... REQUEST.other.pop('cell', None) REQUEST.other.pop('cell_index', None) if render_format == 'list': return list_result return list_html
class ZGDChartWidget(Widget.Widget): """ This is the class used in order to include inside ERP5 some very nice charts """ property_names = Widget.Widget.property_names +\ ['selection_name','default_params','chart_title', 'data_method','chart_style','x_title','y_title', 'bg_transparent'] default = fields.TextAreaField( 'default', title='Default', description=("Default value of the text in the widget."), default="", width=20, height=3, required=0) selection_name = fields.StringField( 'selection_name', title='Selection Name', description=('The name of the selection to store' 'params of selection'), default='', required=0) data_method = fields.StringField( 'data_method', title='Data Method', description=('The method wich returns data'), default='', required=0) chart_style = fields.StringField('chart_style', title='Chart Style', description=('The kind of Chart we want'), default='bar_3d', required=0) chart_title = fields.StringField( 'chart_title', title='Chart Title', description=('The Title on the top of the chart'), default='', required=0) x_title = fields.StringField('x_title', title='X Title', description=('The Title for the X axis'), default='', required=0) y_title = fields.StringField('y_title', title='Y Title', description=('The Title for the Y axis'), default='', required=0) default_params = fields.ListTextAreaField( 'default_params', title="Default Parameters", description=("Default Parameters for the List Method."), default=[], required=0) bg_transparent = fields.CheckBoxField( 'bg_transparent', title='Transparent Background', description=('Allows to set the background transparent'), default='', required=0) def render(self, field, key, value, REQUEST, render_prefix=None): """ This is where most things happens """ main_content = "" here = REQUEST['here'] selection_name = field.get_value('selection_name') default_params = field.get_value('default_params') chart_title = field.get_value('chart_title') data_method = field.get_value('data_method') chart_style = field.get_value('chart_style') x_title = field.get_value('x_title') y_title = field.get_value('y_title') bg_transparent = field.get_value('bg_transparent') selection = here.portal_selections.getSelectionFor(selection_name, REQUEST=REQUEST) LOG( 'ZGDChart.render', 0, 'selection: %s, selection_name: %s' % (str(selection), str(selection_name))) # This is the default data, this is just in the case there is not method given data = {'chart_data': []} # Retrieve the data with the data_method if hasattr(here, data_method): LOG('ZGDChart.render', 0, 'found method') data_method = getattr(here, data_method) data['chart_data'] = data_method() data['chart_parameter'] = { 'zgdchart_runtime_title': chart_title, 'zgdchart_runtime_xtitle': x_title, 'zgdchart_runtime_ytitle': y_title, 'zgdchart_runtime_type': 'Line_3D', 'zgdchart_runtime_bg_transparent': bg_transparent } # Creation selection if needed if selection is None: selection = Selection(selection_name, params=data) else: LOG('ZGDChart.render', 0, 'selection is not None') kw = {'params': data} selection.edit(**kw) here.portal_selections.setSelectionFor(selection_name, selection, REQUEST=REQUEST) if len(data['chart_data']) > 0: main_content = """\ <div class="ChartContent"> <table border="0" cellpadding="0" cellspacing="0""> <tr> <td valign="middle" align="center" nowrap> <img src="%s" title="Chart" border="0" alt="img"/"> </td> </tr> </table> </div>""" % str(chart_style + '?selection_name=' + selection_name) return main_content
class Widget: """A field widget that knows how to display itself as HTML. """ property_names = [ 'title', 'description', 'default', 'css_class', 'alternate_name', 'hidden' ] title = fields.StringField( 'title', title='Title', description=( "The title of this field. This is the title of the field that " "will appear in the form when it is displayed. Required."), default="", required=1) description = fields.TextAreaField( 'description', title='Description', description=( "Description of this field. The description property can be " "used to add a short description of what a field does; such as " "this one."), default="", width="20", height="3", required=0) css_class = fields.StringField( 'css_class', title='CSS class', description=( "The CSS class of the field. This can be used to style your " "formulator fields using cascading style sheets. Not required."), default="", required=0) alternate_name = fields.StringField( 'alternate_name', title='Alternate name', description=( "An alternative name for this field. This name will show up in " "the result dictionary when doing validation, and in the REQUEST " "if validation goes to request. This can be used to support names " "that cannot be used as Zope ids."), default="", required=0) hidden = fields.CheckBoxField( 'hidden', title="Hidden", description=( "This field will be on the form, but as a hidden field. The " "contents of the hidden field will be the default value. " "Hidden fields are not visible but will be validated."), default=0) # NOTE: for ordering reasons (we want extra at the end), # this isn't in the base class property_names list, but # instead will be referred to by the subclasses. extra = fields.StringField( 'extra', title='Extra', description=( "A string containing extra HTML code for attributes. This " "string will be literally included in the rendered field." "This property can be useful if you want " "to add an onClick attribute to use with JavaScript, for instance." ), default="", required=0) #this property is used to determine whether the widget # uses an html id (e.g. the widget has a single or primary # input), so that the presentation can wrap the field # title within a label or not. has_html_id = True def render(self, field, key, value, REQUEST): """Renders this widget as HTML using property values in field. """ return "[widget]" def render_hidden(self, field, key, value, REQUEST): """Renders this widget as a hidden field. """ try: extra = field.get_value('extra') except KeyError: # In case extra is not defined as in DateTimeWidget extra = '' kw = {'type': "hidden", 'name': key, 'value': value, 'extra': extra} if not extra or not id_value_re.search(extra): kw['id'] = field.generate_field_html_id(key) return render_element("input", **kw) def render_view(self, field, value): """Renders this widget for public viewing. """ return render_value(value)