示例#1
0
class StringValidator(StringBaseValidator):
    property_names = StringBaseValidator.property_names +\
                   ['unicode', 'max_length', 'truncate']
    message_names = StringBaseValidator.message_names +\
                  ['too_long']

    unicode = fields.CheckBoxField(
        'unicode',
        title='Unicode',
        description=(
            "Checked if the field delivers a unicode string instead of an "
            "8-bit string."),
        default=0)
    max_length = fields.IntegerField(
        'max_length',
        title='Maximum length',
        description=(
            "The maximum amount of characters that can be entered in this "
            "field. If set to 0 or is left empty, there is no maximum. "
            "Note that this is server side validation."),
        default="",
        required=0)
    truncate = fields.CheckBoxField(
        'truncate',
        title='Truncate',
        description=(
            "If checked, truncate the field if it receives more input than is "
            "allowed. The behavior in this case is to raise a validation "
            "error, but the text can be silently truncated instead."),
        default=0)

    too_long = _('Too much input was given.')

    def check(self, field, value, failover=False):
        value = StringBaseValidator.check(self, field, value, failover)

        # Verify encoding (using form setting)
        value = ensure_unicode(value,
                               convert=field.get_value('unicode'),
                               encoding=field.get_form_encoding())

        if not failover:
            max_length = field.get_value('max_length') or 0
            if max_length > 0 and len(value) > max_length:
                if field.get_value('truncate'):
                    value = value[:max_length]
                else:
                    self.raise_error('too_long', field)

        return value
示例#2
0
class SelectionValidator(StringBaseValidator):
    property_names = StringBaseValidator.property_names + ['unicode']
    message_names = StringBaseValidator.message_names + ['unknown_selection']

    unicode = fields.CheckBoxField(
        'unicode',
        title='Unicode',
        description=(
            "Checked if the field delivers a unicode string instead of an "
            "8-bit string."),
        default=0)

    unknown_selection = _('You selected an item that was not in the list.')

    def check(self, field, value, failover=False):
        value = StringBaseValidator.check(self, field, value, failover)
        convert = field.get_value('unicode')
        encoding = field.get_form_encoding()
        value = ensure_unicode(value, convert, encoding)

        if not failover and value:
            for item in field.get_value('items'):
                if isinstance(item, (list, tuple)):
                    _, candidate = item
                else:
                    candidate = item
                if ensure_unicode(candidate, convert, encoding) == value:
                    break
            else:
                self.raise_error('unknown_selection', field)
            value = candidate
        return value
示例#3
0
class FileValidator(Validator):
    property_names = Validator.property_names + ['required']
    message_names = Validator.message_names + [
        'required_not_found', 'incorrect_enctype'
    ]

    required_not_found = _('Input is required but no input given.')
    incorrect_enctype = _(
        'Form enctype appears to be either unset or set to application/x-www-form-urlencoded.  For FileUpload types this needs to be set to "multipart/form-data"'
    )

    required = fields.CheckBoxField(
        'required',
        title='Required',
        description=(
            "Checked if the field is required; the user has to supply a file."
        ),
        default=0)

    def validate(self, field, key, REQUEST):
        f = REQUEST.get(key, None)
        if type(f) in StringTypes:
            self.raise_error('incorrect_enctype', field)
        if field.get_value('required'):
            if f.filename == '':
                #I think we can assume that if the filename part
                # of the content-disposition header is empty, then
                # no file was uploaded.  I suppose we should also check to
                # see if the file is of zero length, too.
                self.raise_error('required_not_found', field)
        return REQUEST.get(key, None)
示例#4
0
class CheckBoxWidget(Widget):
    property_names = Widget.property_names + ['extra']

    default = fields.CheckBoxField(
        'default',
        title='Default',
        description=(
            "Default setting of the widget; either checked or unchecked. "
            "(true or false)"),
        default=0)

    def render(self, field, key, value, REQUEST):
        """Render checkbox.
        """
        extra = field.get_value('extra')
        kw = {
            'type': "checkbox",
            'name': key,
            'css_class': field.get_value('css_class'),
            'extra': extra
        }
        if not extra or not id_value_re.search(extra):
            kw['id'] = field.generate_field_html_id(key)
        if value:
            kw['checked'] = None
        return render_element("input", **kw)

    def render_view(self, field, value):
        if value:
            return "Yes"
        return "No"
示例#5
0
class InterfaceValidator(Validator):
    """Formulator validator for an interface.
    """
    property_names = Validator.property_names + ['required']
    message_names = Validator.message_names + [
        'required_not_found', 'invalid_interface'
    ]

    required = fields.CheckBoxField(
        'required',
        title='Required',
        description=(
            u"Checked if the field is required; the user has to fill in some "
            u"data."),
        default=1)

    invalid_interface = u"Input is not a valid interface."
    required_not_found = u"Input is required but no input given."

    def validate(self, field, key, REQUEST):
        value = REQUEST.get(key)
        if value is None:
            if field.get_value('required'):
                self.raise_error('required_not_found', field)
            return None
        interface = queryUtility(IInterface, name=value.strip())
        if interface is None:
            self.raise_error('invalid_interface', field)
        return interface
示例#6
0
class StringBaseValidator(Validator):
    """Simple string validator.
    """
    property_names = Validator.property_names + [
        'required', 'whitespace_preserve'
    ]
    message_names = Validator.message_names + ['required_not_found']

    required = fields.CheckBoxField(
        'required',
        title='Required',
        description=(
            "Checked if the field is required; the user has to fill in some "
            "data."),
        default=1)
    whitespace_preserve = fields.CheckBoxField(
        'whitespace_preserve',
        title="Preserve whitespace",
        description=(
            "Checked if the field preserves whitespace. This means even "
            "just whitespace input is considered to be data."),
        default=0)

    required_not_found = _('Input is required but no input given.')

    def check(self, field, value, failover=False):
        if not field.get_value('whitespace_preserve'):
            value = value.strip()
        if not failover:
            if not value and field.get_value('required'):
                self.raise_error('required_not_found', field)
        return value

    def validate(self, field, key, REQUEST):
        return self.check(field=field,
                          value=REQUEST.get(key, ""),
                          failover=key + '_novalidate' in REQUEST)

    def serializeValue(self, field, value, producer):
        # if our value is not a string type, the SAX lib won't eat it,
        # therefore convert to string first
        if type(value) not in (str, unicode):
            value = str(value)
        producer.characters(value)
示例#7
0
class GadgetFieldValidator(Validator.Validator):

    property_names = Validator.Validator.property_names + ['data_url']

    data_url = fields.CheckBoxField(
        'data_url',
        title='Data Url',
        description=("Checked if gadget return data url."),
        default=0)

    def validate(self, field, key, REQUEST):
        value = REQUEST.get(key, None)
        if value is not None:
            if field.get_value('data_url'):
                value = value.split(",")[1]
                return StringIO(value.decode('base64'))
            return value
示例#8
0
class LinkValidator(StringValidator):
    property_names = StringValidator.property_names + [
        'check_link', 'check_timeout', 'link_type'
    ]
    message_names = StringValidator.message_names + ['not_link']

    check_link = fields.CheckBoxField(
        'check_link',
        title='Check Link',
        description=("Check whether the link is not broken."),
        default=0)
    check_timeout = fields.FloatField(
        'check_timeout',
        title='Check Timeout',
        description=("Maximum amount of seconds to check link. Required"),
        default=7.0,
        required=1)
    link_type = fields.ListField(
        'link_type',
        title='Type of Link',
        default="external",
        size=1,
        items=[('External Link', 'external'), ('Internal Link', 'internal'),
               ('Relative Link', 'relative')],
        description=("Define the type of the link. Required."),
        required=1)

    not_link = _('The specified link is broken.')

    def validate(self, field, key, REQUEST):
        value = StringValidator.validate(self, field, key, REQUEST)
        if value == "" and not field.get_value('required'):
            return value

        link_type = field.get_value('link_type')
        if link_type == 'internal':
            value = urljoin(REQUEST['BASE0'], value)
        elif link_type == 'relative':
            value = urljoin(REQUEST['URL1'], value)
        # otherwise must be external

        # FIXME: should try regular expression to do some more checking here?

        # if we don't need to check the link, we're done now
        if not field.get_value('check_link'):
            return value

        # resolve internal links using Zope's resolve_url
        if link_type in ['internal', 'relative']:
            try:
                REQUEST.resolve_url(value)
            except:
                self.raise_error('not_link', field)

        # check whether we can open the link
        link = LinkHelper(value)
        thread = Thread(target=link.open)
        thread.start()
        thread.join(field.get_value('check_timeout'))
        del thread
        if not link.status:
            self.raise_error('not_link', field)

        return value
示例#9
0
class SingleItemsWidget(ItemsWidget):
    """A widget with a number of items that has only a single
    selectable item.
    """
    default = fields.StringField(
        'default',
        title='Default',
        description=(
            "The default value of the widget; this should be one of the "
            "elements in the list of items."),
        default="",
        required=0)

    first_item = fields.CheckBoxField(
        'first_item',
        title="Select First Item",
        description=("If checked, the first item will always be selected if "
                     "no initial default value is supplied."),
        default=0)

    def render_items(self, field, key, value, REQUEST):

        # get items
        items = field.get_value('items')

        # check if we want to select first item
        if not value and field.get_value('first_item') and len(items) > 0:
            if is_sequence(items[0]):
                text, value = items[0]
            else:
                value = items[0]

        css_class = field.get_value('css_class')
        extra_item = field.get_value('extra_item')

        field_html_id = None
        if not extra_item or not id_value_re.search(extra_item):
            field_html_id = field.generate_field_html_id(key)

        # if we run into multiple items with same value, we select the
        # first one only (for now, may be able to fix this better later)
        selected_found = 0
        rendered_items = []
        index = 0
        for item in items:
            index += 1
            if is_sequence(item):
                item_text, item_value = item
            else:
                item_text = item
                item_value = item

            item_id = field_html_id and field_html_id + str(index) or None
            if item_value == value and not selected_found:
                rendered_item = self.render_selected_item(
                    item_text, item_value, key, css_class, extra_item, item_id)
                selected_found = 1
            else:
                rendered_item = self.render_item(item_text, item_value, key,
                                                 css_class, extra_item,
                                                 item_id)

            rendered_items.append(rendered_item)

        return rendered_items

    def render_view(self, field, value):
        if value is None or value == '':
            # check for empty string too, for situations
            # where no default value is set.
            return ''
        items = field.get_value('items')
        for item in items:
            if is_sequence(item):
                item_text, item_value = item
            else:
                item_text = item
                item_value = item
            if value == item_value:
                return render_value(item_text)
        raise KeyError("Wrong item value [[%s]]" % (value, ))
示例#10
0
class MultiSelectionValidator(Validator):
    property_names = Validator.property_names + ['required', 'unicode']
    message_names = Validator.message_names + [
        'required_not_found', 'unknown_selection'
    ]

    required = fields.CheckBoxField(
        'required',
        title='Required',
        description=(
            "Checked if the field is required; the user has to fill in some "
            "data."),
        default=1)
    unicode = fields.CheckBoxField(
        'unicode',
        title='Unicode',
        description=(
            "Checked if the field delivers a unicode string instead of an "
            "8-bit string."),
        default=0)

    required_not_found = _('Input is required but no input given.')
    unknown_selection = _('You selected an item that was not in the list.')

    def check(self, field, value, failover=False):
        if not isinstance(value, (list, tuple)):
            self.raise_error('not_a_list', field)

        # If we selected nothing and entry is required, give error, otherwise
        # give entry list
        if len(value) == 0:
            if not failover and field.get_value('required'):
                self.raise_error('required_not_found', field)
            return []

        convert = field.get_value('unicode')
        encoding = field.get_form_encoding()

        # Convert everything to unicode if necessary
        value = map(lambda v: ensure_unicode(v, convert, encoding), value)

        if not failover:
            # Possible values
            items = set()
            for item in field.get_value('items'):
                if isinstance(item, (tuple, list)):
                    _, candidate = item
                else:
                    candidate = item
                items.add(ensure_unicode(candidate, convert, encoding))

            if set(value).difference(items):
                # Some values are not valid items
                self.raise_error('unknown_selection', field)

        return value

    def validate(self, field, key, REQUEST):
        value = REQUEST.get(key, [])

        # Ensure to have a list
        if not isinstance(value, (list, tuple)):
            value = [value]

        return self.check(field, value, key + '_novalidate' in REQUEST)

    def serializeValue(self, field, values, producer):
        producer.startPrefixMapping(None, NS_FORMULATOR)
        for value in values:
            # XXX How should I handle integer types here?
            producer.startElement('value')
            producer.characters(value)
            producer.endElement('value')
        producer.endPrefixMapping(None)
