web/formfields.py
author sylvain.thenault@logilab.fr
Tue, 07 Apr 2009 17:18:54 +0200
branchtls-sprint
changeset 1265 e5cdd5c0dce3
parent 1181 620ec8e6ae19
child 1268 5db94912650b
permissions -rw-r--r--
handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
     1
"""field classes for form construction
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
     2
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
     3
:organization: Logilab
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
     4
:copyright: 2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
     5
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
     6
"""
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
     7
__docformat__ = "restructuredtext en"
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
     8
1095
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
     9
from datetime import datetime
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
    10
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
    11
from logilab.mtconverter import html_escape
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
    12
from yams.constraints import SizeConstraint, StaticVocabularyConstraint
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
    13
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
    14
from cubicweb.schema import FormatConstraint
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
    15
from cubicweb.utils import ustrftime
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
    16
from cubicweb.common import tags, uilib
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
    17
from cubicweb.web import INTERNAL_FIELD_VALUE
1265
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    18
from cubicweb.web.formwidgets import (
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    19
    HiddenInput, TextInput, FileInput, PasswordInput, TextArea, FCKEditor,
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    20
    Radio, Select, DateTimePicker) 
1095
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
    21
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
    22
class Field(object):
1265
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    23
    """field class is introduced to control what's displayed in forms. It makes
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    24
    the link between something to edit and its display in the form. Actual
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    25
    display is handled by a widget associated to the field.
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    26
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    27
    Attributes
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    28
    ----------
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    29
    all the attributes described below have sensible default value which may be
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    30
    overriden by value given to field's constructor.
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    31
    
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    32
    :name:
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    33
       name of the field (basestring), should be unique in a form.
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    34
    :id:
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    35
       dom identifier (default to the same value as `name`), should be unique in
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    36
       a form.
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    37
    :label:
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    38
       label of the field (default to the same value as `name`).
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    39
    :help:
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    40
       help message about this field.
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    41
    :widget:
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    42
       widget associated to the field. Each field class has a default widget
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    43
       class which may be overriden per instance.
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    44
    :required:
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    45
       bool flag telling if the field is required or not.
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    46
    :initial:
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    47
       initial value, used when no value specified by other means.
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    48
    :choices:
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    49
       static vocabulary for this field. May be a list of values or a list of
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    50
       (label, value) tuples if specified.
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    51
    :sort:
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    52
       bool flag telling if the vocabulary (either static vocabulary specified
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    53
       in `choices` or dynamic vocabulary fetched from the form) should be
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    54
       sorted on label.
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    55
    :internationalizable:
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    56
       bool flag telling if the vocabulary labels should be translated using the
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    57
       current request language.
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    58
    :eidparam:
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    59
       bool flag telling if this field is linked to a specific entity
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    60
    :role:
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    61
       when the field is linked to an entity attribute or relation, tells the
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    62
       role of the entity in the relation (eg 'subject' or 'object')
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    63
    
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
    64
    """
1265
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    65
    # default widget associated to this class of fields. May be overriden per
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    66
    # instance
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
    67
    widget = TextInput
1265
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    68
    # does this field requires a multipart form
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
    69
    needs_multipart = False
1265
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    70
    # class attribute used for ordering of fields in a form
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    71
    __creation_rank = 0
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
    72
1265
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    73
    def __init__(self, name=None, id=None, label=None, help=None, 
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
    74
                 widget=None, required=False, initial=None,
1265
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    75
                 choices=None, sort=True, internationalizable=False,
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    76
                 eidparam=False, role='subject'):
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    77
        self.name = name
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    78
        self.id = id or name
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    79
        self.label = label or name
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    80
        self.help = help
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
    81
        self.required = required
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
    82
        if widget is not None:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
    83
            self.widget = widget
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
    84
        if isinstance(self.widget, type):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
    85
            self.widget = self.widget()
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
    86
        self.initial = initial
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
    87
        self.choices = choices
1265
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    88
        self.sort = sort
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    89
        self.internationalizable = internationalizable
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
    90
        self.eidparam = eidparam
1095
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
    91
        self.role = role
1265
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    92
        # ordering number for this field instance
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    93
        self.creation_rank = Field.__creation_rank
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    94
        Field.__creation_rank += 1
