web/uihelper.py
changeset 8667 5a394fc419b4
parent 8665 e65af61bde7d
child 9161 7b51daf84a66
equal deleted inserted replaced
8666:1dd655788ece 8667:5a394fc419b4
     1 # copyright 2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
     1 # copyright 2011-2012 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
     2 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
     2 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
     3 #
     3 #
     4 # This file is part of CubicWeb.
     4 # This file is part of CubicWeb.
     5 #
     5 #
     6 # CubicWeb is free software: you can redistribute it and/or modify it under the
     6 # CubicWeb is free software: you can redistribute it and/or modify it under the
    43 .. autoclass:: cubicweb.web.uihelper.FormConfig
    43 .. autoclass:: cubicweb.web.uihelper.FormConfig
    44 
    44 
    45 """
    45 """
    46 __docformat__ = "restructuredtext en"
    46 __docformat__ = "restructuredtext en"
    47 
    47 
       
    48 
       
    49 from logilab.common.deprecation import deprecated
    48 from cubicweb.web.views import uicfg
    50 from cubicweb.web.views import uicfg
    49 from functools import partial
       
    50 
       
    51 def _tag_rel(rtag, etype, attr, desttype='*', *args, **kwargs):
       
    52     if isinstance(attr, basestring):
       
    53         attr, role = attr, 'subject'
       
    54     else:
       
    55         attr, role = attr
       
    56     if role == 'subject':
       
    57         rtag.tag_subject_of((etype, attr, desttype), *args, **kwargs)
       
    58     else:
       
    59         rtag.tag_object_of((desttype, attr, etype), *args, **kwargs)
       
    60 
    51 
    61 
    52 
    62 ## generic uicfg helpers ######################################################
    53 ## generic uicfg helpers ######################################################
    63 def append_to_addmenu(etype, attr, createdtype='*'):
       
    64     """adds `attr` in the actions box *addrelated* submenu of `etype`.
       
    65 
    54 
    66     :param etype: the entity type as a string
    55 backward_compat_funcs = (('append_to_addmenu', uicfg.actionbox_appearsin_addmenu),
    67     :param attr: the name of the attribute or relation to hide
    56                          ('remove_from_addmenu', uicfg.actionbox_appearsin_addmenu),
       
    57                          ('set_fields_order', uicfg.autoform_field_kwargs),
       
    58                          ('hide_field', uicfg.autoform_section),
       
    59                          ('hide_fields', uicfg.autoform_section),
       
    60                          ('set_field_kwargs', uicfg.autoform_field_kwargs),
       
    61                          ('set_field', uicfg.autoform_field),
       
    62                          ('edit_inline', uicfg.autoform_section),
       
    63                          ('edit_as_attr', uicfg.autoform_section),
       
    64                          ('set_muledit_editable', uicfg.autoform_section),
       
    65                          )
    68 
    66 
    69     `attr` can be a string or 2-tuple (relname, role_of_etype_in_the_relation)
    67 for funcname, tag in backward_compat_funcs:
    70 
    68     msg = ('[3.16] uihelper.%(name)s is deprecated, please use '
    71     """
    69            'web.uicfg.%(classname)s.%(name)s' % dict(
    72     _tag_rel(uicfg.actionbox_appearsin_addmenu, etype, attr, createdtype, True)
    70                name=funcname, classname=tag.__class__.__name__))
    73 
    71     globals()[funcname] = deprecated(msg)(getattr(tag, funcname))
    74 def remove_from_addmenu(etype, attr, createdtype='*'):
       
    75     """removes `attr` from the actions box *addrelated* submenu of `etype`.
       
    76 
       
    77     :param etype: the entity type as a string
       
    78     :param attr: the name of the attribute or relation to hide
       
    79 
       
    80     `attr` can be a string or 2-tuple (relname, role_of_etype_in_the_relation)
       
    81     """
       
    82     _tag_rel(uicfg.actionbox_appearsin_addmenu, etype, attr, createdtype, False)
       
    83 
       
    84 
       
    85 ## form uicfg helpers ##########################################################
       
    86 def set_fields_order(etype, attrs):
       
    87     """specify the field order in `etype` main edition form.
       
    88 
       
    89     :param etype: the entity type as a string
       
    90     :param attrs: the ordered list of attribute names (or relations)
       
    91 
       
    92     `attrs` can be strings or 2-tuples (relname, role_of_etype_in_the_relation)
       
    93 
       
    94     Unspecified fields will be displayed after specified ones, their
       
    95     order being consistent with the schema definition.
       
    96 
       
    97     Examples:
       
    98 
       
    99 .. sourcecode:: python
       
   100 
       
   101   from cubicweb.web import uihelper
       
   102   uihelper.set_fields_order('CWUser', ('firstname', 'surname', 'login'))
       
   103   uihelper.set_fields_order('CWUser', ('firstname', ('in_group', 'subject'), 'surname', 'login'))
       
   104 
       
   105     """
       
   106     afk = uicfg.autoform_field_kwargs
       
   107     for index, attr in enumerate(attrs):
       
   108         _tag_rel(afk, etype, attr, '*', {'order': index})
       
   109 
       
   110 
       
   111 def hide_field(etype, attr, desttype='*', formtype='main'):
       
   112     """hide `attr` in `etype` forms.
       
   113 
       
   114     :param etype: the entity type as a string
       
   115     :param attr: the name of the attribute or relation to hide
       
   116     :param formtype: which form will be affected ('main', 'inlined', etc.), *main* by default.
       
   117 
       
   118     `attr` can be a string or 2-tuple (relname, role_of_etype_in_the_relation)
       
   119 
       
   120     Examples:
       
   121 
       
   122 .. sourcecode:: python
       
   123 
       
   124   from cubicweb.web import uihelper
       
   125   uihelper.hide_field('CWUser', 'login')
       
   126   uihelper.hide_field('*', 'name')
       
   127   uihelper.hide_field('CWUser', 'use_email', formtype='inlined')
       
   128 
       
   129     """
       
   130     _tag_rel(uicfg.autoform_section, etype, attr, desttype,
       
   131              formtype=formtype, section='hidden')
       
   132 
       
   133 
       
   134 def hide_fields(etype, attrs, formtype='main'):
       
   135     """simple for-loop wrapper around :func:`hide_field`.
       
   136 
       
   137     :param etype: the entity type as a string
       
   138     :param attrs: the ordered list of attribute names (or relations)
       
   139     :param formtype: which form will be affected ('main', 'inlined', etc.), *main* by default.
       
   140 
       
   141     `attrs` can be strings or 2-tuples (relname, role_of_etype_in_the_relation)
       
   142 
       
   143     Examples:
       
   144 
       
   145 .. sourcecode:: python
       
   146 
       
   147   from cubicweb.web import uihelper
       
   148   uihelper.hide_fields('CWUser', ('login', ('use_email', 'subject')), formtype='inlined')
       
   149     """
       
   150     for attr in attrs:
       
   151         hide_field(etype, attr, formtype=formtype)
       
   152 
       
   153 
       
   154 def set_field_kwargs(etype, attr, **kwargs):
       
   155     """tag `attr` field of `etype` with additional named paremeters.
       
   156 
       
   157     :param etype: the entity type as a string
       
   158     :param attr: the name of the attribute or relation
       
   159 
       
   160     `attr` can be a string or 2-tuple (relname, role_of_etype_in_the_relation)
       
   161 
       
   162     Examples:
       
   163 
       
   164 .. sourcecode:: python
       
   165 
       
   166   from cubicweb.web import uihelper, formwidgets as fwdgs
       
   167 
       
   168   uihelper.set_field_kwargs('Person', 'works_for', widget=fwdgs.AutoCompletionWidget())
       
   169   uihelper.set_field_kwargs('CWUser', 'login', label=_('login or email address'),
       
   170                             widget=fwdgs.TextInput(attrs={'size': 30}))
       
   171     """
       
   172     _tag_rel(uicfg.autoform_field_kwargs, etype, attr, '*', kwargs)
       
   173 
       
   174 
       
   175 def set_field(etype, attr, field):
       
   176     """sets the `attr` field of `etype`.
       
   177 
       
   178     :param etype: the entity type as a string
       
   179     :param attr: the name of the attribute or relation
       
   180 
       
   181     `attr` can be a string or 2-tuple (relname, role_of_etype_in_the_relation)
       
   182 
       
   183     """
       
   184     _tag_rel(uicfg.autoform_field, etype, attr, '*', field)
       
   185 
       
   186 
       
   187 def edit_inline(etype, attr, desttype='*', formtype=('main', 'inlined')):
       
   188     """edit `attr` with and inlined form.
       
   189 
       
   190     :param etype: the entity type as a string
       
   191     :param attr: the name of the attribute or relation
       
   192     :param desttype: the destination type(s) concerned, default is everything
       
   193     :param formtype: which form will be affected ('main', 'inlined', etc.), *main* and *inlined* by default.
       
   194 
       
   195     `attr` can be a string or 2-tuple (relname, role_of_etype_in_the_relation)
       
   196 
       
   197     Examples:
       
   198 
       
   199 .. sourcecode:: python
       
   200 
       
   201   from cubicweb.web import uihelper
       
   202 
       
   203   uihelper.edit_inline('*', 'use_email')
       
   204   """
       
   205     _tag_rel(uicfg.autoform_section, etype, attr, desttype,
       
   206              formtype=formtype, section='inlined')
       
   207 
       
   208 
       
   209 def edit_as_attr(etype, attr, desttype='*', formtype=('main', 'muledit')):
       
   210     """make `attr` appear in the *attributes* section of `etype` form.
       
   211 
       
   212     :param etype: the entity type as a string
       
   213     :param attr: the name of the attribute or relation
       
   214     :param desttype: the destination type(s) concerned, default is everything
       
   215     :param formtype: which form will be affected ('main', 'inlined', etc.), *main* and *muledit* by default.
       
   216 
       
   217     `attr` can be a string or 2-tuple (relname, role_of_etype_in_the_relation)
       
   218 
       
   219     Examples:
       
   220 
       
   221 .. sourcecode:: python
       
   222 
       
   223   from cubicweb.web import uihelper
       
   224 
       
   225   uihelper.edit_as_attr('CWUser', 'in_group')
       
   226     """
       
   227     _tag_rel(uicfg.autoform_section, etype, attr, desttype,
       
   228              formtype=formtype, section='attributes')
       
   229 
       
   230 
       
   231 def set_muledit_editable(etype, attrs):
       
   232     """make `attrs` appear in muledit form of `etype`.
       
   233 
       
   234     :param etype: the entity type as a string
       
   235     :param attrs: the ordered list of attribute names (or relations)
       
   236 
       
   237     `attrs` can be strings or 2-tuples (relname, role_of_etype_in_the_relation)
       
   238 
       
   239     Examples:
       
   240 
       
   241 .. sourcecode:: python
       
   242 
       
   243   from cubicweb.web import uihelper
       
   244 
       
   245   uihelper.set_muledit_editable('CWUser', ('firstname', 'surname', 'in_group'))
       
   246     """
       
   247     for attr in attrs:
       
   248         edit_as_attr(etype, attr, formtype='muledit')
       
   249 
    72 
   250 
    73 
   251 class meta_formconfig(type):
    74 class meta_formconfig(type):
   252     """metaclass of FormConfig classes, only for easier declaration purpose"""
    75     """metaclass of FormConfig classes, only for easier declaration purpose"""
   253     def __init__(cls, name, bases, classdict):
    76     def __init__(cls, name, bases, classdict):
   254         if cls.etype is None:
    77         if cls.etype is None:
   255             return
    78             return
       
    79         if cls.uicfg_afs is None:
       
    80             uicfg_afs = uicfg.autoform_section
       
    81         if cls.uicfg_aff is None:
       
    82             uicfg_aff = uicfg.autoform_field
       
    83         if cls.uicfg_affk is None:
       
    84             uicfg_affk = uicfg.autoform_field_kwargs
   256         for attr_role in cls.hidden:
    85         for attr_role in cls.hidden:
   257             hide_field(cls.etype, attr_role, formtype=cls.formtype)
    86             uicfg_afs.hide_field(cls.etype, attr_role, formtype=cls.formtype)
   258         for attr_role in cls.rels_as_attrs:
    87         for attr_role in cls.rels_as_attrs:
   259             edit_as_attr(cls.etype, attr_role, formtype=cls.formtype)
    88             uicfg_afs.edit_as_attr(cls.etype, attr_role, formtype=cls.formtype)
   260         for attr_role in cls.inlined:
    89         for attr_role in cls.inlined:
   261             edit_inline(cls.etype, attr_role, formtype=cls.formtype)
    90             uicfg_afs.edit_inline(cls.etype, attr_role, formtype=cls.formtype)
   262         for rtype, widget in cls.widgets.items():
    91         for rtype, widget in cls.widgets.items():
   263             set_field_kwargs(cls.etype, rtype, widget=widget)
    92             uicfg_affk.set_field_kwargs(cls.etype, rtype, widget=widget)
   264         for rtype, field in cls.fields.items():
    93         for rtype, field in cls.fields.items():
   265             set_field(cls.etype, rtype, field)
    94             uicfg_aff.set_field(cls.etype, rtype, field)
   266         set_fields_order(cls.etype, cls.fields_order)
    95         uicfg_affk.set_fields_order(cls.etype, cls.fields_order)
   267         super(meta_formconfig, cls).__init__(name, bases, classdict)
    96         super(meta_formconfig, cls).__init__(name, bases, classdict)
   268 
    97 
   269 
    98 
   270 class FormConfig:
    99 class FormConfig:
   271     """helper base class to define uicfg rules on a given entity type.
   100     """helper base class to define uicfg rules on a given entity type.
   301       a dictionary mapping attribute names to widget instances.
   130       a dictionary mapping attribute names to widget instances.
   302 
   131 
   303     :attr:`fields`
   132     :attr:`fields`
   304       a dictionary mapping attribute names to field instances.
   133       a dictionary mapping attribute names to field instances.
   305 
   134 
       
   135     :attr:`uicfg_afs`
       
   136       an instance of ``cubicweb.web.uicfg.AutoformSectionRelationTags``
       
   137       Default is None, meaning ``cubicweb.web.uicfg.autoform_section`` is used.
       
   138 
       
   139     :attr:`uicfg_aff`
       
   140       an instance of ``cubicweb.web.uicfg.AutoformFieldTags``
       
   141       Default is None, meaning ``cubicweb.web.uicfg.autoform_field`` is used.
       
   142 
       
   143     :attr:`uicfg_affk`
       
   144       an instance of ``cubicweb.web.uicfg.AutoformFieldKwargsTags``
       
   145       Default is None, meaning ``cubicweb.web.uicfg.autoform_field_kwargs`` is used.
       
   146 
   306     Examples:
   147     Examples:
   307 
   148 
   308 .. sourcecode:: python
   149 .. sourcecode:: python
   309 
   150 
   310   from cubicweb.web import uihelper, formwidgets as fwdgs
   151   from cubicweb.web import uihelper, formwidgets as fwdgs
   331     rels_as_attrs = ()
   172     rels_as_attrs = ()
   332     inlined = ()
   173     inlined = ()
   333     fields_order = ()
   174     fields_order = ()
   334     widgets = {}
   175     widgets = {}
   335     fields = {}
   176     fields = {}
       
   177     uicfg_afs = None
       
   178     uicfg_aff = None
       
   179     uicfg_affk = None