示例#11
0
class DateTimeWidget(Widget):
    property_names = Widget.property_names +\
                     ['default_now', 'date_separator', 'time_separator',
                      'input_style', 'input_order',
                      'date_only', 'hide_day', 'ampm_time_style', 'calendar_picker', 'calendar_start']

    default = fields.DateTimeField('default',
                                   title="Default",
                                   description=("The default datetime."),
                                   default=None,
                                   display_style="text",
                                   display_order="ymd",
                                   input_style="text",
                                   required=0)

    default_now = fields.CheckBoxField(
        'default_now',
        title="Default to now",
        description=(
            "Default date and time will be the date and time at showing of "
            "the form (if the default is left empty)."),
        default=0)

    date_separator = fields.StringField(
        'date_separator',
        title='Date separator',
        description=("Separator to appear between year, month, day."),
        default="/",
        required=0,
        display_width=2,
        display_maxwith=2,
        max_length=2)

    time_separator = fields.StringField(
        'time_separator',
        title='Time separator',
        description=("Separator to appear between hour and minutes."),
        default=":",
        required=0,
        display_width=2,
        display_maxwith=2,
        max_length=2)

    input_style = fields.ListField(
        'input_style',
        title="Input style",
        description=("The type of input used. 'text' will show the date part "
                     "as text, while 'list' will use dropdown lists instead."),
        default="text",
        items=[("text", "text"), ("list", "list")],
        size=1)

    input_order = fields.ListField(
        'input_order',
        title="Input order",
        description=("The order in which date input should take place. Either "
                     "year/month/day, day/month/year or month/day/year."),
        default="ymd",
        items=[("year/month/day", "ymd"), ("day/month/year", "dmy"),
               ("month/day/year", "mdy")],
        required=1,
        size=1)

    date_only = fields.CheckBoxField(
        'date_only',
        title="Display date only",
        description=("Display the date only, not the time."),
        default=0)

    hide_day = fields.CheckBoxField('hide_day',
                                    title="Hide day field",
                                    description=("Hide the day field."),
                                    default=0)

    ampm_time_style = fields.CheckBoxField(
        'ampm_time_style',
        title="AM/PM time style",
        description=("Display time in am/pm format."),
        default=0)
    calendar_picker = fields.CheckBoxField(
        'calendar_picker',
        title="Enable calendar picker",
        description=
        ("Displays a floating calendar to select the date.  "
         "The js calendar is located here: http://www.dynarch.com/projects/calendar/old/"
         ),
        default=0)

    calendar_start = fields.ListField(
        'calendar_start',
        title="Starting day of week",
        description=(
            "The starting day of the week for the floating calendar."),
        default="Sunday",
        items=[
            ("Sunday", "0"),
            ("Monday", "1"),
            ("Tuesday", "2"),
            ("Wednesday", "3"),
            ("Thursday", "4"),
            ("Friday", "5"),
            ("Saturday", "6"),
        ],
        required=0,
        size=1)

    has_html_id = False

    # FIXME: do we want to handle 'extra'?

    def render(self, field, key, value, REQUEST):
        use_ampm = field.get_value('ampm_time_style')
        hide_day = field.get_value('hide_day')
        calendar_picker = field.get_value('calendar_picker')
        start_day = field.get_value('calendar_start')
        # FIXME: backwards compatibility hack:
        if not hasattr(field, 'sub_form'):
            from StandardFields import create_datetime_text_sub_form
            field.sub_form = create_datetime_text_sub_form()

        if value is None and field.get_value('default_now'):
            value = DateTime()

        # Allow subfields to get their values even when default_now is set.
        if REQUEST is not None and \
                   REQUEST.form.has_key(field.generate_subfield_key('year')):
            value = None

        if value is None:
            year = None
            month = None
            day = None
            hour = None
            minute = None
            ampm = None
        else:
            if not isinstance(value, DateTime):
                value = DateTime(value)
            year = "%04d" % value.year()
            month = "%02d" % value.month()
            day = "%02d" % value.day()
            if use_ampm:
                hour = "%02d" % value.h_12()
            else:
                hour = "%02d" % value.hour()
            minute = "%02d" % value.minute()
            ampm = value.ampm()

        input_order = field.get_value('input_order')
        if input_order == 'ymd':
            order = [('year', year), ('month', month), ('day', day)]
        elif input_order == 'dmy':
            order = [('day', day), ('month', month), ('year', year)]
        elif input_order == 'mdy':
            order = [('month', month), ('day', day), ('year', year)]
        result = []
        hidden_day_part = ""
        for sub_field_name, sub_field_value in order:
            if hide_day and (sub_field_name == 'day'):
                dayvalue = sub_field_value
                if dayvalue is None:
                    dayvalue = "01"
                sub_key = field.generate_subfield_key(sub_field_name)
                sub_field = field.sub_form.get_field(sub_field_name)
                hidden_day_part = sub_field.widget.\
                                  render_hidden(sub_field, sub_key,
                                                dayvalue, REQUEST)
            else:
                result.append(
                    field.render_sub_field(sub_field_name, sub_field_value,
                                           REQUEST))
        date_result = string.join(result, field.get_value('date_separator'))

        day_id = field.sub_form.get_field('day').generate_field_html_id(
            "subfield_" + field.id + "_day")
        month_id = field.sub_form.get_field('month').generate_field_html_id(
            "subfield_" + field.id + "_month")
        year_id = field.sub_form.get_field('year').generate_field_html_id(
            "subfield_" + field.id + "_year")

        select_day = ''
        if hidden_day_part:
            date_result += hidden_day_part
        else:
            #get the proper html id
            select_day = 'document.getElementById("' + day_id + '").value = RegExp.$3;'
        calendar_popup = ''
        html_id = field.generate_field_html_id(key)
        if calendar_picker:
            calendar_popup = ' ' + render_element(
                'button',
                css_class='kupu-button kupu-link-reference calendar-button',
                style='padding: 0px 0px 0px 0px',
                id=html_id + '_calendar',
                title='set date',
                contents=' ') + """<script type="text/javascript">
setTimeout(function(){Calendar.setup({inputField : '%s_hiddeninput',
                ifFormat : '%%Y/%%m/%%d %%%s:%%M %%P',
                showsTime : '%s',
                button : '%s_calendar',
                weekNumbers: false,
                timeFormat: '%s',
                date: (new Date()).setHours(0,0,0,0),
                firstDay: '%s'})},100);</script>""" % (
                    html_id,
                    use_ampm and 'I' or 'H',
                    field.get_value('date_only') and 'false' or 'true',
                    html_id,
                    use_ampm and '12' or '24',
                    start_day,
                )
        if not field.get_value('date_only'):
            time_result = (field.render_sub_field('hour', hour, REQUEST) +
                           field.get_value('time_separator') +
                           field.render_sub_field('minute', minute, REQUEST))

            hour_id = field.sub_form.get_field('hour').generate_field_html_id(
                "subfield_" + field.id + "_hour")
            minute_id = field.sub_form.get_field(
                'minute').generate_field_html_id("subfield_" + field.id +
                                                 "_minute")
            ampm_id = field.sub_form.get_field('ampm').generate_field_html_id(
                "subfield_" + field.id + "_ampm")
            if use_ampm:
                time_result += '&nbsp;' + field.render_sub_field(
                    'ampm', ampm, REQUEST)
            calendar_popup += calendar_picker and render_element(
                'input',
                type='hidden',
                id=html_id + '_hiddeninput',
                onchange=
                'var pattern = /(\d{4})\/(\d{2})\/(\d{2}) (\d{2}):(\d{2}) (am|pm)/; if (pattern.exec(this.value)) { document.getElementById("'
                + year_id + '").value = RegExp.$1; document.getElementById("' +
                month_id + '").value = RegExp.$2; ' + select_day +
                ' document.getElementById("' + hour_id +
                '").value = RegExp.$4; document.getElementById("' + minute_id +
                '").value = RegExp.$5; ' +
                str(use_ampm and 'document.getElementById("' + ampm_id +
                    '").value = RegExp.$6;' or '') + ' }') or ''
            return date_result + '&nbsp;&nbsp;&nbsp;' + time_result + calendar_popup
        else:
            calendar_popup += calendar_picker and render_element(
                'input',
                type='hidden',
                id=html_id + '_hiddeninput',
                onchange=
                'var pattern = /(\d{4})\/(\d{2})\/(\d{2}) (\d{2}):(\d{2}) (am|pm)/; if (pattern.exec(this.value)) { document.getElementById("'
                + year_id + '").value = RegExp.$1; document.getElementById("' +
                month_id + '").value = RegExp.$2; ' + select_day + ' }') or ''
            return date_result + calendar_popup

    def render_hidden(self, field, key, value, REQUEST):
        result = []
        if value is None and field.get_value('default_now'):
            value = DateTime()
        sub_values = {}
        subfields = ['year', 'month', 'day']
        if value is not None:
            if not isinstance(value, DateTime):
                value = DateTime(value)
            sub_values['year'] = '%04d' % value.year()
            sub_values['month'] = "%02d" % value.month()
            sub_values['day'] = "%02d" % value.day()
            if not field.get_value('date_only'):
                use_ampm = field.get_value('ampm_time_style')
                subfields.extend(['hour', 'minute'])
                if use_ampm: subfields.append('ampm')
                if value is not None:
                    if use_ampm:
                        sub_values['hour'] = "%02d" % value.h_12()
                        sub_values['ampm'] = value.ampm()
                    else:
                        sub_values['hour'] = "%02d" % value.hour()
                    sub_values['minute'] = "%02d" % value.minute()
        for subfield in subfields:
            # XXX it would be nicer to pass the hidden value somewhere
            # to the subfields, but ...
            sub_key = field.generate_subfield_key(subfield)
            sub_field = field.sub_form.get_field(subfield)
            result.append(
                sub_field.widget.render_hidden(sub_field, sub_key,
                                               sub_values.get(subfield),
                                               REQUEST))
        return ''.join(result)

    def render_view(self, field, value):
        if value is None:
            return ''

        use_ampm = field.get_value('ampm_time_style')

        if not isinstance(value, DateTime):
            value = DateTime(value)
        year = "%04d" % value.year()
        month = "%02d" % value.month()
        day = "%02d" % value.day()
        if use_ampm:
            hour = "%02d" % value.h_12()
        else:
            hour = "%02d" % value.hour()
        minute = "%02d" % value.minute()
        ampm = value.ampm()

        order = field.get_value('input_order')
        if order == 'ymd':
            output = [year, month, day]
        elif order == 'dmy':
            output = [day, month, year]
        elif order == 'mdy':
            output = [month, day, year]
        date_result = string.join(output, field.get_value('date_separator'))

        if not field.get_value('date_only'):
            time_result = hour + field.get_value('time_separator') + minute
            if use_ampm:
                time_result += '&nbsp;' + ampm
            return date_result + '&nbsp;&nbsp;&nbsp;' + time_result
        else:
            return date_result