1108
1e5ed5f57f2f give field id in __repr__
sylvain.thenault@logilab.fr
parents: 1104
diff changeset
    95
    
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
    96
    def __unicode__(self):
1108
1e5ed5f57f2f give field id in __repr__
sylvain.thenault@logilab.fr
parents: 1104
diff changeset
    97
        return u'<%s name=%r label=%r id=%r initial=%r @%x>' % (
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
    98
            self.__class__.__name__, self.name, self.label,
1108
1e5ed5f57f2f give field id in __repr__
sylvain.thenault@logilab.fr
parents: 1104
diff changeset
    99
            self.id, self.initial, id(self))
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   100
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   101
    def __repr__(self):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   102
        return self.__unicode__().encode('utf-8')
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   103
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   104
    def set_name(self, name):
1265
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
   105
        """automatically set .id and .label when name is set"""
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   106
        assert name
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   107
        self.name = name
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   108
        if not self.id:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   109
            self.id = name
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   110
        if not self.label:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   111
            self.label = name
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   112
            
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   113
    def is_visible(self):
1265
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
   114
        """return true if the field is not an hidden field"""
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   115
        return not isinstance(self.widget, HiddenInput)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   116
    
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   117
    def actual_fields(self, form):
1265
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
   118
        """return actual fields composing this field in case of a compound
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
   119
        field, usually simply return self
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
   120
        """
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   121
        yield self
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   122
    
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   123
    def format_value(self, req, value):
1265
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
   124
        """return value suitable for display where value may be a list or tuple
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
   125
        of values
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
   126
        """
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   127
        if isinstance(value, (list, tuple)):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   128
            return [self.format_single_value(req, val) for val in value]
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   129
        return self.format_single_value(req, value)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   130
    
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   131
    def format_single_value(self, req, value):
1265
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
   132
        """return value suitable for display"""
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   133
        if value is None:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   134
            return u''
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   135
        return unicode(value)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   136
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   137
    def get_widget(self, form):
1265
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
   138
        """return the widget instance associated to this field"""
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   139
        return self.widget
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   140
    
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   141
    def example_format(self, req):
1265
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
   142
        """return a sample string describing what can be given as input for this
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
   143
        field
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
   144
        """        
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   145
        return u''
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   146
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   147
    def render(self, form, renderer):
1265
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
   148
        """render this field, which is part of form, using the given form
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
   149
        renderer
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
   150
        """
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   151
        return self.get_widget(form).render(form, self)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   152
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   153
    def vocabulary(self, form):
1265
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
   154
        """return vocabulary for this field. This method will be called by
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
   155
        widgets which desire it."""        
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   156
        if self.choices is not None:
1181
620ec8e6ae19 cleanup, various fix to get something working
sylvain.thenault@logilab.fr
parents: 1147
diff changeset
   157
            if callable(self.choices):
620ec8e6ae19 cleanup, various fix to get something working
sylvain.thenault@logilab.fr
parents: 1147
diff changeset
   158
                vocab = self.choices(req=form.req)
620ec8e6ae19 cleanup, various fix to get something working
sylvain.thenault@logilab.fr
parents: 1147
diff changeset
   159
            else:
620ec8e6ae19 cleanup, various fix to get something working
sylvain.thenault@logilab.fr
parents: 1147
diff changeset
   160
                vocab = self.choices
620ec8e6ae19 cleanup, various fix to get something working
sylvain.thenault@logilab.fr
parents: 1147
diff changeset
   161
            if vocab and not isinstance(vocab[0], (list, tuple)):
620ec8e6ae19 cleanup, various fix to get something working
sylvain.thenault@logilab.fr
parents: 1147
diff changeset
   162
                vocab = [(x, x) for x in vocab]
