[uicfg] uicfg.py moves from web/ to web/views/ (prepares #2406609)
We are about to make uicfg selectable. Registrable / selectable views
and helpers live in web/views. Hence the move.
Backward compat is put in place. However CubicWeb imports of uicfg are
updated to the new location.
--- a/devtools/devctl.py Thu Jan 10 13:03:38 2013 +0100
+++ b/devtools/devctl.py Thu Jan 10 18:34:10 2013 +0100
@@ -97,7 +97,7 @@
break
# fresh rtags
from cubicweb import rtags
- from cubicweb.web import uicfg
+ from cubicweb.web.views import uicfg
rtags.RTAGS[:] = []
reload(uicfg)
@@ -129,7 +129,7 @@
def _generate_schema_pot(w, vreg, schema, libconfig=None):
from copy import deepcopy
from cubicweb.i18n import add_msg
- from cubicweb.web import uicfg
+ from cubicweb.web.views import uicfg
from cubicweb.schema import NO_I18NCONTEXT, CONSTRAINTS
w('# schema pot file, generated on %s\n'
% datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
--- a/doc/book/en/devweb/views/boxes.rst Thu Jan 10 13:03:38 2013 +0100
+++ b/doc/book/en/devweb/views/boxes.rst Thu Jan 10 18:34:10 2013 +0100
@@ -15,7 +15,7 @@
which the box is displayed). By default, the links generated in this
box are computed from the schema properties of the displayed entity,
but it is possible to explicitly specify them thanks to the
-`cubicweb.web.uicfg.rmode` *relation tag*:
+`cubicweb.web.views.uicfg.rmode` *relation tag*:
* `link`, indicates that a relation is in general created pointing
to an existing entity and that we should not to display a link
--- a/doc/book/en/devweb/views/primary.rst Thu Jan 10 13:03:38 2013 +0100
+++ b/doc/book/en/devweb/views/primary.rst Thu Jan 10 18:34:10 2013 +0100
@@ -51,7 +51,7 @@
.. sourcecode:: python
- from cubicweb.web import uicfg
+ from cubicweb.web.views import uicfg
uicfg.primaryview_section.tag_attribute(('Blog', 'title'), 'hidden')
**Relations** can be either displayed in one of the three sections or hidden.
--- a/doc/book/en/devweb/views/reledit.rst Thu Jan 10 13:03:38 2013 +0100
+++ b/doc/book/en/devweb/views/reledit.rst Thu Jan 10 18:34:10 2013 +0100
@@ -68,7 +68,7 @@
The behaviour of reledited attributes/relations can be finely
controlled using the reledit_ctrl rtag, defined in
-:mod:`cubicweb.web.uicfg`.
+:mod:`cubicweb.web.views.uicfg`.
This rtag provides four control variables:
@@ -93,7 +93,7 @@
.. sourcecode:: python
from logilab.mtconverter import xml_escape
- from cubicweb.web.uicfg import reledit_ctrl
+ from cubicweb.web.views.uicfg import reledit_ctrl
reledit_ctrl.tag_attribute(('Company', 'name'),
{'reload': lambda x:x.eid,
'default_value': xml_escape(u'<logilab tastes better>')})
@@ -125,7 +125,7 @@
.. sourcecode:: python
- import uicfg.primaryview_display_ctrl as _pvdc
+ from cubicweb.web.views.uicfg import primaryview_display_ctrl as _pvdc
_pvdc.tag_attribute(('Company', 'name'), {'vid': 'incontext'})
To deactivate it everywhere it's used automatically, you may use the code snippet
--- a/doc/book/en/tutorials/advanced/part05_ui-advanced.rst Thu Jan 10 13:03:38 2013 +0100
+++ b/doc/book/en/tutorials/advanced/part05_ui-advanced.rst Thu Jan 10 18:34:10 2013 +0100
@@ -215,7 +215,7 @@
from logilab.common.decorators import monkeypatch
from cubicweb import ValidationError
- from cubicweb.web import uicfg, component
+ from cubicweb.web.views import uicfg, component
from cubicweb.web.views import basecontrollers
# hide displayed_on relation using uicfg since it will be displayed by the box below
--- a/web/formfields.py Thu Jan 10 13:03:38 2013 +0100
+++ b/web/formfields.py Thu Jan 10 18:34:10 2013 +0100
@@ -79,7 +79,8 @@
from cubicweb import Binary, tags, uilib
from cubicweb.utils import support_args
from cubicweb.web import INTERNAL_FIELD_VALUE, ProcessFormError, eid_param, \
- formwidgets as fw, uicfg
+ formwidgets as fw
+from cubicweb.web.views import uicfg
class UnmodifiedField(Exception):
--- a/web/test/unittest_formwidgets.py Thu Jan 10 13:03:38 2013 +0100
+++ b/web/test/unittest_formwidgets.py Thu Jan 10 18:34:10 2013 +0100
@@ -20,7 +20,7 @@
from logilab.common.testlib import TestCase, unittest_main, mock_object as mock
from cubicweb.devtools import TestServerConfiguration, fake
-from cubicweb.web import uicfg, formwidgets, formfields
+from cubicweb.web import formwidgets, formfields
from cubes.file.entities import File
--- a/web/test/unittest_reledit.py Thu Jan 10 13:03:38 2013 +0100
+++ b/web/test/unittest_reledit.py Thu Jan 10 18:34:10 2013 +0100
@@ -20,7 +20,7 @@
"""
from cubicweb.devtools.testlib import CubicWebTC
-from cubicweb.web.uicfg import reledit_ctrl
+from cubicweb.web.views.uicfg import reledit_ctrl
class ReleditMixinTC(object):
--- a/web/test/unittest_uicfg.py Thu Jan 10 13:03:38 2013 +0100
+++ b/web/test/unittest_uicfg.py Thu Jan 10 18:34:10 2013 +0100
@@ -18,7 +18,8 @@
import copy
from logilab.common.testlib import tag
from cubicweb.devtools.testlib import CubicWebTC
-from cubicweb.web import uicfg, uihelper, formwidgets as fwdgs
+from cubicweb.web import uihelper, formwidgets as fwdgs
+from cubicweb.web.views import uicfg
abaa = uicfg.actionbox_appearsin_addmenu
--- a/web/test/unittest_views_editforms.py Thu Jan 10 13:03:38 2013 +0100
+++ b/web/test/unittest_views_editforms.py Thu Jan 10 18:34:10 2013 +0100
@@ -22,7 +22,7 @@
from logilab.common.compat import any
from cubicweb.devtools.testlib import CubicWebTC
-from cubicweb.web import uicfg
+from cubicweb.web.views import uicfg
from cubicweb.web.formwidgets import AutoCompletionWidget
AFFK = uicfg.autoform_field_kwargs
--- a/web/uicfg.py Thu Jan 10 13:03:38 2013 +0100
+++ b/web/uicfg.py Thu Jan 10 18:34:10 2013 +0100
@@ -15,422 +15,15 @@
#
# You should have received a copy of the GNU Lesser General Public License along
# with CubicWeb. If not, see <http://www.gnu.org/licenses/>.
-"""This module (``cubicweb.web.uicfg``) regroups a set of structures that may be
-used to configure various options of the generated web interface.
-
-To configure the interface generation, we use ``RelationTag`` objects.
-
-Index view configuration
-````````````````````````
-:indexview_etype_section:
- entity type category in the index/manage page. May be one of:
-
- * ``application``
- * ``system``
- * ``schema``
- * ``subobject`` (not displayed by default)
-
- By default only entities on the ``application`` category are shown.
-
-.. sourcecode:: python
-
- from cubicweb.web import uicfg
- # force hiding
- uicfg.indexview_etype_section['HideMe'] = 'subobject'
- # force display
- uicfg.indexview_etype_section['ShowMe'] = 'application'
-
-
-Actions box configuration
-`````````````````````````
-:actionbox_appearsin_addmenu:
- simple boolean relation tags used to control the "add entity" submenu.
- Relations whose rtag is True will appears, other won't.
-
-.. sourcecode:: python
-
- # Adds all subjects of the entry_of relation in the add menu of the ``Blog``
- # primary view
- uicfg.actionbox_appearsin_addmenu.tag_object_of(('*', 'entry_of', 'Blog'), True)
+"""
+This module is now deprecated, see web.views.uicfg.
"""
__docformat__ = "restructuredtext en"
from warnings import warn
-
-from logilab.common.compat import any
-
-from cubicweb import neg_role
-from cubicweb.rtags import (RelationTags, RelationTagsBool, RelationTagsSet,
- RelationTagsDict, NoTargetRelationTagsDict,
- register_rtag, _ensure_str_key)
-from cubicweb.schema import META_RTYPES, INTERNAL_TYPES, WORKFLOW_TYPES
-
-
-# primary view configuration ##################################################
-
-def init_primaryview_section(rtag, sschema, rschema, oschema, role):
- if rtag.get(sschema, rschema, oschema, role) is None:
- rdef = rschema.rdef(sschema, oschema)
- if rschema.final:
- if rschema.meta or sschema.is_metadata(rschema) \
- or oschema.type in ('Password', 'Bytes'):
- section = 'hidden'
- else:
- section = 'attributes'
- else:
- if rdef.role_cardinality(role) in '1+':
- section = 'attributes'
- elif rdef.composite == neg_role(role):
- section = 'relations'
- else:
- section = 'sideboxes'
- rtag.tag_relation((sschema, rschema, oschema, role), section)
-
-primaryview_section = RelationTags('primaryview_section',
- init_primaryview_section,
- frozenset(('attributes', 'relations',
- 'sideboxes', 'hidden')))
-
-
-class DisplayCtrlRelationTags(NoTargetRelationTagsDict):
- def __init__(self, *args, **kwargs):
- super(DisplayCtrlRelationTags, self).__init__(*args, **kwargs)
- self.counter = 0
-
-def init_primaryview_display_ctrl(rtag, sschema, rschema, oschema, role):
- if role == 'subject':
- oschema = '*'
- else:
- sschema = '*'
- rtag.counter += 1
- rtag.setdefault((sschema, rschema, oschema, role), 'order', rtag.counter)
-
-primaryview_display_ctrl = DisplayCtrlRelationTags('primaryview_display_ctrl',
- init_primaryview_display_ctrl)
+from cubicweb.web.views.uicfg import *
-# index view configuration ####################################################
-# entity type section in the index/manage page. May be one of
-# * 'application'
-# * 'system'
-# * 'schema'
-# * 'hidden'
-# * 'subobject' (not displayed by default)
-
-class InitializableDict(dict):
- def __init__(self, *args, **kwargs):
- super(InitializableDict, self).__init__(*args, **kwargs)
- register_rtag(self)
- self.__defaults = dict(self)
-
- def init(self, schema, check=True):
- self.update(self.__defaults)
- for eschema in schema.entities():
- if eschema.final:
- continue
- if eschema.schema_entity():
- self.setdefault(eschema, 'schema')
- elif eschema in INTERNAL_TYPES or eschema in WORKFLOW_TYPES:
- self.setdefault(eschema, 'system')
- elif eschema.is_subobject(strict=True):
- self.setdefault(eschema, 'subobject')
- else:
- self.setdefault(eschema, 'application')
-
-indexview_etype_section = InitializableDict(
- EmailAddress='subobject',
- Bookmark='system',
- # entity types in the 'system' table by default (managers only)
- CWUser='system', CWGroup='system',
- )
-
-# autoform.AutomaticEntityForm configuration ##################################
-
-def _formsections_as_dict(formsections):
- result = {}
- for formsection in formsections:
- formtype, section = formsection.split('_', 1)
- result[formtype] = section
- return result
-
-def _card_and_comp(sschema, rschema, oschema, role):
- rdef = rschema.rdef(sschema, oschema)
- if role == 'subject':
- card = rdef.cardinality[0]
- composed = not rschema.final and rdef.composite == 'object'
- else:
- card = rdef.cardinality[1]
- composed = not rschema.final and rdef.composite == 'subject'
- return card, composed
-
-class AutoformSectionRelationTags(RelationTagsSet):
- """autoform relations'section"""
-
- _allowed_form_types = ('main', 'inlined', 'muledit')
- _allowed_values = {'main': ('attributes', 'inlined', 'relations',
- 'metadata', 'hidden'),
- 'inlined': ('attributes', 'inlined', 'hidden'),
- 'muledit': ('attributes', 'hidden'),
- }
-
- def init(self, schema, check=True):
- super(AutoformSectionRelationTags, self).init(schema, check)
- self.apply(schema, self._initfunc_step2)
-
- @staticmethod
- def _initfunc(self, sschema, rschema, oschema, role):
- formsections = self.init_get(sschema, rschema, oschema, role)
- if formsections is None:
- formsections = self.tag_container_cls()
- if not any(tag.startswith('inlined') for tag in formsections):
- if not rschema.final:
- negsects = self.init_get(sschema, rschema, oschema, neg_role(role))
- if 'main_inlined' in negsects:
- formsections.add('inlined_hidden')
- key = _ensure_str_key( (sschema, rschema, oschema, role) )
- self._tagdefs[key] = formsections
-
- @staticmethod
- def _initfunc_step2(self, sschema, rschema, oschema, role):
- formsections = self.get(sschema, rschema, oschema, role)
- sectdict = _formsections_as_dict(formsections)
- if rschema in META_RTYPES:
- sectdict.setdefault('main', 'hidden')
- sectdict.setdefault('muledit', 'hidden')
- sectdict.setdefault('inlined', 'hidden')
- elif role == 'subject' and rschema in sschema.meta_attributes():
- # meta attribute, usually embeded by the described attribute's field
- # (eg RichTextField, FileField...)
- sectdict.setdefault('main', 'hidden')
- sectdict.setdefault('muledit', 'hidden')
- sectdict.setdefault('inlined', 'hidden')
- # ensure we have a tag for each form type
- if not 'main' in sectdict:
- if not rschema.final and (
- sectdict.get('inlined') == 'attributes' or
- 'inlined_attributes' in self.init_get(sschema, rschema, oschema,
- neg_role(role))):
- sectdict['main'] = 'hidden'
- elif sschema.is_metadata(rschema):
- sectdict['main'] = 'metadata'
- else:
- card, composed = _card_and_comp(sschema, rschema, oschema, role)
- if card in '1+':
- sectdict['main'] = 'attributes'
- if not 'muledit' in sectdict:
- sectdict['muledit'] = 'attributes'
- elif rschema.final:
- sectdict['main'] = 'attributes'
- else:
- sectdict['main'] = 'relations'
- if not 'muledit' in sectdict:
- sectdict['muledit'] = 'hidden'
- if sectdict['main'] == 'attributes':
- card, composed = _card_and_comp(sschema, rschema, oschema, role)
- if card in '1+' and not composed:
- sectdict['muledit'] = 'attributes'
- if not 'inlined' in sectdict:
- sectdict['inlined'] = sectdict['main']
- # recompute formsections and set it to avoid recomputing
- for formtype, section in sectdict.iteritems():
- formsections.add('%s_%s' % (formtype, section))
-
- def tag_relation(self, key, formtype, section):
- if isinstance(formtype, tuple):
- for ftype in formtype:
- self.tag_relation(key, ftype, section)
- return
- assert formtype in self._allowed_form_types, \
- 'formtype should be in (%s), not %s' % (
- ','.join(self._allowed_form_types), formtype)
- assert section in self._allowed_values[formtype], \
- 'section for %s should be in (%s), not %s' % (
- formtype, ','.join(self._allowed_values[formtype]), section)
- rtags = self._tagdefs.setdefault(_ensure_str_key(key),
- self.tag_container_cls())
- # remove previous section for this form type if any
- if rtags:
- for tag in rtags.copy():
- if tag.startswith(formtype):
- rtags.remove(tag)
- rtags.add('%s_%s' % (formtype, section))
- return rtags
-
- def init_get(self, stype, rtype, otype, tagged):
- key = (stype, rtype, otype, tagged)
- rtags = {}
- for key in self._get_keys(stype, rtype, otype, tagged):
- tags = self._tagdefs.get(key, ())
- for tag in tags:
- assert '_' in tag, (tag, tags)
- section, value = tag.split('_', 1)
- rtags[section] = value
- cls = self.tag_container_cls
- rtags = cls('_'.join([section,value]) for section,value in rtags.iteritems())
- return rtags
-
+warn('[3.16] moved to cubicweb.web.views.uicfg',
+ DeprecationWarning, stacklevel=2)
- def get(self, *key):
- # overriden to avoid recomputing done in parent classes
- return self._tagdefs.get(key, ())
-
- def relations_by_section(self, entity, formtype, section, permission,
- strict=False):
- """return a list of (relation schema, target schemas, role) for the
- given entity matching categories and permission.
-
- `strict`:
- bool telling if having local role is enough (strict = False) or not
- """
- tag = '%s_%s' % (formtype, section)
- eschema = entity.e_schema
- permsoverrides = autoform_permissions_overrides
- if entity.has_eid():
- eid = entity.eid
- else:
- eid = None
- strict = False
- if permission == 'update':
- assert section in ('attributes', 'metadata', 'hidden')
- relpermission = 'add'
- else:
- assert section not in ('attributes', 'metadata', 'hidden')
- relpermission = permission
- cw = entity._cw
- for rschema, targetschemas, role in eschema.relation_definitions(True):
- _targetschemas = []
- for tschema in targetschemas:
- # check section's tag first, potentially lower cost than
- # checking permission which may imply rql queries
- if not tag in self.etype_get(eschema, rschema, role, tschema):
- continue
- rdef = rschema.role_rdef(eschema, tschema, role)
- if rschema.final:
- if not rdef.has_perm(cw, permission, eid=eid,
- creating=eid is None):
- continue
- elif strict or not rdef.has_local_role(relpermission):
- if role == 'subject':
- if not rdef.has_perm(cw, relpermission, fromeid=eid):
- continue
- elif role == 'object':
- if not rdef.has_perm(cw, relpermission, toeid=eid):
- continue
- _targetschemas.append(tschema)
- if not _targetschemas:
- continue
- targetschemas = _targetschemas
- rdef = eschema.rdef(rschema, role=role, targettype=targetschemas[0])
- # XXX tag allowing to hijack the permission machinery when
- # permission is not verifiable until the entity is actually
- # created...
- if eid is None and '%s_on_new' % permission in permsoverrides.etype_get(eschema, rschema, role):
- yield (rschema, targetschemas, role)
- continue
- if not rschema.final and role == 'subject':
- # on relation with cardinality 1 or ?, we need delete perm as well
- # if the relation is already set
- if (relpermission == 'add'
- and rdef.role_cardinality(role) in '1?'
- and eid and entity.related(rschema.type, role)
- and not rdef.has_perm(cw, 'delete', fromeid=eid,
- toeid=entity.related(rschema.type, role)[0][0])):
- continue
- elif role == 'object':
- # on relation with cardinality 1 or ?, we need delete perm as well
- # if the relation is already set
- if (relpermission == 'add'
- and rdef.role_cardinality(role) in '1?'
- and eid and entity.related(rschema.type, role)
- and not rdef.has_perm(cw, 'delete', toeid=eid,
- fromeid=entity.related(rschema.type, role)[0][0])):
- continue
- yield (rschema, targetschemas, role)
-
-autoform_section = AutoformSectionRelationTags('autoform_section')
-
-# relations'field class
-autoform_field = RelationTags('autoform_field')
-
-# relations'field explicit kwargs (given to field's __init__)
-autoform_field_kwargs = RelationTagsDict('autoform_field_kwargs')
-
-
-# set of tags of the form <action>_on_new on relations. <action> is a
-# schema action (add/update/delete/read), and when such a tag is found
-# permissions checking is by-passed and supposed to be ok
-autoform_permissions_overrides = RelationTagsSet('autoform_permissions_overrides')
-
-class ReleditTags(NoTargetRelationTagsDict):
- """Associate to relation a dictionary to control `reledit` (e.g. edition of
- attributes / relations from within views).
-
- Possible keys and associated values are:
-
- * `novalue_label`, alternative default value (shown when there is no value).
-
- * `novalue_include_rtype`, when `novalue_label` is not specified, this boolean
- flag control wether the generated default value should contains the
- relation label or not. Will be the opposite of the `showlabel` value found
- in the `primaryview_display_ctrl` rtag by default.
-
- * `reload`, boolean, eid (to reload to) or function taking subject and
- returning bool/eid. This is useful when editing a relation (or attribute)
- that impacts the url or another parts of the current displayed
- page. Defaults to False.
-
- * `rvid`, alternative view id (as str) for relation or composite edition.
- Default is 'autolimited'.
-
- * `edit_target`, may be either 'rtype' (to edit the relation) or 'related'
- (to edit the related entity). This controls whether to edit the relation
- or the target entity of the relation. Currently only one-to-one relations
- support target entity edition. By default, the 'related' option is taken
- whenever the relation is composite.
- """
- _keys = frozenset('novalue_label novalue_include_rtype reload rvid edit_target'.split())
-
- def tag_relation(self, key, tag):
- for tagkey in tag.iterkeys():
- assert tagkey in self._keys, 'tag %r not in accepted tags: %r' % (tag, self._keys)
- return super(ReleditTags, self).tag_relation(key, tag)
-
-def init_reledit_ctrl(rtag, sschema, rschema, oschema, role):
- values = rtag.get(sschema, rschema, oschema, role)
- if not rschema.final:
- composite = rschema.rdef(sschema, oschema).composite == role
- if role == 'subject':
- oschema = '*'
- else:
- sschema = '*'
- edittarget = values.get('edit_target')
- if edittarget not in (None, 'rtype', 'related'):
- rtag.warning('reledit: wrong value for edit_target on relation %s: %s',
- rschema, edittarget)
- edittarget = None
- if not edittarget:
- edittarget = 'related' if composite else 'rtype'
- rtag.tag_relation((sschema, rschema, oschema, role),
- {'edit_target': edittarget})
- if not 'novalue_include_rtype' in values:
- showlabel = primaryview_display_ctrl.get(
- sschema, rschema, oschema, role).get('showlabel', True)
- rtag.tag_relation((sschema, rschema, oschema, role),
- {'novalue_include_rtype': not showlabel})
-
-reledit_ctrl = ReleditTags('reledit', init_reledit_ctrl)
-
-# boxes.EditBox configuration #################################################
-
-# 'link' / 'create' relation tags, used to control the "add entity" submenu
-def init_actionbox_appearsin_addmenu(rtag, sschema, rschema, oschema, role):
- if rtag.get(sschema, rschema, oschema, role) is None:
- if rschema in META_RTYPES:
- rtag.tag_relation((sschema, rschema, oschema, role), False)
- return
- rdef = rschema.rdef(sschema, oschema)
- if not rdef.role_cardinality(role) in '?1' and rdef.composite == role:
- rtag.tag_relation((sschema, rschema, oschema, role), True)
-
-actionbox_appearsin_addmenu = RelationTagsBool('actionbox_appearsin_addmenu',
- init_actionbox_appearsin_addmenu)
--- a/web/uihelper.py Thu Jan 10 13:03:38 2013 +0100
+++ b/web/uihelper.py Thu Jan 10 18:34:10 2013 +0100
@@ -45,7 +45,7 @@
"""
__docformat__ = "restructuredtext en"
-from cubicweb.web import uicfg
+from cubicweb.web.views import uicfg
from functools import partial
def _tag_rel(rtag, etype, attr, desttype='*', *args, **kwargs):
--- a/web/views/actions.py Thu Jan 10 13:03:38 2013 +0100
+++ b/web/views/actions.py Thu Jan 10 18:34:10 2013 +0100
@@ -32,8 +32,8 @@
authenticated_user, match_user_groups, match_search_state,
has_permission, has_add_permission, is_instance, debug_mode,
)
-from cubicweb.web import uicfg, controller, action
-from cubicweb.web.views import linksearch_select_url, vid_from_rset
+from cubicweb.web import controller, action
+from cubicweb.web.views import uicfg, linksearch_select_url, vid_from_rset
class has_editable_relation(EntityPredicate):
--- a/web/views/autoform.py Thu Jan 10 13:03:38 2013 +0100
+++ b/web/views/autoform.py Thu Jan 10 18:34:10 2013 +0100
@@ -135,9 +135,9 @@
match_kwargs, match_form_params, non_final_entity,
specified_etype_implements)
from cubicweb.utils import json_dumps
-from cubicweb.web import (stdmsgs, uicfg, eid_param,
+from cubicweb.web import (stdmsgs, eid_param,
form as f, formwidgets as fw, formfields as ff)
-from cubicweb.web.views import forms
+from cubicweb.web.views import uicfg, forms
from cubicweb.web.views.ajaxcontroller import ajaxfunc
_AFS = uicfg.autoform_section
--- a/web/views/basecomponents.py Thu Jan 10 13:03:38 2013 +0100
+++ b/web/views/basecomponents.py Thu Jan 10 18:34:10 2013 +0100
@@ -36,7 +36,7 @@
from cubicweb.schema import display_name
from cubicweb.utils import wrap_on_write
from cubicweb.uilib import toggle_action
-from cubicweb.web import component, uicfg
+from cubicweb.web import component
from cubicweb.web.htmlwidgets import MenuWidget, PopupBoxMenu
VISIBLE_PROP_DEF = {
--- a/web/views/bookmark.py Thu Jan 10 13:03:38 2013 +0100
+++ b/web/views/bookmark.py Thu Jan 10 18:34:10 2013 +0100
@@ -24,9 +24,8 @@
from cubicweb import Unauthorized, typed_eid
from cubicweb.predicates import is_instance, one_line_rset
-from cubicweb.web import (action, component, uicfg, htmlwidgets,
- formwidgets as fw)
-from cubicweb.web.views import primary
+from cubicweb.web import action, component, htmlwidgets, formwidgets as fw
+from cubicweb.web.views import uicfg, primary
from cubicweb.web.views.ajaxcontroller import ajaxfunc
_abaa = uicfg.actionbox_appearsin_addmenu
--- a/web/views/cwproperties.py Thu Jan 10 13:03:38 2013 +0100
+++ b/web/views/cwproperties.py Thu Jan 10 18:34:10 2013 +0100
@@ -28,12 +28,12 @@
from cubicweb.predicates import (one_line_rset, none_rset, is_instance,
match_user_groups, logged_user_in_rset)
from cubicweb.view import StartupView
-from cubicweb.web import uicfg, stdmsgs
+from cubicweb.web import stdmsgs
from cubicweb.web.form import FormViewMixIn
from cubicweb.web.formfields import FIELDS, StringField
from cubicweb.web.formwidgets import (Select, TextInput, Button, SubmitButton,
FieldWidget)
-from cubicweb.web.views import primary, formrenderers, editcontroller
+from cubicweb.web.views import uicfg, primary, formrenderers, editcontroller
from cubicweb.web.views.ajaxcontroller import ajaxfunc
uicfg.primaryview_section.tag_object_of(('*', 'for_user', '*'), 'hidden')
--- a/web/views/cwsources.py Thu Jan 10 13:03:38 2013 +0100
+++ b/web/views/cwsources.py Thu Jan 10 18:34:10 2013 +0100
@@ -1,4 +1,4 @@
-# copyright 2010-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# copyright 2010-2012 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
#
# This file is part of CubicWeb.
@@ -33,9 +33,9 @@
match_user_groups, match_kwargs, match_view)
from cubicweb.view import EntityView, StartupView
from cubicweb.schema import META_RTYPES, VIRTUAL_RTYPES, display_name
-from cubicweb.web import uicfg, formwidgets as wdgs, facet
+from cubicweb.web import formwidgets as wdgs, facet
from cubicweb.web.views import add_etype_button
-from cubicweb.web.views import (tabs, actions, ibreadcrumbs, navigation,
+from cubicweb.web.views import (uicfg, tabs, actions, ibreadcrumbs, navigation,
tableview, pyviews)
--- a/web/views/cwuser.py Thu Jan 10 13:03:38 2013 +0100
+++ b/web/views/cwuser.py Thu Jan 10 18:34:10 2013 +0100
@@ -28,8 +28,8 @@
from cubicweb.schema import display_name
from cubicweb.predicates import one_line_rset, is_instance, match_user_groups
from cubicweb.view import EntityView, StartupView
-from cubicweb.web import action, uicfg, formwidgets
-from cubicweb.web.views import tabs, tableview, actions, add_etype_button
+from cubicweb.web import action, formwidgets
+from cubicweb.web.views import uicfg, tabs, tableview, actions, add_etype_button
_pvs = uicfg.primaryview_section
_pvs.tag_attribute(('CWUser', 'login'), 'hidden')
--- a/web/views/editforms.py Thu Jan 10 13:03:38 2013 +0100
+++ b/web/views/editforms.py Thu Jan 10 18:34:10 2013 +0100
@@ -34,10 +34,10 @@
specified_etype_implements, is_instance)
from cubicweb.view import EntityView
from cubicweb.schema import display_name
-from cubicweb.web import uicfg, stdmsgs, eid_param, \
+from cubicweb.web import stdmsgs, eid_param, \
formfields as ff, formwidgets as fw
from cubicweb.web.form import FormViewMixIn, FieldNotFound
-from cubicweb.web.views import forms, reledit
+from cubicweb.web.views import uicfg, forms, reledit
_pvdc = uicfg.primaryview_display_ctrl
--- a/web/views/emailaddress.py Thu Jan 10 13:03:38 2013 +0100
+++ b/web/views/emailaddress.py Thu Jan 10 18:34:10 2013 +0100
@@ -24,8 +24,7 @@
from cubicweb.schema import display_name
from cubicweb.predicates import is_instance
from cubicweb import Unauthorized
-from cubicweb.web import uicfg
-from cubicweb.web.views import baseviews, primary, ibreadcrumbs
+from cubicweb.web.views import uicfg, baseviews, primary, ibreadcrumbs
_pvs = uicfg.primaryview_section
_pvs.tag_subject_of(('*', 'use_email', '*'), 'attributes')
--- a/web/views/forms.py Thu Jan 10 13:03:38 2013 +0100
+++ b/web/views/forms.py Thu Jan 10 18:34:10 2013 +0100
@@ -56,7 +56,8 @@
from cubicweb.utils import support_args
from cubicweb.predicates import non_final_entity, match_kwargs, one_line_rset
from cubicweb.web import RequestError, ProcessFormError
-from cubicweb.web import uicfg, form, formwidgets as fwdgs
+from cubicweb.web import form, formwidgets as fwdgs
+from cubicweb.web.views import uicfg
from cubicweb.web.formfields import guess_field
--- a/web/views/primary.py Thu Jan 10 13:03:38 2013 +0100
+++ b/web/views/primary.py Thu Jan 10 18:34:10 2013 +0100
@@ -50,7 +50,8 @@
from cubicweb.predicates import match_kwargs, match_context
from cubicweb.view import EntityView
from cubicweb.schema import META_RTYPES, VIRTUAL_RTYPES, display_name
-from cubicweb.web import uicfg, component
+from cubicweb.web import component
+from cubicweb.web.views import uicfg
class PrimaryView(EntityView):
--- a/web/views/reledit.py Thu Jan 10 13:03:38 2013 +0100
+++ b/web/views/reledit.py Thu Jan 10 18:34:10 2013 +0100
@@ -34,7 +34,8 @@
from cubicweb.utils import json, json_dumps
from cubicweb.predicates import non_final_entity, match_kwargs
from cubicweb.view import EntityView
-from cubicweb.web import uicfg, stdmsgs
+from cubicweb.web import stdmsgs
+from cubicweb.web.views import uicfg
from cubicweb.web.form import FieldNotFound
from cubicweb.web.formwidgets import Button, SubmitButton
from cubicweb.web.views.ajaxcontroller import ajaxfunc
--- a/web/views/schema.py Thu Jan 10 13:03:38 2013 +0100
+++ b/web/views/schema.py Thu Jan 10 18:34:10 2013 +0100
@@ -39,9 +39,9 @@
from cubicweb.utils import make_uid
from cubicweb.view import EntityView, StartupView
from cubicweb import tags, uilib
-from cubicweb.web import action, facet, uicfg, schemaviewer
+from cubicweb.web import action, facet, schemaviewer
from cubicweb.web.views import TmpFileViewMixin
-from cubicweb.web.views import primary, baseviews, tabs, tableview, ibreadcrumbs
+from cubicweb.web.views import uicfg, primary, baseviews, tabs, tableview, ibreadcrumbs
ALWAYS_SKIP_TYPES = BASE_TYPES | SCHEMA_TYPES
SKIP_TYPES = (ALWAYS_SKIP_TYPES | META_RTYPES | SYSTEM_RTYPES | WORKFLOW_TYPES
--- a/web/views/startup.py Thu Jan 10 13:03:38 2013 +0100
+++ b/web/views/startup.py Thu Jan 10 18:34:10 2013 +0100
@@ -31,7 +31,8 @@
from cubicweb.view import StartupView
from cubicweb.predicates import match_user_groups, is_instance
from cubicweb.schema import display_name
-from cubicweb.web import uicfg, httpcache
+from cubicweb.web import httpcache
+from cubicweb.web.views import uicfg
class ManageView(StartupView):
""":__regid__: *manage*
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/web/views/uicfg.py Thu Jan 10 18:34:10 2013 +0100
@@ -0,0 +1,436 @@
+# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
+#
+# This file is part of CubicWeb.
+#
+# CubicWeb is free software: you can redistribute it and/or modify it under the
+# terms of the GNU Lesser General Public License as published by the Free
+# Software Foundation, either version 2.1 of the License, or (at your option)
+# any later version.
+#
+# CubicWeb is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+# details.
+#
+# You should have received a copy of the GNU Lesser General Public License along
+# with CubicWeb. If not, see <http://www.gnu.org/licenses/>.
+"""This module (``cubicweb.web.uicfg``) regroups a set of structures that may be
+used to configure various options of the generated web interface.
+
+To configure the interface generation, we use ``RelationTag`` objects.
+
+Index view configuration
+````````````````````````
+:indexview_etype_section:
+ entity type category in the index/manage page. May be one of:
+
+ * ``application``
+ * ``system``
+ * ``schema``
+ * ``subobject`` (not displayed by default)
+
+ By default only entities on the ``application`` category are shown.
+
+.. sourcecode:: python
+
+ from cubicweb.web import uicfg
+ # force hiding
+ uicfg.indexview_etype_section['HideMe'] = 'subobject'
+ # force display
+ uicfg.indexview_etype_section['ShowMe'] = 'application'
+
+
+Actions box configuration
+`````````````````````````
+:actionbox_appearsin_addmenu:
+ simple boolean relation tags used to control the "add entity" submenu.
+ Relations whose rtag is True will appears, other won't.
+
+.. sourcecode:: python
+
+ # Adds all subjects of the entry_of relation in the add menu of the ``Blog``
+ # primary view
+ uicfg.actionbox_appearsin_addmenu.tag_object_of(('*', 'entry_of', 'Blog'), True)
+"""
+__docformat__ = "restructuredtext en"
+
+from warnings import warn
+
+from logilab.common.compat import any
+
+from cubicweb import neg_role
+from cubicweb.rtags import (RelationTags, RelationTagsBool, RelationTagsSet,
+ RelationTagsDict, NoTargetRelationTagsDict,
+ register_rtag, _ensure_str_key)
+from cubicweb.schema import META_RTYPES, INTERNAL_TYPES, WORKFLOW_TYPES
+
+
+# primary view configuration ##################################################
+
+def init_primaryview_section(rtag, sschema, rschema, oschema, role):
+ if rtag.get(sschema, rschema, oschema, role) is None:
+ rdef = rschema.rdef(sschema, oschema)
+ if rschema.final:
+ if rschema.meta or sschema.is_metadata(rschema) \
+ or oschema.type in ('Password', 'Bytes'):
+ section = 'hidden'
+ else:
+ section = 'attributes'
+ else:
+ if rdef.role_cardinality(role) in '1+':
+ section = 'attributes'
+ elif rdef.composite == neg_role(role):
+ section = 'relations'
+ else:
+ section = 'sideboxes'
+ rtag.tag_relation((sschema, rschema, oschema, role), section)
+
+primaryview_section = RelationTags('primaryview_section',
+ init_primaryview_section,
+ frozenset(('attributes', 'relations',
+ 'sideboxes', 'hidden')))
+
+
+class DisplayCtrlRelationTags(NoTargetRelationTagsDict):
+ def __init__(self, *args, **kwargs):
+ super(DisplayCtrlRelationTags, self).__init__(*args, **kwargs)
+ self.counter = 0
+
+def init_primaryview_display_ctrl(rtag, sschema, rschema, oschema, role):
+ if role == 'subject':
+ oschema = '*'
+ else:
+ sschema = '*'
+ rtag.counter += 1
+ rtag.setdefault((sschema, rschema, oschema, role), 'order', rtag.counter)
+
+primaryview_display_ctrl = DisplayCtrlRelationTags('primaryview_display_ctrl',
+ init_primaryview_display_ctrl)
+
+
+# index view configuration ####################################################
+# entity type section in the index/manage page. May be one of
+# * 'application'
+# * 'system'
+# * 'schema'
+# * 'hidden'
+# * 'subobject' (not displayed by default)
+
+class InitializableDict(dict):
+ def __init__(self, *args, **kwargs):
+ super(InitializableDict, self).__init__(*args, **kwargs)
+ register_rtag(self)
+ self.__defaults = dict(self)
+
+ def init(self, schema, check=True):
+ self.update(self.__defaults)
+ for eschema in schema.entities():
+ if eschema.final:
+ continue
+ if eschema.schema_entity():
+ self.setdefault(eschema, 'schema')
+ elif eschema in INTERNAL_TYPES or eschema in WORKFLOW_TYPES:
+ self.setdefault(eschema, 'system')
+ elif eschema.is_subobject(strict=True):
+ self.setdefault(eschema, 'subobject')
+ else:
+ self.setdefault(eschema, 'application')
+
+indexview_etype_section = InitializableDict(
+ EmailAddress='subobject',
+ Bookmark='system',
+ # entity types in the 'system' table by default (managers only)
+ CWUser='system', CWGroup='system',
+ )
+
+# autoform.AutomaticEntityForm configuration ##################################
+
+def _formsections_as_dict(formsections):
+ result = {}
+ for formsection in formsections:
+ formtype, section = formsection.split('_', 1)
+ result[formtype] = section
+ return result
+
+def _card_and_comp(sschema, rschema, oschema, role):
+ rdef = rschema.rdef(sschema, oschema)
+ if role == 'subject':
+ card = rdef.cardinality[0]
+ composed = not rschema.final and rdef.composite == 'object'
+ else:
+ card = rdef.cardinality[1]
+ composed = not rschema.final and rdef.composite == 'subject'
+ return card, composed
+
+class AutoformSectionRelationTags(RelationTagsSet):
+ """autoform relations'section"""
+
+ _allowed_form_types = ('main', 'inlined', 'muledit')
+ _allowed_values = {'main': ('attributes', 'inlined', 'relations',
+ 'metadata', 'hidden'),
+ 'inlined': ('attributes', 'inlined', 'hidden'),
+ 'muledit': ('attributes', 'hidden'),
+ }
+
+ def init(self, schema, check=True):
+ super(AutoformSectionRelationTags, self).init(schema, check)
+ self.apply(schema, self._initfunc_step2)
+
+ @staticmethod
+ def _initfunc(self, sschema, rschema, oschema, role):
+ formsections = self.init_get(sschema, rschema, oschema, role)
+ if formsections is None:
+ formsections = self.tag_container_cls()
+ if not any(tag.startswith('inlined') for tag in formsections):
+ if not rschema.final:
+ negsects = self.init_get(sschema, rschema, oschema, neg_role(role))
+ if 'main_inlined' in negsects:
+ formsections.add('inlined_hidden')
+ key = _ensure_str_key( (sschema, rschema, oschema, role) )
+ self._tagdefs[key] = formsections
+
+ @staticmethod
+ def _initfunc_step2(self, sschema, rschema, oschema, role):
+ formsections = self.get(sschema, rschema, oschema, role)
+ sectdict = _formsections_as_dict(formsections)
+ if rschema in META_RTYPES:
+ sectdict.setdefault('main', 'hidden')
+ sectdict.setdefault('muledit', 'hidden')
+ sectdict.setdefault('inlined', 'hidden')
+ elif role == 'subject' and rschema in sschema.meta_attributes():
+ # meta attribute, usually embeded by the described attribute's field
+ # (eg RichTextField, FileField...)
+ sectdict.setdefault('main', 'hidden')
+ sectdict.setdefault('muledit', 'hidden')
+ sectdict.setdefault('inlined', 'hidden')
+ # ensure we have a tag for each form type
+ if not 'main' in sectdict:
+ if not rschema.final and (
+ sectdict.get('inlined') == 'attributes' or
+ 'inlined_attributes' in self.init_get(sschema, rschema, oschema,
+ neg_role(role))):
+ sectdict['main'] = 'hidden'
+ elif sschema.is_metadata(rschema):
+ sectdict['main'] = 'metadata'
+ else:
+ card, composed = _card_and_comp(sschema, rschema, oschema, role)
+ if card in '1+':
+ sectdict['main'] = 'attributes'
+ if not 'muledit' in sectdict:
+ sectdict['muledit'] = 'attributes'
+ elif rschema.final:
+ sectdict['main'] = 'attributes'
+ else:
+ sectdict['main'] = 'relations'
+ if not 'muledit' in sectdict:
+ sectdict['muledit'] = 'hidden'
+ if sectdict['main'] == 'attributes':
+ card, composed = _card_and_comp(sschema, rschema, oschema, role)
+ if card in '1+' and not composed:
+ sectdict['muledit'] = 'attributes'
+ if not 'inlined' in sectdict:
+ sectdict['inlined'] = sectdict['main']
+ # recompute formsections and set it to avoid recomputing
+ for formtype, section in sectdict.iteritems():
+ formsections.add('%s_%s' % (formtype, section))
+
+ def tag_relation(self, key, formtype, section):
+ if isinstance(formtype, tuple):
+ for ftype in formtype:
+ self.tag_relation(key, ftype, section)
+ return
+ assert formtype in self._allowed_form_types, \
+ 'formtype should be in (%s), not %s' % (
+ ','.join(self._allowed_form_types), formtype)
+ assert section in self._allowed_values[formtype], \
+ 'section for %s should be in (%s), not %s' % (
+ formtype, ','.join(self._allowed_values[formtype]), section)
+ rtags = self._tagdefs.setdefault(_ensure_str_key(key),
+ self.tag_container_cls())
+ # remove previous section for this form type if any
+ if rtags:
+ for tag in rtags.copy():
+ if tag.startswith(formtype):
+ rtags.remove(tag)
+ rtags.add('%s_%s' % (formtype, section))
+ return rtags
+
+ def init_get(self, stype, rtype, otype, tagged):
+ key = (stype, rtype, otype, tagged)
+ rtags = {}
+ for key in self._get_keys(stype, rtype, otype, tagged):
+ tags = self._tagdefs.get(key, ())
+ for tag in tags:
+ assert '_' in tag, (tag, tags)
+ section, value = tag.split('_', 1)
+ rtags[section] = value
+ cls = self.tag_container_cls
+ rtags = cls('_'.join([section,value]) for section,value in rtags.iteritems())
+ return rtags
+
+
+ def get(self, *key):
+ # overriden to avoid recomputing done in parent classes
+ return self._tagdefs.get(key, ())
+
+ def relations_by_section(self, entity, formtype, section, permission,
+ strict=False):
+ """return a list of (relation schema, target schemas, role) for the
+ given entity matching categories and permission.
+
+ `strict`:
+ bool telling if having local role is enough (strict = False) or not
+ """
+ tag = '%s_%s' % (formtype, section)
+ eschema = entity.e_schema
+ permsoverrides = autoform_permissions_overrides
+ if entity.has_eid():
+ eid = entity.eid
+ else:
+ eid = None
+ strict = False
+ if permission == 'update':
+ assert section in ('attributes', 'metadata', 'hidden')
+ relpermission = 'add'
+ else:
+ assert section not in ('attributes', 'metadata', 'hidden')
+ relpermission = permission
+ cw = entity._cw
+ for rschema, targetschemas, role in eschema.relation_definitions(True):
+ _targetschemas = []
+ for tschema in targetschemas:
+ # check section's tag first, potentially lower cost than
+ # checking permission which may imply rql queries
+ if not tag in self.etype_get(eschema, rschema, role, tschema):
+ continue
+ rdef = rschema.role_rdef(eschema, tschema, role)
+ if rschema.final:
+ if not rdef.has_perm(cw, permission, eid=eid,
+ creating=eid is None):
+ continue
+ elif strict or not rdef.has_local_role(relpermission):
+ if role == 'subject':
+ if not rdef.has_perm(cw, relpermission, fromeid=eid):
+ continue
+ elif role == 'object':
+ if not rdef.has_perm(cw, relpermission, toeid=eid):
+ continue
+ _targetschemas.append(tschema)
+ if not _targetschemas:
+ continue
+ targetschemas = _targetschemas
+ rdef = eschema.rdef(rschema, role=role, targettype=targetschemas[0])
+ # XXX tag allowing to hijack the permission machinery when
+ # permission is not verifiable until the entity is actually
+ # created...
+ if eid is None and '%s_on_new' % permission in permsoverrides.etype_get(eschema, rschema, role):
+ yield (rschema, targetschemas, role)
+ continue
+ if not rschema.final and role == 'subject':
+ # on relation with cardinality 1 or ?, we need delete perm as well
+ # if the relation is already set
+ if (relpermission == 'add'
+ and rdef.role_cardinality(role) in '1?'
+ and eid and entity.related(rschema.type, role)
+ and not rdef.has_perm(cw, 'delete', fromeid=eid,
+ toeid=entity.related(rschema.type, role)[0][0])):
+ continue
+ elif role == 'object':
+ # on relation with cardinality 1 or ?, we need delete perm as well
+ # if the relation is already set
+ if (relpermission == 'add'
+ and rdef.role_cardinality(role) in '1?'
+ and eid and entity.related(rschema.type, role)
+ and not rdef.has_perm(cw, 'delete', toeid=eid,
+ fromeid=entity.related(rschema.type, role)[0][0])):
+ continue
+ yield (rschema, targetschemas, role)
+
+autoform_section = AutoformSectionRelationTags('autoform_section')
+
+# relations'field class
+autoform_field = RelationTags('autoform_field')
+
+# relations'field explicit kwargs (given to field's __init__)
+autoform_field_kwargs = RelationTagsDict('autoform_field_kwargs')
+
+
+# set of tags of the form <action>_on_new on relations. <action> is a
+# schema action (add/update/delete/read), and when such a tag is found
+# permissions checking is by-passed and supposed to be ok
+autoform_permissions_overrides = RelationTagsSet('autoform_permissions_overrides')
+
+class ReleditTags(NoTargetRelationTagsDict):
+ """Associate to relation a dictionary to control `reledit` (e.g. edition of
+ attributes / relations from within views).
+
+ Possible keys and associated values are:
+
+ * `novalue_label`, alternative default value (shown when there is no value).
+
+ * `novalue_include_rtype`, when `novalue_label` is not specified, this boolean
+ flag control wether the generated default value should contains the
+ relation label or not. Will be the opposite of the `showlabel` value found
+ in the `primaryview_display_ctrl` rtag by default.
+
+ * `reload`, boolean, eid (to reload to) or function taking subject and
+ returning bool/eid. This is useful when editing a relation (or attribute)
+ that impacts the url or another parts of the current displayed
+ page. Defaults to False.
+
+ * `rvid`, alternative view id (as str) for relation or composite edition.
+ Default is 'autolimited'.
+
+ * `edit_target`, may be either 'rtype' (to edit the relation) or 'related'
+ (to edit the related entity). This controls whether to edit the relation
+ or the target entity of the relation. Currently only one-to-one relations
+ support target entity edition. By default, the 'related' option is taken
+ whenever the relation is composite.
+ """
+ _keys = frozenset('novalue_label novalue_include_rtype reload rvid edit_target'.split())
+
+ def tag_relation(self, key, tag):
+ for tagkey in tag.iterkeys():
+ assert tagkey in self._keys, 'tag %r not in accepted tags: %r' % (tag, self._keys)
+ return super(ReleditTags, self).tag_relation(key, tag)
+
+def init_reledit_ctrl(rtag, sschema, rschema, oschema, role):
+ values = rtag.get(sschema, rschema, oschema, role)
+ if not rschema.final:
+ composite = rschema.rdef(sschema, oschema).composite == role
+ if role == 'subject':
+ oschema = '*'
+ else:
+ sschema = '*'
+ edittarget = values.get('edit_target')
+ if edittarget not in (None, 'rtype', 'related'):
+ rtag.warning('reledit: wrong value for edit_target on relation %s: %s',
+ rschema, edittarget)
+ edittarget = None
+ if not edittarget:
+ edittarget = 'related' if composite else 'rtype'
+ rtag.tag_relation((sschema, rschema, oschema, role),
+ {'edit_target': edittarget})
+ if not 'novalue_include_rtype' in values:
+ showlabel = primaryview_display_ctrl.get(
+ sschema, rschema, oschema, role).get('showlabel', True)
+ rtag.tag_relation((sschema, rschema, oschema, role),
+ {'novalue_include_rtype': not showlabel})
+
+reledit_ctrl = ReleditTags('reledit', init_reledit_ctrl)
+
+# boxes.EditBox configuration #################################################
+
+# 'link' / 'create' relation tags, used to control the "add entity" submenu
+def init_actionbox_appearsin_addmenu(rtag, sschema, rschema, oschema, role):
+ if rtag.get(sschema, rschema, oschema, role) is None:
+ if rschema in META_RTYPES:
+ rtag.tag_relation((sschema, rschema, oschema, role), False)
+ return
+ rdef = rschema.rdef(sschema, oschema)
+ if not rdef.role_cardinality(role) in '?1' and rdef.composite == role:
+ rtag.tag_relation((sschema, rschema, oschema, role), True)
+
+actionbox_appearsin_addmenu = RelationTagsBool('actionbox_appearsin_addmenu',
+ init_actionbox_appearsin_addmenu)
--- a/web/views/workflow.py Thu Jan 10 13:03:38 2013 +0100
+++ b/web/views/workflow.py Thu Jan 10 18:34:10 2013 +0100
@@ -36,10 +36,10 @@
score_entity, is_instance, adaptable)
from cubicweb.view import EntityView
from cubicweb.schema import display_name
-from cubicweb.web import uicfg, stdmsgs, action, component, form, action
+from cubicweb.web import stdmsgs, action, component, form, action
from cubicweb.web import formfields as ff, formwidgets as fwdgs
from cubicweb.web.views import TmpFileViewMixin
-from cubicweb.web.views import forms, primary, ibreadcrumbs
+from cubicweb.web.views import uicfg, forms, primary, ibreadcrumbs
from cubicweb.web.views.tabs import TabbedPrimaryView, PrimaryTab
from cubicweb.web.views.dotgraphview import DotGraphView, DotPropsHandler