示例#12
0
class ImageFieldWidget(Widget.TextWidget):
    """ImageField widget.

    Renders an HTML <img> element where the src is the 'default' field value.
    The 'description' field value is used as 'alt' attribute.
    The image size is calculated using 'image_display'.
    """
    property_names = Widget.TextWidget.property_names + \
      ['image_display', 'image_format','image_quality', 'image_pre_converted_only']

    image_display = fields.StringField(
        'image_display',
        title='Image Display',
        description=
        ("The display size. See erp5.component.document.Image.default_displays_id_list "
         "for possible values. This is only used with ERP5 Images."),
        default='thumbnail',
        required=0)

    image_format = fields.StringField(
        'image_format',
        title='Image Format',
        description=("The format in which the image should be converted to. "
                     "This is only used with ERP5 Images."),
        default='',
        required=0)

    image_quality = fields.IntegerField(
        'image_quality',
        title='Image Quality',
        description=("The quality used when converting the image. "
                     "This is only used with ERP5 Images."),
        default=75,
        required=0)

    image_pre_converted_only = fields.CheckBoxField(
        'image_pre_converted_only',
        title='Image Pre Converted Only',
        description=(
            "Return image only if it is already pre converted in cache. "
            "This is only used with ERP5 Images."),
        default=False,
        required=0)

    def render(self, field, key, value, REQUEST, render_prefix=None):
        """Render image field as a link to the image
        """
        return self.render_view(field, value, REQUEST=REQUEST)

    def render_view(self, field, value, REQUEST=None, render_prefix=None):
        """Render image field as a link to the image
        """
        # Url is already defined in value
        if value is None:
            return ''
        image = value
        alt = field.get_value('description') or \
              field.get_value('title')
        css_class = field.get_value('css_class')
        extra = field.get_value('extra')
        options = {}
        options['display'] = field.get_value('image_display')
        options['format'] = field.get_value('image_format')
        options['quality'] = field.get_value('image_quality')
        pre_converted_only = field.get_value('image_pre_converted_only')
        if pre_converted_only:
            # only add if it's True as conversion machine assume that if it is missing
            # then conversion should happen "on the fly"
            options['pre_converted_only'] = pre_converted_only
        parameters = '&'.join(['%s=%s' % (k, v) for k, v in options.items() \
                               if v])
        if parameters:
            image = '%s?%s' % (image, parameters)
        return Widget.render_element(
            "img",
            alt=alt,
            src=image,
            css_class=css_class,
            extra=extra,
        )

    def render_odg_view(self, field, value, as_string, ooo_builder, REQUEST,
                        render_prefix, attr_dict, local_name):
        """
        return an image xml node rendered in odg format
        if as_string is True (default) the returned value is a string (xml
        reprensation of the node), if it's False, the value returned is the node
        object.
        attr_dict can be used for additional parameters (like style).
      """
        if attr_dict is None:
            attr_dict = {}
        draw_frame_node = None
        if value in ('', None):
            return None
        path = '/'.join(REQUEST.physicalPathFromURL(value))
        path = path.encode()
        image_object = field.getPortalObject().restrictedTraverse(path)
        display = field.get_value('image_display')
        format = field.get_value('image_format')
        quality = field.get_value('image_quality')
        image_parameter_dict = {'format': format}
        if display:
            image_parameter_dict['display'] = display
        if quality:
            image_parameter_dict['quality'] = quality
        # convert the image using fields parameters. In this way, if an image
        # is displayed in the form as a thumbnail, it will be added in the odg
        # document as thumbnail size/quality
        content_type, image_data = image_object.convert(**image_parameter_dict)
        image = OFSImage('', '', image_data)
        width = image.width
        height = image.height
        if image_data is None:
            return draw_frame_node

        # Big images are cut into smaller chunks, so it's required to cast to
        # str. See OFS/Image -> _read_data method for more information
        image_data = str(image_data)

        format = content_type.split('/')[-1]
        # add the image to the odg document
        picture_path = ooo_builder.addImage(image=image_data,
                                            format=format,
                                            content_type=content_type)

        # create the xml nodes related to the image
        draw_frame_tag_name = '{%s}%s' % (DRAW_URI, 'frame')
        draw_frame_node = Element(draw_frame_tag_name, nsmap=NSMAP)
        draw_frame_node.attrib.update(
            attr_dict.get(draw_frame_tag_name, {}).pop(0))

        # set the size of the image
        if display is not None:
            # if the image width and height are not on defined, use current
            # width and height
            if (image_object.getWidth(), image_object.getHeight()) not in \
              ((-1, -1), (0,0)):
                width, height = image_object._getAspectRatioSize(width, height)
                if draw_frame_node.attrib.get('{%s}width' % SVG_URI) and \
                  draw_frame_node.attrib.get('{%s}height' % SVG_URI):
                    # if a size already exist from attr_dict, try to resize the image to
                    # fit this size (image should not be biger than size from attr_dict)
                    # devide the value by 20 to have cm instead of px
                    width, height = self._getPictureSize(
                        width / 20.,
                        height / 20.,
                        target_width=draw_frame_node.attrib.get(
                            '{%s}width' % SVG_URI, ''),
                        target_height=draw_frame_node.attrib.get(
                            '{%s}height' % SVG_URI, ''))

                draw_frame_node.set('{%s}width' % SVG_URI, str(width))
                draw_frame_node.set('{%s}height' % SVG_URI, str(height))

        image_tag_name = '{%s}%s' % (DRAW_URI, 'image')
        image_node = Element(image_tag_name, nsmap=NSMAP)
        image_node.attrib.update(attr_dict.get(image_tag_name, []).pop())
        image_node.set('{%s}href' % XLINK_URI, picture_path)

        draw_frame_node.append(image_node)
        if as_string:
            return etree.tostring(draw_frame_node)
        return draw_frame_node

    def _getPictureSize(self, picture_width, picture_height, target_width,
                        target_height):
        # if not match causes exception
        width_tuple = re.match("(\d[\d\.]*)(.*)", target_width).groups()
        height_tuple = re.match("(\d[\d\.]*)(.*)", target_height).groups()
        unit = width_tuple[1]
        w = float(width_tuple[0])
        h = float(height_tuple[0])
        aspect_ratio = 1
        try:  # try image properties
            aspect_ratio = picture_width / picture_height
        except (TypeError, ZeroDivisionError):
            try:  # try Image Document API
                height = picture_height
                if height:
                    aspect_ratio = picture_width / height
            except AttributeError:  # fallback to Photo API
                height = float(picture_height)
                if height:
                    aspect_ratio = picture_width / height
        resize_w = h * aspect_ratio
        resize_h = w / aspect_ratio
        if resize_w < w:
            w = resize_w
        elif resize_h < h:
            h = resize_h
        return (str(w) + unit, str(h) + unit)
示例#13
0
class VideoWidget(Widget.TextWidget):
    """
  A widget that displays a Video HTML element.
  This widget is intended to be used in
  conjunction with WebSite.
  """
    property_names = Widget.TextWidget.property_names + \
            ['video_controls', 'video_error_message', 'video_loop', \
                'video_width', 'video_height', 'video_preload', \
                'video_autoplay', 'js_enabled', 'video_player']

    video_controls = fields.CheckBoxField(
        'video_controls',
        title='Video Controls',
        description=("Controls to be used in Video Player."),
        default=1,
        required=0)

    video_error_message = fields.StringField(
        'video_error_message',
        title='Video Error Message',
        description=("Error message to be showed when \
          user's browser does not support the video tag."),
        default='Your browser does not support video tag.',
        required=0)

    video_loop = fields.CheckBoxField(
        'video_loop',
        title='Video Loop',
        description=("Specifies that the video file \
          will start over again, every time it is finished."),
        default=0,
        required=0)

    video_width = fields.IntegerField(
        'video_width',
        title='Video Width',
        description=("The width to be used when playing the video."),
        default=160,
        required=0)

    video_height = fields.IntegerField(
        'video_height',
        title='Video Height',
        description=("The height to be used when playing the video."),
        default=85,
        required=0)

    video_preload = fields.CheckBoxField(
        'video_preload',
        title='Video Preload',
        description=("Configure that you would like to \
      start downloading the video file as soon as possible."),
        default=1,
        required=0)

    video_autoplay = fields.CheckBoxField(
        'video_autoplay',
        title='Video Autoplay',
        description=("Configure that you would like to \
      start downloading and playing the video file as soon as possible."),
        default=0,
        required=0)

    js_enabled = fields.CheckBoxField(
        'js_enabled',
        title='Enable on the fly video player change (based on java script)',
        description=
        'Define if javascript is enabled or not on the current Video',
        default=1,
        required=0)

    video_player = fields.ListField(
        'video_player',
        title='Video Player',
        description=("The video player to be used to show video."),
        default="html5_video",
        required=1,
        size=1,
        items=[
            ('HTML5 Video', 'html5_video'),
            ('Flowplayer', 'flowplayer'),
        ])

    def render(self, field, key, value, REQUEST, render_prefix=None):
        return self.render_view(field, value, REQUEST, render_prefix)

    def render_view(self, field, value, REQUEST=None, render_prefix=None):
        if value is None:
            return ''
        video_player = field.get_value('video_player')
        if video_player == 'html5_video':
            extra_kw = {}
            if field.get_value('video_autoplay'):
                extra_kw['autoplay'] = 'autoplay'
            if field.get_value('video_controls'):
                extra_kw['controls'] = 'controls'
            if field.get_value('video_loop'):
                extra_kw['loop'] = 'loop'
            if field.get_value('video_preload'):
                extra_kw['preload'] = 'preload'
            return Widget.render_element(
                "video",
                src=value,
                extra=field.get_value('extra'),
                width=field.get_value('video_width'),
                height=field.get_value('video_height'),
                contents=field.get_value('video_error_message'),
                **extra_kw)
        elif video_player == 'flowplayer':
            a_element = Widget.render_element("a",
                              href="%s" % value,
                              style="display:block;width:%spx;height:%spx;" % \
                                              (field.get_value('video_width'),
                                               field.get_value('video_height'),),
                              id="player")

            script_element = """<script language="JavaScript">
                             flowplayer("player", "%s/flowplayer.swf");
                         </script>""" % self.getContext(
                field, REQUEST).getPortalObject().portal_url()
            return ' '.join([a_element, script_element])

    def get_javascript_list(self, field, REQUEST=None):
        """
    Returns list of javascript needed by the widget
    """
        if field.get_value('js_enabled'):
            video_player = field.get_value('video_player')
            context = self.getContext(field, REQUEST)
            if video_player == 'html5_video':
                # XXX Instead of harcoding library name
                # it should be better to call a python script, as
                # it is done on type base method.
                return ['%s/html5media.min.js' % context.portal_url()]
            elif video_player == 'flowplayer':
                return ['%s/flowplayer.min.js' % context.portal_url()]
        else:
            return []

    def getContext(self, field, REQUEST):
        """Return the context of rendering this Field.
    """
        value = REQUEST.get('here')
        if value is None:
            value = self.getForm(field).aq_parent
        return value

    def getForm(self, field):
        """Return the form which contains the Field.
    """
        return field.aq_parent