1265
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
   163
        else:
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
   164
            vocab = form.form_field_vocabulary(self)
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
   165
        if self.internationalizable:
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
   166
            vocab = [(form.req._(label), value) for label, value in vocab]
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
   167
        if self.sort:
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
   168
            vocab = sorted(vocab)
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
   169
        return vocab
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   170
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   171
    
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   172
class StringField(Field):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   173
    def __init__(self, max_length=None, **kwargs):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   174
        super(StringField, self).__init__(**kwargs)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   175
        self.max_length = max_length
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   176
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   177
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   178
class TextField(Field):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   179
    widget = TextArea
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   180
    def __init__(self, rows=10, cols=80, **kwargs):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   181
        super(TextField, self).__init__(**kwargs)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   182
        self.rows = rows
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   183
        self.cols = cols
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   184
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   185
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   186
class RichTextField(TextField):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   187
    widget = None
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   188
    def __init__(self, format_field=None, **kwargs):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   189
        super(RichTextField, self).__init__(**kwargs)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   190
        self.format_field = format_field
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   191
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   192
    def get_widget(self, form):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   193
        if self.widget is None:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   194
            if self.use_fckeditor(form):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   195
                return FCKEditor()
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   196
            return TextArea()
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   197
        return self.widget
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   198
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   199
    def get_format_field(self, form):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   200
        if self.format_field:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   201
            return self.format_field
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   202
        # we have to cache generated field since it's use as key in the
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   203
        # context dictionnary
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   204
        req = form.req
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   205
        try:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   206
            return req.data[self]
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   207
        except KeyError:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   208
            if self.use_fckeditor(form):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   209
                # if fckeditor is used and format field isn't explicitly
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   210
                # deactivated, we want an hidden field for the format
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   211
                widget = HiddenInput()
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   212
                choices = None
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   213
            else:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   214
                # else we want a format selector
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   215
                # XXX compute vocabulary
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   216
                widget = Select
1095
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
   217
                fcstr = FormatConstraint()
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
   218
                choices = [(req._(fmt), fmt) for fmt in fcstr.vocabulary(req=req)]
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   219
            field = StringField(name=self.name + '_format', widget=widget,
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   220
                                choices=choices)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   221
            req.data[self] = field
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   222
            return field
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   223
    
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   224
    def actual_fields(self, form):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   225
        yield self
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   226
        format_field = self.get_format_field(form)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   227
        if format_field:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   228
            yield format_field
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   229
            
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   230
    def use_fckeditor(self, form):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   231
        """return True if fckeditor should be used to edit entity's attribute named
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   232
        `attr`, according to user preferences
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   233
        """
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   234
        if form.req.use_fckeditor():
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   235
            return form.form_field_format(self) == 'text/html'
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   236
        return False
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   237
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   238
    def render(self, form, renderer):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   239
        format_field = self.get_format_field(form)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   240
        if format_field:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   241
            result = format_field.render(form, renderer)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   242
        else:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   243
            result = u''
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   244
        return result + self.get_widget(form).render(form, self)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   245
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   246
    
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   247
class FileField(StringField):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   248
    widget = FileInput
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   249
    needs_multipart = True
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   250
    
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   251
    def __init__(self, format_field=None, encoding_field=None, **kwargs):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   252
        super(FileField, self).__init__(**kwargs)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   253
        self.format_field = format_field
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   254
        self.encoding_field = encoding_field
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   255
        
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   256
    def actual_fields(self, form):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   257
        yield self
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   258
        if self.format_field:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   259
            yield self.format_field
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   260
        if self.encoding_field:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   261
            yield self.encoding_field
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   262
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   263
    def render(self, form, renderer):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   264
        wdgs = [self.get_widget(form).render(form, self)]
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   265
        if self.format_field or self.encoding_field:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   266
            divid = '%s-advanced' % form.context[self]['name']
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   267
            wdgs.append(u'<a href="%s" title="%s"><img src="%s" alt="%s"/></a>' %
1095
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
   268
                        (html_escape(uilib.toggle_action(divid)),
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   269
                         form.req._('show advanced fields'),
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   270
                         html_escape(form.req.build_url('data/puce_down.png')),
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   271
                         form.req._('show advanced fields')))
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   272
            wdgs.append(u'<div id="%s" class="hidden">' % divid)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   273
            if self.format_field:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   274
                wdgs.append(self.render_subfield(form, self.format_field, renderer))
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   275
            if self.encoding_field:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   276
                wdgs.append(self.render_subfield(form, self.encoding_field, renderer))
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   277
            wdgs.append(u'</div>')            
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   278
        if not self.required and form.context[self]['value']:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   279
            # trick to be able to delete an uploaded file
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   280
            wdgs.append(u'<br/>')
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   281
            wdgs.append(tags.input(name=u'%s__detach' % form.context[self]['name'],
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   282
                                   type=u'checkbox'))
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   283
            wdgs.append(form.req._('detach attached file'))
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   284
        return u'\n'.join(wdgs)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   285
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   286
    def render_subfield(self, form, field, renderer):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   287
        return (renderer.render_label(form, field)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   288
                + field.render(form, renderer)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   289
                + renderer.render_help(form, field)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   290
                + u'<br/>')
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   291
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   292
        
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   293
class EditableFileField(FileField):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   294
    editable_formats = ('text/plain', 'text/html', 'text/rest')
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   295
    
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   296
    def render(self, form, renderer):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   297
        wdgs = [super(EditableFileField, self).render(form, renderer)]
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   298
        if form.form_field_format(self) in self.editable_formats:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   299
            data = form.form_field_value(self, {}, load_bytes=True)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   300
            if data:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   301
                encoding = form.form_field_encoding(self)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   302
                try:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   303
                    form.context[self]['value'] = unicode(data.getvalue(), encoding)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   304
                except UnicodeError:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   305
                    pass
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   306
                else:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   307
                    if not self.required:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   308
                        msg = form.req._(
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   309
                            'You can either submit a new file using the browse button above'
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   310
                            ', or choose to remove already uploaded file by checking the '
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   311
                            '"detach attached file" check-box, or edit file content online '
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   312
                            'with the widget below.')
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   313
                    else:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   314
                        msg = form.req._(
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   315
                            'You can either submit a new file using the browse button above'
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   316
                            ', or edit file content online with the widget below.')
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   317
                    wdgs.append(u'<p><b>%s</b></p>' % msg)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   318
                    wdgs.append(TextArea(setdomid=False).render(form, self))
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   319
                    # XXX restore form context?
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   320
        return '\n'.join(wdgs)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   321
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   322
        
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   323
class IntField(Field):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   324
    def __init__(self, min=None, max=None, **kwargs):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   325
        super(IntField, self).__init__(**kwargs)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   326
        self.min = min
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   327
        self.max = max
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   328
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   329
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   330
class BooleanField(Field):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   331
    widget = Radio
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   332
        
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   333
    def vocabulary(self, form):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   334
        if self.choices:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   335
            return self.choices
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   336
        return [(form.req._('yes'), '1'), (form.req._('no'), '')]
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   337
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   338
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   339
class FloatField(IntField):    
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   340
    def format_single_value(self, req, value):
1095
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
   341
        formatstr = req.property_value('ui.float-format')
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   342
        if value is None:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   343
            return u''
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   344
        return formatstr % float(value)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   345
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   346
    def render_example(self, req):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   347
        return self.format_value(req, 1.234)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   348
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   349
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   350
class DateField(StringField):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   351
    format_prop = 'ui.date-format'
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   352
    widget = DateTimePicker
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   353
    
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   354
    def format_single_value(self, req, value):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   355
        return value and ustrftime(value, req.property_value(self.format_prop)) or u''
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   356
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   357
    def render_example(self, req):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   358
        return self.format_value(req, datetime.now())
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   359
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   360
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   361
class DateTimeField(DateField):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   362
    format_prop = 'ui.datetime-format'
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   363
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   364
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   365
class TimeField(DateField):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   366
    format_prop = 'ui.datetime-format'
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   367
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   368
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   369
class HiddenInitialValueField(Field):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   370
    def __init__(self, visible_field, name):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   371
        super(HiddenInitialValueField, self).__init__(name=name,
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   372
                                                      widget=HiddenInput,
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   373
                                                      eidparam=True)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   374
        self.visible_field = visible_field
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   375
    
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   376
                 
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   377
class RelationField(Field):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   378
    def __init__(self, **kwargs):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   379
        super(RelationField, self).__init__(**kwargs)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   380
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   381
    @staticmethod