示例#14
0
文件: Form.py 项目: poses/erp5
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
示例#15
0
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)
示例#16
0
class OOoChartWidget(Widget.Widget):
  """
  This class is capabale of producing ODF
  charts based on data obtained through a
  listbox.
  Some properties are useless
  http://books.evc-cit.info/odbook/ch08.html#chart-plot-area-example
    - mean-value
    - error-margin
    - error-upper-limit
    - error-lower-limit
    - error-category
    - error-percentage
    - chart-japanese-candle-stick and stock-with-volume,chart:stock-updown-bars. These attributs are used with a chart:stock
  """

  property_names = list(Widget.Widget.property_names)

  # XXX The description says it's not used
  #     but removing 'default' breaks ODT/ODS rendering ...
  default = fields.StringField(
                              'default',
                              title='Default',
                              description=("A default value (not used)."),
                              default="",
                              required=0)

  listbox_form_id = fields.StringField(
                              'listbox_form_id',
                              title='ListBox Form ID',
                              description=("ID of the master form."),
                              default="",
                              required=0)
  property_names.append('listbox_form_id')

  listbox_id = fields.StringField(
                              'listbox_id',
                              title='ListBox ID',
                              description=("ID of the listbox in the master form."),
                              default="",
                              required=0)
  property_names.append('listbox_id')

  image_display = fields.ListField('image_display',
                              title='Image Display',
                              description=("Render size of this chart in HTML mode."),
                              default='medium',
                              items=[('thumbnail','thumbnail'),
                                    ('xsmall', 'xsmall'),
                                    ('small', 'small'),
                                    ('medium', 'medium'),
                                    ('large', 'large'),
                                    ('xlarge', 'xlarge'),
                                    ],
                              size=1)
  property_names.append('image_display')

  image_format = fields.StringField('image_format',
                              title='Image Format',
                              description=(
      "The format in which the chart should be converted to."),
                              default='png',
                              required=0)
  property_names.append('image_format')

  ooo_template = fields.StringField('ooo_template',
                              title='OOo Template',
                              description=('The ID of a OOo Page Template'
                                            'to render the ListBox'),
                              default='ERP5Site_viewChart',
                              required=0)
  property_names.append('ooo_template')


  chart_type = fields.ListField('chart_type',
                              title='Chart Type',
                              description=('Type of the Chart'),
                              default='chart:bar',
                              items=[('bar', 'chart:bar'),
                                    ('circle', 'chart:circle'),
                                    ('line', 'chart:line'),
                                    ('scatter', 'chart:scatter'),
                                    ('area', 'chart:area'),
                                    ],
                              size=0)
  property_names.append('chart_type')


  colour_column_list = fields.ListTextAreaField('colour_column_list',
                              title="Data Color",
                              description=(
    "A list of colors for each data associated to a column."),
                              default=[],
                              required=0)
  property_names.append('colour_column_list')

  # vertical ="true"
  chart_position = fields.ListField('chart_position',
                              title='Bar Position',
                              description=(
                    'Render the bar in horizontal position or vertical position'),
                              default='false',
                              items=[('horizontal', 'true'),
                                    ('vertical', 'false'),
                                    ],
                              size=0)
  property_names.append('chart_position')

  #legend of the chart or not
  chart_legend = fields.CheckBoxField('chart_legend',
                              title='Chart Legend',
                              description=('Show Chart Legend or no'),
                              default=1,
                              required=0)
  property_names.append('chart_legend')


  position_legend = fields.ListField('position_legend',
                              title='Legend Position',
                              description=(
                              'Legend Position according to the graph'),
                              default='end',
                              items=[('bottom', 'bottom'),
                                    ('end', 'end'),
                                    ('start', 'start'),
                                    ('top', 'top'),
                                    ],
                              size=1)
  property_names.append('position_legend')

  #legend of the chart or not
  chart_title_or_no = fields.CheckBoxField('chart_title_or_no',
                              title='Chart Title ',
                              description=('Show Title on Graph or no '),
                              default=1,
                              required=0)
  property_names.append('chart_title_or_no')

  # Axis
  x_axis_property_list = fields.ListTextAreaField('x_axis_property_list',
                              title="X-Axis Properties",
                              description="Examples of recognized properties:"
                                          " 'chart:visible',"
                                          " 'chart:display-label',"
                                          " 'chart:label-arrangement',"
                                          " 'chart:tick-marks-major-inner',"
                                          " 'chart:reverse-direction',"
                                          " 'chart:logarithmic',"
                                          " 'chart:text-overlap',"
                                          " 'chart:origin',"
                                          " 'text:line-break',"
                                          " 'style:rotation-angle'...",
                              default=(),
                              required=0)
  property_names.append('x_axis_property_list')

  y_axis_property_list = fields.ListTextAreaField('y_axis_property_list',
                              title="Y-Axis Properties",
                              default=(),
                              required=0)
  property_names.append('y_axis_property_list')

  #grid or not
  grid_graph = fields.CheckBoxField('grid_graph',
                              title='Chart Grid ',
                              description=('Show Grid or no'),
                              default=1,
                              required=0)
  property_names.append('grid_graph')


  grid_size = fields.ListField('grid_size',
                              title='Grid Size',
                              description=(
                              'Render a big grid size or a small grid size'),
                              default='major',
                              items=[('major', 'major'),
                                    ('minor', 'minor'),
                                    ],
                              size=0)
  property_names.append('grid_size')

  user_data_title = fields.StringField('user_data_title',
                              title="Overide Labelled Column ID",
                              description=(
    "Column Id choose by user to define the label."),
                              required=0)
  property_names.append('user_data_title')

  user_column_id_list = fields.ListTextAreaField('user_column_id_list',
                              title="Overide Column Ids",
                              description=(
    "A list of column Ids choose by user to draw the graph."),
                              default=[],
                              required=0)
  property_names.append('user_column_id_list')


  chart_stacked = fields.CheckBoxField('chart_stacked',
                              title='Stacked Data',
                              description=('stacked data or not'),
                              default=0,
                              required=0)
  property_names.append('chart_stacked')

  #connect-bars="false"
  connect_bars = fields.CheckBoxField('connect_bars',
                              title='Connect Bars',
                              description=(''),
                              default=0,
                              required=0)
  property_names.append('connect_bars')


  chart_three_dimensional = fields.CheckBoxField('chart_three_dimensional',
                              title='3D',
                              description=(
                      'Render the chart in three dimensions rather in flat mode'),
                              default=0,
                              required=0)
  property_names.append('chart_three_dimensional')

  #deep="false"
  deep = fields.CheckBoxField('deep',
                              title='Deep',
                              description=('Deep'),
                              default=0,
                              required=0)
  property_names.append('deep')

  # sector_pie_offset Default:0
  sector_pie_offset = fields.IntegerField('sector_pie_offset',
                              title='Sector Pie Offset',
                              description=(''),
                              default=0,
                              required=0)
  property_names.append('sector_pie_offset')


  #interpolation="none", cubic-spline, b-spline
  interpolation = fields.ListField('interpolation',
                              title='Interpolation',
                              description=(''),
                              default='none',
                              items=[('none', 'none'),
                                    ('cubic-spline', 'cubic-spline'),
                                    ('b-spline', 'b-spline')],
                              size=1)
  property_names.append('interpolation')

  #symbol-type="none", automatic
  symbol_type = fields.ListField('symbol_type',
                              title='Symbol Type',
                              description=(''),
                              default='none',
                              items=[('none', 'none'),
                                    ('automatic', 'automatic'),],
                              size=1)
  property_names.append('symbol_type')

  #lines-used="0"
  lines_used = fields.ListField('lines_used',
                              title='Lines Used',
                              description=(''),
                              default='0',
                              items=[('0', '0'),
                                      ('1', '1')],
                              size=1)
  property_names.append('lines_used')


  #series-source=columns or rows
  series_source = fields.ListField('series_source',
                              title='Series Source',
                              description=(''),
                              default='columns',
                              items=[('columns', 'columns'),
                                    ('rows', 'rows'),],
                              size=1)
  property_names.append('series_source')

  #regression-type="none" linear logarithmic exponential power
  regression_type = fields.ListField('regression_type',
                              title='Regression Type',
                              description=(''),
                              default='none',
                              items=[('none', 'none'),
                                    ('linear', 'linear'),
                                    ('logarithmic', 'logarithmic'),
                                    ('exponential', 'exponential'),
                                    ('power', 'power')],
                              size=1)
  property_names.append('regression_type')

  #data-label-number="none" value percentage
  data_label_number = fields.ListField('data_label_number',
                              title='Data Label Number',
                              description=(''),
                              default='none',
                              items=[('none', 'none'),
                                    ('value', 'value'),
                                    ('percentage', 'percentage')],
                              size=1)
  property_names.append('data_label_number')

  #data-label-text="false"
  data_label_text = fields.CheckBoxField('data_label_text',
                              title='Data Label Text',
                              description=(''),
                              default=0,
                              required=0)
  property_names.append('data_label_text')

  #data-label-symbol="false"
  data_label_symbol = fields.CheckBoxField('data_label_symbol',
                              title='Data Label Symbol',
                              description=(''),
                              default=0,
                              required=0)
  property_names.append('data_label_symbol')


  def getArgumentDict(self, field, REQUEST):
    """ Build argument Dict """
    def stringBoolean(value):
      return str(bool(value)).lower()
    form = field.aq_parent
    listbox_form_id = field.get_value('listbox_form_id')
    if listbox_form_id in ('', None):
      listbox_form_id = form.getId()
    listbox_id = field.get_value('listbox_id')
    if listbox_id in ('', None):
      listbox_id = 'listbox'
    render_prefix = REQUEST.get('render_prefix')
    extra_argument_dict = dict(
      render_prefix = render_prefix,
      chart_form_id = listbox_form_id,
      chart_field_id = listbox_id,
      chart_title = field.get_value('title'),
      chart_type = field.get_value('chart_type'),
      colour_column_list = field.get_value('colour_column_list'),
      user_column_id_list = field.get_value('user_column_id_list'),
      user_data_title= field.get_value('user_data_title'),
      chart_position = field.get_value('chart_position'),
      chart_legend = stringBoolean(field.get_value('chart_legend')),
      chart_title_or_no = stringBoolean(field.get_value('chart_title_or_no')),
      x_axis_property_dict = dict(field.get_value('x_axis_property_list')),
      y_axis_property_dict = dict(field.get_value('y_axis_property_list')),
      grid_graph = stringBoolean(field.get_value('grid_graph')),
      grid_size=field.get_value('grid_size'),
      chart_three_dimensional = stringBoolean(field.get_value('chart_three_dimensional')),
      deep = stringBoolean(field.get_value('deep')),
      chart_stacked = stringBoolean(field.get_value('chart_stacked')),
      sector_pie_offset = field.get_value('sector_pie_offset'),
      interpolation = field.get_value('interpolation'),
      symbol_type = field.get_value('symbol_type'),
      lines_used = field.get_value('lines_used'),
      connect_bars = stringBoolean(field.get_value('connect_bars')),
      series_source = field.get_value('series_source'),
      regression_type = field.get_value('regression_type'),
      data_label_number = field.get_value('data_label_number'),
      data_label_text = stringBoolean(field.get_value('data_label_text')),
      data_label_symbol = stringBoolean(field.get_value('data_label_symbol')),
      position_legend=field.get_value('position_legend'),
    )

    for k, v in extra_argument_dict.items():
      if REQUEST.get(k) is None:
        REQUEST.form[k] = v
    return extra_argument_dict


  def render_view(self, field, value, REQUEST=None, key=None, render_format='html', render_prefix=None):
    """
      Render a Chart in read-only.
    """
    if REQUEST is None: REQUEST=get_request()
    return self.render(field, key, value, REQUEST, render_format=render_format,
                       render_prefix=render_prefix)


  def render_odf(self, field, key, value, REQUEST, render_format='ooo',
                 render_prefix=None):
    """
      Render a Chart for ODT Style.
    """
    if REQUEST is None: REQUEST=get_request()
    form = field.aq_parent
    here = getattr(form, 'aq_parent', REQUEST)
    REQUEST.set('render_prefix', render_prefix)
    #needed to update REQUEST
    argument_dict = self.getArgumentDict(field, REQUEST)
    from xml.marshal.generic import dumps
    dump_args = dumps(argument_dict)
    #remove xml declaration (first processing node)
    dump_args = dump_args[dump_args.index('?>')+2:]
    content = '''<office:include path="%s/ERP5Site_buildChart"
                                 xlink:type="simple" xlink:actuate="onLoad"
                                 xlink:show="embed">%s</office:include>
                                 ''' % (here.getPath(), dump_args)
    return content


  def render(self, field, key, value, REQUEST, render_format='html', render_prefix=None):

    """
      Render a chart.

      render_format   -- If the format is set to html, render the chart
                         as a URL to ourselves with a png render_format

                         If the format is set to 'raw', render the chart
                         as raw XML.

                         If the format is set to an image type (ex. png)
                         render the chart using that format.
    """
    title = field.get_value('title')
    alt = field.get_value('description') or title
    form = field.aq_parent
    if not render_prefix:
      render_prefix = REQUEST.get('render_prefix')
    # Find the applicable context
    here = getattr(form, 'aq_parent', REQUEST)
    # Update the render format based on REQUEST parameters
    render_format = getattr(REQUEST, 'render_format', render_format)
    if render_format == 'html':
      css_class = field.get_value('css_class')
      format = field.get_value('image_format') or 'png'
      query_dict = dict(REQUEST.form.items())
      query_dict.update(render_format=format != 'raw' and format or '',
                        render_prefix=render_prefix,
                        display=field.get_value('image_display'))
      # XXX make_query does not handle tuples properly so listbox should be
      #     not editable (otherwise, REQUEST.form may contain listbox=()).
      url = '%s/%s/%s?%s' % (here.absolute_url(), form.getId(), field.getId(),
                             make_query(query_dict))
      if format in VALID_IMAGE_FORMAT_LIST:
        return '''<div class="OOoChartContent">
          <img class="%s" src="%s" title="%s" alt="%s"/">
          </div>''' % (css_class,
                       url,
                       title,
                       alt)
      elif format == 'raw':
        UrlIconOOo = '%s/misc_/ERP5OOo/OOo.png' % REQUEST['BASEPATH1']
        return '''<div class="OOoChartContent">
          <a href="%s"><img src="%s" alt="OOo"/></a>
          </div>''' % (url,
                       UrlIconOOo)
      elif format == 'pdf':
        UrlIconPdf = '%s/misc_/ERP5Form/PDF.png' % REQUEST['BASEPATH1']
        return '''<div class="OOoChartContent">
          <a href="%s"><img src="%s" alt="PDF" /></a>
          </div>''' % (url,
                       UrlIconPdf)
      else:
        raise NotImplementedError, 'Format: %s not handled' % format

    extra_context = self.getArgumentDict(field, REQUEST)

    method_id = field.get_value('ooo_template')

    # Find the page template
    ooo_template = getattr(here, method_id)

    # Render the chart
    return ooo_template(format=render_format, **extra_context)
示例#17
0
文件: GadgetField.py 项目: poses/erp5
class GadgetWidget(Widget.TextWidget):
    """
  A widget that displays a renderjs gadget 
  """
    property_names = Widget.TextWidget.property_names + \
         ['gadget_html', 'gadget_cached', 'gadget_cache_id', 'gadget_property',
          'gadget_connection', 'gadget_id']

    gadget_html = fields.StringField(
        'gadget_html',
        title='Gadget Html',
        description=("The id of the html page containing the \
                                      gadget"),
        default='',
        required=0)

    gadget_id = fields.StringField('gadget_id',
                                   title='Gadget Id',
                                   description=("The id of the gadget"),
                                   default='',
                                   required=0)

    gadget_cache_id = fields.StringField(
        'gadget_cache_id',
        title='Gadget Cache Id',
        description=("The id of the cache in localstorage"),
        default='',
        required=0)

    gadget_property = fields.StringField(
        'gadget_property',
        title='Gadget Properties',
        description=("Json Data used to initialize the gadget"),
        default='',
        required=0)

    gadget_connection = fields.StringField(
        'gadget_connection',
        title='Gadget Connections',
        description=("Json Data used to define interactions"),
        default='',
        required=0)

    gadget_cached = fields.CheckBoxField(
        'gadget_cached',
        title='Gadget Cached',
        description=("The rendering of the gadget will be \
                                       cached in localstorage."),
        default=0,
        required=0)

    def render(self, field, key, value, REQUEST, render_prefix=None):
        return self.render_view(field, value, REQUEST, render_prefix)

    def render_view(self, field, value, REQUEST=None, render_prefix=None):
        kw = {}
        gadget_mapping = {
            "gadget_cached": "data-gadget-cacheable",
            "gadget_cache_id": "data-gadget-cache-id",
            "gadget_html": "data-gadget",
            "gadget_id": "id",
            "gadget_connection": "data-gadget-connection",
            "gadget_property": "data-gadget-property"
        }
        for property_name in gadget_mapping.keys():
            property_value = field.get_value(property_name)
            if property_value or property_name == "gadget_html":
                kw[gadget_mapping[property_name]] = property_value
        return Widget.render_element("div", **kw)
示例#18
0
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
示例#19
0
class MultiRelationStringFieldWidget(Widget.LinesTextAreaWidget,
                                     Widget.TextWidget, Widget.ListWidget):
    """
  RelationStringField widget
  Works like a string field but includes one buttons
  - one search button which updates the field and sets a relation
  - creates object if not there
  """
    local_property_names = [
        'update_method',
        'jump_method',
        'allow_jump',
        'base_category',
        'portal_type',
        'allow_creation',
        'container_getter_id',
        'context_getter_id',
        'catalog_index',
        'relation_setter_id',
        'relation_form_id',
        'columns',
        'sort',
        'parameter_list',
        'list_method',
        'first_item',
        'items',
        'proxy_listbox_ids',
        'size',
        'extra_item',
    ]

    property_names = Widget.LinesTextAreaWidget.property_names + \
                     Widget.TextWidget.property_names + \
                     local_property_names

    # XXX Field to remove...
    update_method = fields.StringField(
        'update_method',
        title='Update Method',
        description=("The method to call to set the relation. Required."),
        default="Base_validateRelation",
        required=1)

    jump_method = fields.StringField(
        'jump_method',
        title='Jump Method',
        description=("The method to call to jump to the relation. Required."),
        default="Base_jumpToRelatedDocument",
        required=1)

    allow_jump = fields.CheckBoxField(
        'allow_jump',
        title='Allow Jump',
        description=("Do we allow to jump to the relation ?"),
        default=1,
        required=0)

    base_category = fields.StringField(
        'base_category',
        title='Base Category',
        description=("The method to call to set the relation. Required."),
        default="",
        required=1)

    portal_type = fields.ListTextAreaField(
        'portal_type',
        title='Portal Type',
        description=("The method to call to set the relation. Required."),
        default="",
        required=1)

    allow_creation = fields.CheckBoxField(
        'allow_creation',
        title='Allow Creation',
        description=("Do we allow to create new objects ?"),
        default=1,
        required=0)

    container_getter_id = fields.StringField(
        'container_getter_id',
        title='Container Getter Method',
        description=("The method to call to get a container object."),
        default="",
        required=0)

    context_getter_id = fields.StringField(
        'context_getter_id',
        title='Context Getter Method',
        description=("The method to call to get the context."),
        default="",
        required=0)

    catalog_index = fields.StringField(
        'catalog_index',
        title='Catalog Index',
        description=("The method to call to set the relation. Required."),
        default="",
        required=1)

    # XXX Is it a good idea to keep such a field ??
    # User can redefine setter method with a script (and so, don't use the API)
    relation_setter_id = fields.StringField(
        'relation_setter_id',
        title='Relation Update Method',
        description=("The method to invoke in order to update the relation"),
        default="",
        required=0)

    relation_form_id = fields.StringField(
        'relation_form_id',
        title='Relation Form',
        description=("Form to display relation choices"),
        default="",
        required=0)

    size = fields.IntegerField(
        'size',
        title='Size',
        description=(
            "The display size in rows of the field. If set to 1, the "
            "widget will be displayed as a drop down box by many browsers, "
            "if set to something higher, a list will be shown. Required."),
        default=1,
        required=1)

    columns = fields.ListTextAreaField(
        'columns',
        title="Columns",
        description=("A list of attributes names to display."),
        default=[],
        required=0)

    sort = fields.ListTextAreaField(
        'sort',
        title='Default Sort',
        description=('The default sort keys and order'),
        default=[],
        required=0)

    parameter_list = fields.ListTextAreaField(
        'parameter_list',
        title="Parameter List",
        description=("A list of paramters used for the portal_catalog."),
        default=[],
        required=0)

    list_method = fields.MethodField('list_method',
                                     title='List Method',
                                     description=('The method to use to list'
                                                  'objects'),
                                     default='',
                                     required=0)

    proxy_listbox_ids = fields.ListTextAreaField(
        'proxy_listbox_ids',
        title='Proxy Listbox IDs',
        description=('A list of listbox that can be used as proxy'),
        default='',
        required=0)

    # delete double in order to keep a usable ZMI...
    # XXX need to keep order !
    #property_names = dict([(i,0) for i in property_names]).keys()
    _v_dict = {}
    _v_property_name_list = []
    for property_name in property_names:
        if not _v_dict.has_key(property_name):
            _v_property_name_list.append(property_name)
            _v_dict[property_name] = 1
    property_names = _v_property_name_list

    default_widget_rendering_instance = Widget.LinesTextAreaWidgetInstance

    def _getContextValue(self, field, REQUEST):
        """Return result of evaluated method
    defined by context_getter_id or here.
    """
        context_getter_id = field.get_value('context_getter_id')
        here = REQUEST['here']
        if context_getter_id:
            return getattr(here, context_getter_id)()
        return here

    def _generateRenderValueList(self, field, key, value_list, REQUEST):
        result_list = []
        need_validation = 0
        ####################################
        # Check value
        ####################################
        if isinstance(value_list, StringType):
            # Value is a string, reformat it correctly
            value_list = value_list.split("\n")
        else:
            # We get a list
            # rather than displaying nothing, display a marker when the
            # property is not set
            # XXX Translate ?
            value_list = [(x or NO_VALUE) for x in value_list]
        # Check all relation
        for i in range(len(value_list)):
            ###################################
            # Sub field
            ###################################
            relation_field_id = field.generate_subfield_key("%s_%s" % \
                                                            (SUB_FIELD_ID, i),
                                                            key=key)
            relation_item_id = field.generate_subfield_key("%s_%s" % \
                                                           (ITEM_ID, i),
                                                           key=key)
            relation_item_list = REQUEST.get(relation_item_id, None)
            value = value_list[i]
            if (relation_item_list is not None) and \
               (value != ''):
                need_validation = 1
            # If we get a empty string, display nothing !
            if value != '':
                result_list.append(
                    (Widget.TextWidgetInstance, relation_field_id,
                     relation_item_list, value, i))
        if not need_validation:
            ###################################
            # Main field
            ###################################
            result_list = [(Widget.LinesTextAreaWidgetInstance, None, [],
                            value_list, None)]
        return result_list

    def render(self, field, key, value, REQUEST, render_prefix=None):
        """
    Render text input field.
    """
        html_string = ''
        relation_field_index = REQUEST.get('_v_relation_field_index', 0)
        render_parameter_list = self._generateRenderValueList(
            field, key, value, REQUEST)
        ####################################
        # Render subfield
        ####################################
        html_string_list = []
        for widget_instance, relation_field_id, relation_item_list, \
                                value_instance, sub_index in render_parameter_list:
            sub_html_string = widget_instance.render(field, key,
                                                     value_instance, REQUEST)

            here = self._getContextValue(field, REQUEST)
            portal = here.getPortalObject()
            autocomplete_enabled = getattr(portal.portal_skins,
                                           'erp5_autocompletion_ui', None)

            if autocomplete_enabled:
                sub_html_string += self.render_autocomplete(field, key)

            if relation_item_list is not None:
                ####################################
                # Render wheel
                ####################################
                if not autocomplete_enabled:
                    sub_html_string += self.render_wheel(
                        field,
                        value_instance,
                        REQUEST,
                        relation_index=relation_field_index,
                        sub_index=sub_index)

                if relation_item_list:
                    ####################################
                    # Render listfield
                    ####################################

                    REQUEST['relation_item_list'] = relation_item_list
                    sub_html_string += '&nbsp;%s&nbsp;' % \
                                          Widget.ListWidgetInstance.render(
                                          field, relation_field_id, None, REQUEST)
                    REQUEST['relation_item_list'] = None

            html_string_list.append(sub_html_string)
        ####################################
        # Generate html
        ####################################
        html_string = '<br/>'.join(html_string_list)
        ####################################
        # Render jump
        ####################################
        if (value == field.get_value('default')):
            # XXX Default rendering with value...
            relation_html_string = self.render_relation_link(
                field, value, REQUEST)
            if relation_html_string != '':
                html_string += '&nbsp;&nbsp;%s' % relation_html_string
        ####################################
        # Update relation field index
        ####################################
        REQUEST.set('_v_relation_field_index', relation_field_index + 1)
        return html_string

    def render_view(self, field, value, REQUEST=None, render_prefix=None):
        """
    Render read only field.
    """
        html_string = ''
        here = self._getContextValue(field, REQUEST)
        portal_url = here.getPortalObject().portal_url
        portal_url_string = portal_url()
        if (value not in ((), [], None, '')) and \
            field.get_value('allow_jump'):
            string_list = []
            base_category = field.get_value('base_category')
            portal_type = map(lambda x: x[0], field.get_value('portal_type'))
            kw = {}
            for k, v in field.get_value('parameter_list'):
                kw[k] = v
            accessor_name = 'get%sValueList' % ''.join(
                [part.capitalize() for part in base_category.split('_')])
            jump_reference_list = getattr(here, accessor_name)(
                portal_type=portal_type, filter=kw)
            if not isinstance(value, (list, tuple)):
                value = value,
            for jump_reference, display_value in zip(jump_reference_list,
                                                     value):
                string_list.append('<a class="relationfieldlink" href="%s">%s</a>' % \
                        (jump_reference.absolute_url(),
                         display_value))
            html_string = '<br />'.join(string_list)
        else:
            html_string = self.default_widget_rendering_instance.render_view(
                field, value, REQUEST=REQUEST)
            if REQUEST is None:
                REQUEST = get_request()
            relation_html_string = self.render_relation_link(
                field, value, REQUEST)
            if relation_html_string != '':
                html_string += '&nbsp;&nbsp;%s' % relation_html_string
        extra = field.get_value('extra')
        if extra not in (None, ''):
            html_string = "<div %s>%s</div>" % (extra, html_string)
        css_class = field.get_value('css_class')
        if css_class not in ('', None):
            # All strings should be escaped before rendering in HTML
            # except for editor field
            html_string = "<span class='%s'>%s</span>" % (css_class,
                                                          html_string)
        return html_string

    def render_autocomplete(self, field, key):
        """
    Use jquery-ui autocompletion for all relation fields by default, requiring
    only erp5_autocompletion_ui bt5 to be installed
    """
        # XXX: Allow to specify more parameters to jquery-ui autocomplete widget?
        import json
        return """
<script type="text/javascript">
$(document).ready(function() {
  $("input[name='%s']").ERP5Autocomplete({search_portal_type: %s,
                                          search_catalog_key: "%s"});
});
</script>""" % (key,
                json.dumps(map(lambda x: x[0],
                               field.get_value('portal_type'))),
                field.get_value('catalog_index'))

    def render_wheel(self,
                     field,
                     value,
                     REQUEST,
                     relation_index=0,
                     sub_index=None,
                     render_prefix=None):
        """
    Render wheel used to display a listbox
    """
        here = self._getContextValue(field, REQUEST)
        portal_url = here.getPortalObject().portal_url
        portal_url_string = portal_url()
        portal_selections_url_string = here.portal_url.getRelativeContentURL(
            here.portal_selections)
        if sub_index is None:
            sub_index_string = ''
        else:
            sub_index_string = '_%s' % sub_index
        return '&nbsp;<input type="image" ' \
             'src="%s/images/exec16.png" value="update..." ' \
             'name="%s/viewSearchRelatedDocumentDialog%s%s' \
             ':method"/>' % \
               (portal_url_string, portal_selections_url_string,
               relation_index, sub_index_string)

    def render_relation_link(self, field, value, REQUEST, render_prefix=None):
        """
    Render link to the related object.
    """
        html_string = ''
        here = REQUEST.get('cell', self._getContextValue(field, REQUEST))
        portal_url = here.getPortalObject().portal_url
        portal_url_string = portal_url()
        if (value not in ((), [], None, '')) and \
            field.get_value('allow_jump'):
            # Keep the selection name in the URL
            if REQUEST.get('selection_name') is not None:
                selection_name_html = '&amp;selection_name=%s&amp;selection_index=%s' % \
                      (REQUEST.get('selection_name'), REQUEST.get('selection_index'))
            else:
                selection_name_html = ''
            if REQUEST.get('ignore_layout') is not None:
                selection_name_html += '&amp;ignore_layout:int=%s' % int(
                    REQUEST.get('ignore_layout', 0))
            # Generate plan link
            html_string += '<a href="%s/%s?field_id=%s&amp;form_id=%s%s">' \
                             '<img src="%s/images/jump.png" alt="jump" />' \
                           '</a>' % \
                      (here.absolute_url(),
                       field.get_value('jump_method'),
                       field.id, field.aq_parent.id,
                       selection_name_html,
                       portal_url_string)
        return html_string