1095
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
   382
    def fromcardinality(card, **kwargs):
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
   383
        return RelationField(widget=Select(multiple=card in '*+'), **kwargs)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   384
        
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   385
    def vocabulary(self, form):
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1108
diff changeset
   386
        entity = form.edited_entity
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   387
        req = entity.req
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   388
        # first see if its specified by __linkto form parameters
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   389
        linkedto = entity.linked_to(self.name, self.role)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   390
        if linkedto:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   391
            entities = (req.eid_rset(eid).get_entity(0, 0) for eid in linkedto)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   392
            return [(entity.view('combobox'), entity.eid) for entity in entities]
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   393
        # it isn't, check if the entity provides a method to get correct values
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   394
        res = []
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   395
        if not self.required:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   396
            res.append(('', INTERNAL_FIELD_VALUE))
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   397
        # vocabulary doesn't include current values, add them
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   398
        if entity.has_eid():
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   399
            rset = entity.related(self.name, self.role)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   400
            relatedvocab = [(e.view('combobox'), e.eid) for e in rset.entities()]
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   401
        else:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   402
            relatedvocab = []
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   403
        return res + form.form_field_vocabulary(self) + relatedvocab
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   404
    
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   405
    def format_single_value(self, req, value):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   406
        return value
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   407
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   408
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   409
def stringfield_from_constraints(constraints, **kwargs):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   410
    field = None
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   411
    for cstr in constraints:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   412
        if isinstance(cstr, StaticVocabularyConstraint):
1181
620ec8e6ae19 cleanup, various fix to get something working
sylvain.thenault@logilab.fr
parents: 1147
diff changeset
   413
            kwargs.setdefault('widget', Select())
620ec8e6ae19 cleanup, various fix to get something working
sylvain.thenault@logilab.fr
parents: 1147
diff changeset
   414
            return StringField(choices=cstr.vocabulary, **kwargs)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   415
        if isinstance(cstr, SizeConstraint) and cstr.max is not None:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   416
            if cstr.max > 257:
1095
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
   417
                rows_cols_from_constraint(cstr, kwargs)
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
   418
                field = TextField(**kwargs)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   419
            else:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   420
                field = StringField(max_length=cstr.max, **kwargs)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   421
    return field or TextField(**kwargs)
1095
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
   422
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   423
1095
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
   424
def rows_cols_from_constraint(constraint, kwargs):
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
   425
    if constraint.max < 513:
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   426
        rows, cols = 5, 60
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   427
    else:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   428
        rows, cols = 10, 80
1095
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
   429
    kwargs.setdefault('rows', rows)
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
   430
    kwargs.setdefault('cols', cols)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   431
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   432
1104
58f27c3c0167 more guess_field tests and fixes
sylvain.thenault@logilab.fr
parents: 1101
diff changeset
   433
def guess_field(eclass, rschema, role='subject', skip_meta_attr=True, **kwargs):
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   434
    """return the most adapated widget to edit the relation
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   435
    'subjschema rschema objschema' according to information found in the schema
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   436
    """
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   437
    fieldclass = None
1095
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
   438
    eschema = eclass.e_schema
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   439
    if role == 'subject':
1095
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
   440
        targetschema = rschema.objects(eschema)[0]
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
   441
        card = rschema.rproperty(eschema, targetschema, 'cardinality')[0]
1265
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
   442
        if rschema.is_final():
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
   443
            if rschema.rproperty(eschema, targetschema, 'internationalizable'):
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
   444
                kwargs['internationalizable'] = True
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
   445
            kwargs['initial'] = rschema.rproperty(eschema, targetschema, 'default')
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   446
    else:
1095
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
   447
        targetschema = rschema.subjects(eschema)[0]
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
   448
        card = rschema.rproperty(targetschema, eschema, 'cardinality')[1]
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
   449
    kwargs['required'] = card in '1+'
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
   450
    kwargs['name'] = rschema.type
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
   451
    if rschema.is_final():
1104
58f27c3c0167 more guess_field tests and fixes
sylvain.thenault@logilab.fr
parents: 1101
diff changeset
   452
        if skip_meta_attr and rschema in eschema.meta_attributes():
1095
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
   453
            return None
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
   454
        fieldclass = FIELDS[targetschema]
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
   455
        if fieldclass is StringField:
1104
58f27c3c0167 more guess_field tests and fixes
sylvain.thenault@logilab.fr
parents: 1101
diff changeset
   456
            if targetschema == 'Password':
58f27c3c0167 more guess_field tests and fixes
sylvain.thenault@logilab.fr
parents: 1101
diff changeset
   457
                # special case for Password field: specific PasswordInput widget
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1108
diff changeset
   458
                kwargs.setdefault('widget', PasswordInput())
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1108
diff changeset
   459
                return StringField(**kwargs)