示例#20
0
class DateTimeValidator(Validator):
    property_names = Validator.property_names + [
        'required', 'start_datetime', 'end_datetime', 'allow_empty_time'
    ]
    message_names = Validator.message_names + [
        'required_not_found', 'not_datetime', 'datetime_out_of_range'
    ]

    required = fields.CheckBoxField(
        'required',
        title='Required',
        description=(
            "Checked if the field is required; the user has to enter something "
            "in the field."),
        default=1)
    start_datetime = fields.DateTimeField(
        'start_datetime',
        title="Start datetime",
        description=(
            "The date and time entered must be later than or equal to "
            "this date/time. If left empty, no check is performed."),
        default=None,
        input_style="text",
        required=0)
    end_datetime = fields.DateTimeField(
        'end_datetime',
        title="End datetime",
        description=("The date and time entered must be earlier than "
                     "this date/time. If left empty, no check is performed."),
        default=None,
        input_style="text",
        required=0)
    allow_empty_time = fields.CheckBoxField(
        'allow_empty_time',
        title="Allow empty time",
        description=(
            "Allow time to be left empty. Time will default to midnight "
            "on that date."),
        default=0)

    required_not_found = _('Input is required but no input given.')
    not_datetime = _('You did not enter a valid date and time.')
    datetime_out_of_range = _(
        'The date and time you entered were out of range.')

    def check(self, field, value, failover=False):
        if not isinstance(value, DateTime):
            self.raise_error('not_datetime', field)

        if not failover:
            # check if things are within range
            start_datetime = field.get_value('start_datetime')
            if (start_datetime is not None and value < start_datetime):
                self.raise_error('datetime_out_of_range', field)
            end_datetime = field.get_value('end_datetime')
            if (end_datetime is not None and value >= end_datetime):
                self.raise_error('datetime_out_of_range', field)
        return value

    def validate(self, field, key, REQUEST):
        try:
            year = field.validate_sub_field('year', REQUEST)
            month = field.validate_sub_field('month', REQUEST)
            day = field.validate_sub_field('day', REQUEST)

            if field.get_value('date_only'):
                hour = 0
                minute = 0
            elif field.get_value('allow_empty_time'):
                hour = field.validate_sub_field('hour', REQUEST)
                minute = field.validate_sub_field('minute', REQUEST)
                if hour == '' and minute == '':
                    hour = 0
                    minute = 0
                elif hour == '' or minute == '':
                    raise ValidationError('not_datetime', field)
            else:
                hour = field.validate_sub_field('hour', REQUEST)
                minute = field.validate_sub_field('minute', REQUEST)
        except ValidationError:
            self.raise_error('not_datetime', field)

        # handling of completely empty sub fields
        if ((year == '' and month == '' and day == '') and
            (field.get_value('date_only') or (hour == '' and minute == '') or
             (hour == 0 and minute == 0))):
            if field.get_value('required'):
                self.raise_error('required_not_found', field)
            else:
                # field is not required, return None for no entry
                return None
        # handling of partially empty sub fields; invalid datetime
        if ((year == '' or month == '' or day == '')
                or (not field.get_value('date_only') and
                    (hour == '' or minute == ''))):
            self.raise_error('not_datetime', field)

        if field.get_value('ampm_time_style'):
            ampm = field.validate_sub_field('ampm', REQUEST)
            if field.get_value('allow_empty_time'):
                if ampm == '':
                    ampm = 'am'
            hour = int(hour)
            # handling not am or pm
            # handling hour > 12
            if (not (ampm == 'am' or ampm == 'AM')
                    and not (ampm == 'pm' or ampm == 'PM')) or (hour > 12):
                self.raise_error('not_datetime', field)
            if (ampm == 'pm' or ampm == 'PM') and (hour == 0):
                self.raise_error('not_datetime', field)
            elif (ampm == 'pm' or ampm == 'PM') and hour < 12:
                hour += 12

        try:
            result = DateTime(int(year), int(month), int(day), hour, minute)
        except date_time_format_exceptions:
            self.raise_error('not_datetime', field)

        return self.check(field, result, key + '_novalidate' in REQUEST)

    def serializeValue(self, field, value, producer):
        if value is not None:
            value_string = DateTime(value).HTML4()
            producer.characters(value_string)

    def deserializeValue(self, field, value, context=None):
        if isinstance(value, basestring):
            value = value.strip()
        else:
            value = value.text
            if value:
                value.strip()
        if value:
            return DateTime(value)
        return None
示例#21
0
class MultiRelationStringFieldValidator(Validator.LinesValidator):
  """
      Validation includes lookup of relared instances
  """
  message_names = Validator.LinesValidator.message_names +\
                  ['relation_result_too_long', 'relation_result_ambiguous',
                   'relation_result_empty',]

  relation_result_too_long = "Too many documents were found."
  relation_result_ambiguous = "Select appropriate document in the list."
  relation_result_empty = "No such document was found."

  # Relation field variable
  editor = MultiRelationEditor
  default_validator_instance = Validator.LinesValidatorInstance

  # For relation fields, we want to preserve whitespaces by default
  # so that we can search for "  things   "
  whitespace_preserve = fields.CheckBoxField('whitespace_preserve',
                                            title="Preserve whitespace",
                                            description=(
    "Checked if the field preserves whitespace. This means even "
    "just whitespace input is considered to be data."),
                                            default=1)

  def _generateItemUidList(self, field, key, relation_uid_list, REQUEST=None):
    """
    Generate tuple...
    """
    result_list = []
    for i in range(len(relation_uid_list)):
      # Generate a Item id for each value.
      relation_item_id = field.generate_subfield_key("%s_%s" % \
                                                     (ITEM_ID, i),
                                                     key=key)
      relation_uid = relation_uid_list[i]
      result_list.append((relation_item_id, relation_uid, None))
    return result_list

  def _generateFieldValueList(self, field, key,
                              value_list, current_value_list):
    """
    Generate list of value, item_key
    """
    if isinstance(current_value_list, basestring):
      current_value_list = [current_value_list]
    # Changes in the order or in the number of occurences
    # must be taken into account
    if value_list == current_value_list:
      return []
    if value_list:
      return [
        (
          field.generate_subfield_key(
            "%s_%s" % (SUB_FIELD_ID, index),
            key=key,
          ),
          value,
          field.generate_subfield_key(
            "%s_%s" % (ITEM_ID, index),
            key=key,
          ),
        )
        for index, value in enumerate(value_list)
      ]
    return [
      (
        field.generate_subfield_key(SUB_FIELD_ID, key=key),
        '',
        field.generate_subfield_key(ITEM_ID, key=key),
      )
    ]

  def validate(self, field, key, REQUEST):
    """
    Validate the field.
    """
    raising_error_value = None
    relation_editor_list = []
    catalog_index = field.get_value('catalog_index')
    portal_type_list = [x[0] for x in field.get_value('portal_type')]
    portal = field.getPortalObject()
    portal_catalog = portal.portal_catalog
    relation_uid_list = REQUEST.get(
      field.generate_subfield_key(SUB_FIELD_ID, key=key),
    )
    if relation_uid_list in (None, ''):
      field_value_list = self._generateFieldValueList(
        field,
        key,
        self.default_validator_instance.validate(field, key, REQUEST),
        field.get_value('default'),
      )
      if not field_value_list:
        relation_editor_list = None
      for relation_field_id, value, relation_item_id in field_value_list:
        if value == '':
          for subdict_name in ['form', 'other']:
            getattr(REQUEST, subdict_name).pop(relation_field_id, None)
          relation_editor_list.append(
            (value, None, 'Delete the relation', None, None),
          )
          continue
        relation_uid = REQUEST.get(relation_field_id)
        menu_item_list = []
        if relation_uid in (None, ''):
          kw = dict(field.get_value('parameter_list'))
          kw[catalog_index] = value
          relation_list = portal_catalog(
            portal_type=portal_type_list,
            sort_on=catalog_index,
            **kw
          )
          relation_uid_list = [x.uid for x in relation_list]
          if len(relation_list) >= MAX_SELECT:
            raising_error_value = 'relation_result_too_long'
          elif len(relation_list) == 1:
            relation_uid = relation_uid_list[0]
            related_object = relation_list[0].getObject()
            if related_object is None:
              display_text = 'Object has been deleted'
            else:
              value = display_text = str(
                related_object.getProperty(catalog_index),
              )
            menu_item_list.append((display_text, relation_uid))
            relation_editor_list.append(
              (value, relation_uid, display_text, None, relation_item_id),
            )
          elif relation_list:
            menu_item_list.extend(
              (x.getObject().getProperty(catalog_index), x.uid)
              for x in relation_list
            )
            menu_item_list.append(('', ''))
            raising_error_value = 'relation_result_ambiguous'
          else:
            menu_item_list.append(('', ''))
            if field.get_value('allow_creation'):
              getDefaultModuleValue = portal.getDefaultModuleValue
              for portal_type in portal_type_list:
                try:
                  getDefaultModuleValue(
                    portal_type, default=None, only_visible=True,
                  )
                except ValueError:
                  pass
                else:
                  menu_item_list.append(
                    (
                      translateString(
                        'Add ${portal_type}',
                        mapping={
                          'portal_type': translateString(portal_type),
                        },
                      ),
                      '%s%s' % (NEW_CONTENT_PREFIX, portal_type),
                    )
                  )
            raising_error_value = 'relation_result_empty'
        else:
          if isinstance(relation_uid, (list, tuple)):
            relation_uid = relation_uid[0]
          display_text = 'Object has been deleted'
          if isinstance(relation_uid, basestring) and relation_uid.startswith(
                NEW_CONTENT_PREFIX,
              ):
            display_text = translateString('New ${portal_type}', mapping={
              'portal_type': translateString(
                relation_uid[len(NEW_CONTENT_PREFIX):],
              ),
            })
          elif relation_uid is not None:
            related_object = portal_catalog.getObject(relation_uid)
            if related_object is not None:
              display_text = str(related_object.getProperty(catalog_index))
          menu_item_list.append((display_text, relation_uid))
          relation_editor_list.append(
            (
              value,
              str(relation_uid),
              display_text,
              relation_field_id,
              relation_item_id,
            ),
          )
        REQUEST.set(relation_item_id, menu_item_list)
    else:
      for relation_item_id, relation_uid, value in self._generateItemUidList(
            field, key, relation_uid_list, REQUEST=REQUEST,
          ):
        try:
          related_object = portal_catalog.getObject(relation_uid)
          display_text = str(related_object.getProperty(catalog_index))
        except ValueError:
          if relation_uid.startswith(NEW_CONTENT_PREFIX):
            portal_type = relation_uid[len(NEW_CONTENT_PREFIX):]
            display_text = translateString(
              'New ${portal_type}',
              mapping={
                'portal_type': translateString(portal_type),
              },
            )
          else:
            display_text = 'Object has been deleted'
        if value is None:
          value = display_text
        relation_editor_list.append(
          (value, relation_uid, display_text, None, relation_item_id)
        )

    if raising_error_value:
      self.raise_error(raising_error_value, field)
    return self.editor(
      field.id,
      field.get_value('base_category'),
      portal_type_list,
      field.get_value('portal_type'),
      catalog_index,
      field.get_value('relation_setter_id'),
      relation_editor_list,
      field.get_value('context_getter_id'),
    )
示例#22
0
 def getExtraPropertyList(self):
     return [
         fields.StringField(**self._dynamic_property_list[0]),
         fields.PasswordField(**self._dynamic_property_list[1]),
         fields.CheckBoxField(**self._dynamic_property_list[2])
     ]
示例#23
0
class ValidatorBase:
    """Even more minimalistic base class for validators.
    """
    property_names = ['enabled']
    message_names = []

    enabled = fields.CheckBoxField(
        'enabled',
        title="Enabled",
        description=(
            "If a field is not enabled, it will considered to be not "
            "in the form during rendering or validation. Be careful "
            "when you change this state dynamically (in the TALES tab): "
            "a user could submit a field that since got disabled, or "
            "get a validation error as a field suddenly got enabled that "
            "wasn't there when the form was drawn."),
        default=1)

    def raise_error(self, error_key, field):
        raise ValidationError(error_key, field)

    def check(self, field, value, failover=False):
        """Method used to validate the value for a field, either
        coming from the request, when called by validate, or from XML,
        when called by deserializeValue. If failover is True, don't
        raise an error unless it is critical.
        """
        return value

    def validate(self, field, key, REQUEST):
        pass  # override in subclass

    def serializeValue(self, field, value, producer):
        """Given a field, a value and a sax_producer, serialize in XML
        the value of the field.
        """
        pass  # override in subclass

    def deserializeValue(self, field, value, context=None):
        """Given a field, a value and a context, unserialize the XML
        value for the field.
        """
        if isinstance(value, basestring):
            data = value
        else:
            # We have an lxml node
            data = value.text
            if data is None:
                # Try for subvalues
                data = []
                for entry in value.xpath('form:value',
                                         namespaces={'form': NS_FORMULATOR}):
                    data.append(entry.text)
                if not data:
                    # Let's put an empty string it is safe.
                    data = ''
        REQUEST = {'key': data, 'key_novalidate': '1'}
        return self.validate(field, 'key', REQUEST)

    def need_validate(self, field, key, REQUEST):
        """Default behavior is always validation.
        """
        return 1
示例#24
0
class GadgetFieldValidator(Validator.Validator):

    property_names = Validator.Validator.property_names + [
        'data_url', 'validator_form_id', 'validator_field_id'
    ]

    data_url = fields.CheckBoxField(
        'data_url',
        title='Data Url',
        description=("Checked if gadget return data url."),
        default=0)

    validator_form_id = fields.StringField(
        'validator_form_id',
        title='Validator Form ID',
        description=
        "ID of the validator field's form. Default is the current form",
        default="",
        display_width=40,
        required=0)

    validator_field_id = fields.StringField(
        'validator_field_id',
        title='Validator Field ID',
        description="ID of the validator field.",
        default="",
        display_width=40,
        required=0)

    message_names = Validator.Validator.message_names + ['no_validator']

    no_validator = 'Does not support this operation.'

    def getValidatorField(self, field):
        """Get an external validator field located in the same form.
      """
        field_id = field.id
        validator_form_id = field.get_value('validator_form_id')
        validator_field_id = field.get_value('validator_field_id')

        validator_form = field.aq_parent
        if (validator_form_id):
            if '/' in validator_form_id:
                portal = field.getPortalObject()
                portal_skins = portal.portal_skins
                # If a / is in the form_id, it means that skin_folder is explicitly
                # defined. If so, prevent acquisition to get the form.
                aq_validator_form = aq_base(portal_skins).unrestrictedTraverse(
                    validator_form_id, None)
                if aq_validator_form is not None:
                    validator_form = portal_skins.unrestrictedTraverse(
                        validator_form_id)
            else:
                validator_form = getattr(validator_form, validator_form_id,
                                         None)

        if (validator_form is not None) and validator_field_id:
            if validator_form.has_field(validator_field_id,
                                        include_disabled=1):
                return validator_form.get_field(validator_field_id,
                                                include_disabled=1)
        return None

    def validate(self, field, key, REQUEST):
        validator_field = self.getValidatorField(field)
        if validator_field is None:
            # not editable if no validator
            self.raise_error('no_validator', field)
        else:
            value = validator_field._validate_helper(key, REQUEST)
            if value is not None:
                if field.get_value('data_url'):
                    value = value.split(",")[1]
                    return StringIO(value.decode('base64'))
                return value
示例#25
0
class LinesValidator(StringBaseValidator):
    property_names = StringBaseValidator.property_names +\
                   ['unicode', 'max_lines', 'max_linelength', 'max_length']
    message_names = StringBaseValidator.message_names +\
                  ['too_many_lines', 'line_too_long', 'too_long']

    unicode = fields.CheckBoxField(
        'unicode',
        title='Unicode',
        description=(
            "Checked if the field delivers a unicode string instead of an "
            "8-bit string."),
        default=0)
    max_lines = fields.IntegerField(
        'max_lines',
        title='Maximum lines',
        description=(
            "The maximum amount of lines a user can enter. If set to 0, "
            "or is left empty, there is no maximum."),
        default="",
        required=0)
    max_linelength = fields.IntegerField(
        'max_linelength',
        title="Maximum length of line",
        description=(
            "The maximum length of a line. If set to 0 or is left empty, there "
            "is no maximum."),
        default="",
        required=0)
    max_length = fields.IntegerField(
        'max_length',
        title="Maximum length (in characters)",
        description=(
            "The maximum total length in characters that the user may enter. "
            "If set to 0 or is left empty, there is no maximum."),
        default="",
        required=0)

    too_many_lines = _('You entered too many lines.')
    line_too_long = _('A line was too long.')
    too_long = _('You entered too many characters.')

    def check(self, field, value, failover=False):
        if not isinstance(value, (list, tuple)):
            self.raise_error('not_a_list', field)

        result = []
        encoding = field.get_form_encoding()
        convert = field.get_value('unicode')
        whitespace_preserve = field.get_value('whitespace_preserve')
        if not failover:
            max_line_length = field.get_value('max_linelength') or 0
        else:
            max_line_length = 0
        for line in value:
            # Check each line
            if not whitespace_preserve:
                line = line.strip()
            if max_line_length and len(line) > max_line_length:
                self.raise_error('line_too_long', field)
            result.append(ensure_unicode(line, convert, encoding))

        # Check for input size
        if not failover:
            if not result and field.get_value('required'):
                self.raise_error('required_no_found', field)
            max_lines = field.get_value('max_lines') or 0
            if max_lines and len(result) > max_lines:
                self.raise_error('too_many_lines', field)
        return result

    def validate(self, field, key, REQUEST):
        value = REQUEST.get(key, "").strip()
        if isinstance(value, TaintedString):
            value = str(value)
        if not field.get_value('whitespace_preserve'):
            value = value.strip()

        # Check whether the entire input is too long
        max_length = field.get_value('max_length') or 0
        if max_length and len(value) > max_length:
            self.raise_error('too_long', field)

        # split input into separate lines
        value = value.split("\n")
        return self.check(field, value, key + '_novalidate' in REQUEST)

    def serializeValue(self, field, value, producer):
        value_string = '\n'.join(value)
        producer.characters(value_string)