1104
58f27c3c0167 more guess_field tests and fixes
sylvain.thenault@logilab.fr
parents: 1101
diff changeset
   460
            if eschema.has_metadata(rschema, 'format'):
58f27c3c0167 more guess_field tests and fixes
sylvain.thenault@logilab.fr
parents: 1101
diff changeset
   461
                # use RichTextField instead of StringField if the attribute has
58f27c3c0167 more guess_field tests and fixes
sylvain.thenault@logilab.fr
parents: 1101
diff changeset
   462
                # a "format" metadata. But getting information from constraints
58f27c3c0167 more guess_field tests and fixes
sylvain.thenault@logilab.fr
parents: 1101
diff changeset
   463
                # may be useful anyway...
58f27c3c0167 more guess_field tests and fixes
sylvain.thenault@logilab.fr
parents: 1101
diff changeset
   464
                constraints = rschema.rproperty(eschema, targetschema, 'constraints')
58f27c3c0167 more guess_field tests and fixes
sylvain.thenault@logilab.fr
parents: 1101
diff changeset
   465
                for cstr in constraints:
58f27c3c0167 more guess_field tests and fixes
sylvain.thenault@logilab.fr
parents: 1101
diff changeset
   466
                    if isinstance(cstr, StaticVocabularyConstraint):
58f27c3c0167 more guess_field tests and fixes
sylvain.thenault@logilab.fr
parents: 1101
diff changeset
   467
                        raise Exception('rich text field with static vocabulary')
58f27c3c0167 more guess_field tests and fixes
sylvain.thenault@logilab.fr
parents: 1101
diff changeset
   468
                    if isinstance(cstr, SizeConstraint) and cstr.max is not None:
58f27c3c0167 more guess_field tests and fixes
sylvain.thenault@logilab.fr
parents: 1101
diff changeset
   469
                        rows_cols_from_constraint(cstr, kwargs)
58f27c3c0167 more guess_field tests and fixes
sylvain.thenault@logilab.fr
parents: 1101
diff changeset
   470
                return RichTextField(**kwargs)
58f27c3c0167 more guess_field tests and fixes
sylvain.thenault@logilab.fr
parents: 1101
diff changeset
   471
            # return StringField or TextField according to constraints
1095
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
   472
            constraints = rschema.rproperty(eschema, targetschema, 'constraints')
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
   473
            return stringfield_from_constraints(constraints, **kwargs)
1104
58f27c3c0167 more guess_field tests and fixes
sylvain.thenault@logilab.fr
parents: 1101
diff changeset
   474
        if fieldclass is FileField:
58f27c3c0167 more guess_field tests and fixes
sylvain.thenault@logilab.fr
parents: 1101
diff changeset
   475
            for metadata in ('format', 'encoding'):
58f27c3c0167 more guess_field tests and fixes
sylvain.thenault@logilab.fr
parents: 1101
diff changeset
   476
                metaschema = eschema.has_metadata(rschema, metadata)
58f27c3c0167 more guess_field tests and fixes
sylvain.thenault@logilab.fr
parents: 1101
diff changeset
   477
                if metaschema is not None:
58f27c3c0167 more guess_field tests and fixes
sylvain.thenault@logilab.fr
parents: 1101
diff changeset
   478
                    kwargs['%s_field' % metadata] = guess_field(eclass, metaschema,
58f27c3c0167 more guess_field tests and fixes
sylvain.thenault@logilab.fr
parents: 1101
diff changeset
   479
                                                                skip_meta_attr=False)
1095
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
   480
        return fieldclass(**kwargs)
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
   481
    kwargs['role'] = role
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
   482
    return RelationField.fromcardinality(card, **kwargs)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   483
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   484
FIELDS = {
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   485
    'Boolean':  BooleanField,
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   486
    'Bytes':    FileField,
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   487
    'Date':     DateField,
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   488
    'Datetime': DateTimeField,
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   489
    'Int':      IntField,
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   490
    'Float':    FloatField,
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   491
    'Decimal':  StringField,
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   492
    'Password': StringField,
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   493
    'String' :  StringField,
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   494
    'Time':     TimeField,
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   495
    }