示例#26
0
class MultiRelationStringFieldWidget(Widget.LinesTextAreaWidget,
                                     Widget.TextWidget, Widget.ListWidget):
    """
  RelationStringField widget
  Works like a string field but includes one buttons
  - one search button which updates the field and sets a relation
  - creates object if not there
  """
    local_property_names = [
        'update_method',
        'jump_method',
        'allow_jump',
        'base_category',
        'portal_type',
        'allow_creation',
        'container_getter_id',
        'context_getter_id',
        'catalog_index',
        'relation_setter_id',
        'relation_form_id',
        'columns',
        'sort',
        'parameter_list',
        'list_method',
        'first_item',
        'items',
        'proxy_listbox_ids',
        'size',
        'extra_item',
    ]

    property_names = (
        lambda name_list, name_set=set():
        # delete double (but preserve order) in order to keep a usable ZMI...
        [x for x in name_list if not (x in name_set or name_set.add(x))]
    )(Widget.LinesTextAreaWidget.property_names +
      Widget.TextWidget.property_names + local_property_names)

    # XXX Field to remove...
    update_method = fields.StringField(
        'update_method',
        title='Update Method',
        description=("The method to call to set the relation. Required."),
        default="Base_validateRelation",
        required=1)

    jump_method = fields.StringField(
        'jump_method',
        title='Jump Method',
        description=("The method to call to jump to the relation. Required."),
        default="Base_jumpToRelatedDocument",
        required=1)

    allow_jump = fields.CheckBoxField(
        'allow_jump',
        title='Allow Jump',
        description=("Do we allow to jump to the relation ?"),
        default=1,
        required=0)

    base_category = fields.StringField(
        'base_category',
        title='Base Category',
        description=("The method to call to set the relation. Required."),
        default="",
        required=1)

    portal_type = fields.ListTextAreaField(
        'portal_type',
        title='Portal Type',
        description=("The method to call to set the relation. Required."),
        default="",
        required=0)

    allow_creation = fields.CheckBoxField(
        'allow_creation',
        title='Allow Creation',
        description=("Do we allow to create new objects ?"),
        default=1,
        required=0)

    container_getter_id = fields.StringField(
        'container_getter_id',
        title='Container Getter Method',
        description=("The method to call to get a container object."),
        default="",
        required=0)

    context_getter_id = fields.StringField(
        'context_getter_id',
        title='Context Getter Method',
        description=("The method to call to get the context."),
        default="",
        required=0)

    catalog_index = fields.StringField(
        'catalog_index',
        title='Catalog Index',
        description=("The method to call to set the relation. Required."),
        default="",
        required=1)

    # XXX Is it a good idea to keep such a field ??
    # User can redefine setter method with a script (and so, don't use the API)
    relation_setter_id = fields.StringField(
        'relation_setter_id',
        title='Relation Update Method',
        description=("The method to invoke in order to update the relation"),
        default="",
        required=0)

    relation_form_id = fields.StringField(
        'relation_form_id',
        title='Relation Form',
        description=("Form to display relation choices"),
        default="",
        required=0)

    size = fields.IntegerField(
        'size',
        title='Size',
        description=(
            "The display size in rows of the field. If set to 1, the "
            "widget will be displayed as a drop down box by many browsers, "
            "if set to something higher, a list will be shown. Required."),
        default=1,
        required=1)

    columns = fields.ListTextAreaField(
        'columns',
        title="Columns",
        description=("A list of attributes names to display."),
        default=[],
        required=0)

    sort = fields.ListTextAreaField(
        'sort',
        title='Default Sort',
        description=('The default sort keys and order'),
        default=[],
        required=0)

    parameter_list = fields.ListTextAreaField(
        'parameter_list',
        title="Parameter List",
        description=("A list of paramters used for the portal_catalog."),
        default=[],
        required=0)

    list_method = fields.MethodField('list_method',
                                     title='List Method',
                                     description=('The method to use to list'
                                                  'objects'),
                                     default='',
                                     required=0)

    proxy_listbox_ids = fields.ListTextAreaField(
        'proxy_listbox_ids',
        title='Proxy Listbox IDs',
        description=('A list of listbox that can be used as proxy'),
        default='',
        required=0)

    default_widget_rendering_instance = Widget.LinesTextAreaWidgetInstance

    def _getContextValue(self, field, REQUEST):
        """Return result of evaluated method
    defined by context_getter_id or here.
    """
        context_getter_id = field.get_value('context_getter_id')
        here = REQUEST['here']
        if context_getter_id:
            return getattr(here, context_getter_id)()
        return here

    def _generateRenderValueList(self, field, key, value_list, REQUEST):
        if isinstance(value_list, basestring):
            # Value is a string, reformat it correctly
            value_list = value_list.split("\n")
        else:
            # We get a list
            # rather than displaying nothing, display a marker when the
            # property is not set
            # XXX Translate ?
            value_list = [(x or NO_VALUE) for x in value_list]
        generate_subfield_key = field.generate_subfield_key
        need_validation = False
        result_list = []
        for index, value in enumerate(value_list):
            relation_item_list = REQUEST.get(
                generate_subfield_key(
                    "%s_%s" % (ITEM_ID, index),
                    key=key,
                ),
                None,
            )
            # If we get a empty string, display nothing !
            if value:
                need_validation |= relation_item_list is not None
                result_list.append((
                    Widget.TextWidgetInstance,
                    generate_subfield_key(
                        "%s_%s" % (SUB_FIELD_ID, index),
                        key=key,
                    ),
                    relation_item_list,
                    value,
                    index,
                ), )
        if need_validation:
            return result_list
        return [(Widget.LinesTextAreaWidgetInstance, None, [], value_list,
                 None)]

    def render(self, field, key, value, REQUEST, render_prefix=None):
        """
    Render text input field.
    """
        portal = self._getContextValue(field, REQUEST).getPortalObject()
        autocomplete_enabled = getattr(
            portal.portal_skins,
            'erp5_autocompletion_ui',
            None,
        ) is not None
        relation_field_index = REQUEST.get('_v_relation_field_index', 0)
        html_string_list = []
        for (widget_instance, relation_field_id, relation_item_list,
             value_instance, sub_index) in self._generateRenderValueList(
                 field,
                 key,
                 value,
                 REQUEST,
             ):
            sub_html_string = widget_instance.render(
                field,
                key,
                value_instance,
                REQUEST,
            )
            if autocomplete_enabled:
                sub_html_string += self.render_autocomplete(field, key)
            if relation_item_list is not None:
                if not autocomplete_enabled:
                    sub_html_string += self.render_wheel(
                        field,
                        value_instance,
                        REQUEST,
                        relation_index=relation_field_index,
                        sub_index=sub_index,
                    )
                if relation_item_list:
                    REQUEST['relation_item_list'] = relation_item_list
                    sub_html_string += NBSP + Widget.ListWidgetInstance.render(
                        field,
                        relation_field_id,
                        None,
                        REQUEST,
                    ) + NBSP
                    REQUEST['relation_item_list'] = None
            html_string_list.append(sub_html_string)
        html_string = '<br/>'.join(html_string_list)
        if (value == field.get_value('default')):
            # XXX Default rendering with value...
            relation_html_string = self.render_relation_link(
                field, value, REQUEST)
            if relation_html_string:
                html_string += NBSP + NBSP + relation_html_string
        REQUEST.set('_v_relation_field_index', relation_field_index + 1)
        return html_string

    def render_view(self, field, value, REQUEST=None, render_prefix=None):
        """
    Render read only field.
    """
        if (value not in ((), [], None, '')) and field.get_value('allow_jump'):
            if not isinstance(value, (list, tuple)):
                value = value,
            html_string = '<br />'.join(
                '<a class="relationfieldlink" href="%s">%s</a>' % (
                    escape(jump_reference.absolute_url()),
                    escape(display_value),
                ) for jump_reference, display_value in zip(
                    getattr(
                        self._getContextValue(field,
                                              REQUEST), 'get%sValueList' %
                        ''.join(part.capitalize() for part in field.get_value(
                            'base_category').split('_')))(
                                portal_type=[
                                    x[0]
                                    for x in field.get_value('portal_type')
                                ],
                                filter=dict(field.get_value('parameter_list')),
                            ),
                    value,
                ))
        else:
            html_string = self.default_widget_rendering_instance.render_view(
                field,
                value,
                REQUEST=REQUEST,
            )
            if REQUEST is None:
                REQUEST = get_request()
            relation_html_string = self.render_relation_link(
                field, value, REQUEST)
            if relation_html_string:
                html_string += NBSP + NBSP + relation_html_string
        extra = field.get_value('extra')
        if extra not in (None, ''):
            html_string = "<div %s>%s</div>" % (extra, html_string)
        css_class = field.get_value('css_class')
        if css_class not in ('', None):
            html_string = '<span class="%s">%s</span>' % (
                escape(css_class),
                html_string,
            )
        return html_string

    def render_autocomplete(self, field, key):
        """
    Use jquery-ui autocompletion for all relation fields by default, requiring
    only erp5_autocompletion_ui bt5 to be installed
    """
        # XXX: Allow to specify more parameters to jquery-ui autocomplete widget?
        return """
<script type="text/javascript">
$(document).ready(function() {
  $("input[name='%s']").ERP5Autocomplete({search_portal_type: %s,
                                          search_catalog_key: "%s"});
});
</script>""" % (
            escape(key),
            escape(json.dumps([x[0] for x in field.get_value('portal_type')])),
            escape(field.get_value('catalog_index')),
        )

    def render_wheel(self,
                     field,
                     value,
                     REQUEST,
                     relation_index=0,
                     sub_index=None,
                     render_prefix=None):
        """
    Render wheel used to display a listbox
    """
        here = self._getContextValue(field, REQUEST)
        portal_url = here.getPortalObject().portal_url
        if sub_index is None:
            sub_index_string = ''
        else:
            sub_index_string = '_%s' % sub_index
        return '&nbsp;<input type="image" ' \
          'src="%s/images/exec16.png" alt="update..." ' \
          'name="%s/viewSearchRelatedDocumentDialog%s%s' \
          ':method"/>' % (
          escape(portal_url()),
          escape(portal_url.getRelativeContentURL(here.portal_selections)),
          escape(str(relation_index)),
          escape(sub_index_string),
        )

    def render_relation_link(self, field, value, REQUEST, render_prefix=None):
        """
    Render link to the related object.
    """
        if value not in ((), [], None, '') and field.get_value('allow_jump'):
            # If we this relation field is used as a listbox/matrixbox editable
            # field, then the context of this cell is set in REQUEST. XXX this is not
            # 100% reliable way, maybe we need something to know that the field is
            # beeing rendered as an editable field.
            cell = REQUEST.get('cell')
            here = (cell if cell is not None else self._getContextValue(
                field, REQUEST))
            # Keep the selection name in the URL
            selection_name = REQUEST.get('selection_name')
            if selection_name is not None:
                selection_name_html = '&amp;selection_name=%s&amp;selection_index=%s' % (
                    escape(selection_name),
                    escape(str(REQUEST.get('selection_index', 0))),
                )
            else:
                selection_name_html = ''
            ignore_layout = REQUEST.get('ignore_layout')
            if ignore_layout is not None:
                selection_name_html += '&amp;ignore_layout:int=%s' % int(
                    ignore_layout)
            # Generate plan link
            return '<a href="%s/%s?field_id=%s&amp;form_id=%s%s">' \
              '<img src="%s/images/jump.png" alt="jump" />' \
            '</a>' % (
              escape(here.absolute_url()),
              escape(field.get_value('jump_method')),
              escape(field.id),
              escape(field.aq_parent.id),
              escape(selection_name_html),
              escape(here.getPortalObject().portal_url()),
            )
        return ''
示例#27
0
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