diff --git a/CHANGELOG b/CHANGELOG
index cf3afb3ccc..3aa34737c8 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,4 @@
+* Add view_ids on tree view
* Add parent_of operator
* Enforce type of inheriting view
* Use instance context in translated descriptor of Selection
diff --git a/trytond/ir/ui/tree.rnc b/trytond/ir/ui/tree.rnc
index 2b61f692f6..c044817643 100644
--- a/trytond/ir/ui/tree.rnc
+++ b/trytond/ir/ui/tree.rnc
@@ -62,6 +62,7 @@ attlist.field &= [a:defaultValue = "1"] attribute completion { "0" | "1" }?
attlist.field &= attribute string { text }?
attlist.field &= [a:defaultValue = "1"] attribute factor { text }?
attlist.field &= attribute filename { text }?
+attlist.field &= attribute view_ids { text }?
prefix = element prefix { attlist.affix, empty }
suffix = element suffix { attlist.affix, empty }
attlist.affix &= attribute string { text }?
diff --git a/trytond/ir/ui/tree.rng b/trytond/ir/ui/tree.rng
index 4e4a987775..3b5d21dbe2 100644
--- a/trytond/ir/ui/tree.rng
+++ b/trytond/ir/ui/tree.rng
@@ -198,6 +198,11 @@
+
+
+
+
+
diff --git a/trytond/model/modelview.py b/trytond/model/modelview.py
index 102edc85a4..bac0f46632 100644
--- a/trytond/model/modelview.py
+++ b/trytond/model/modelview.py
@@ -484,59 +484,64 @@ class ModelView(Model):
fields_attrs = {}
else:
fields_attrs = copy.deepcopy(fields_attrs)
- childs = True
- if element.tag in ('field', 'label', 'separator', 'group', 'suffix',
- 'prefix'):
- for attr in ('name', 'icon'):
- if element.get(attr):
- fields_attrs.setdefault(element.get(attr), {})
- if type != 'form':
- continue
+ def set_view_ids(element):
+ view_ids = []
+ if element.get('view_ids'):
+ for view_id in element.get('view_ids').split(','):
try:
- field = cls._fields[element.get(attr)]
- if hasattr(field, 'model_name'):
- relation = field.model_name
- else:
- relation = field.get_target().__name__
- except Exception:
- relation = False
- if relation and element.tag == 'field':
- childs = False
- views = {}
- mode = (element.attrib.pop('mode', None)
- or 'tree,form').split(',')
- view_ids = []
- if element.get('view_ids'):
- for view_id in element.get('view_ids').split(','):
- try:
- view_ids.append(int(view_id))
- except ValueError:
- view_ids.append(ModelData.get_id(
- *view_id.split('.')))
- Relation = pool.get(relation)
- if (not len(element)
- and type == 'form'
- and field._type in ('one2many', 'many2many')):
- # Prefetch only the first view to prevent infinite
- # loop
- if view_ids:
- for view_id in view_ids:
- view = Relation.fields_view_get(
- view_id=view_id)
- views[str(view_id)] = view
- break
- else:
- for view_type in mode:
- views[view_type] = \
- Relation.fields_view_get(
- view_type=view_type)
- break
- element.attrib['mode'] = ','.join(mode)
- element.attrib['view_ids'] = ','.join(
- map(str, view_ids))
- fields_attrs[element.get(attr)].setdefault('views', {}
- ).update(views)
+ view_ids.append(int(view_id))
+ except ValueError:
+ view_ids.append(ModelData.get_id(*view_id.split('.')))
+ element.attrib['view_ids'] = ','.join(map(str, view_ids))
+ return view_ids
+
+ def get_relation(field):
+ if hasattr(field, 'model_name'):
+ return field.model_name
+ elif hasattr(field, 'get_target'):
+ return field.get_target().__name__
+
+ def get_views(relation, view_ids, mode):
+ Relation = pool.get(relation)
+ views = {}
+ if field._type in ['one2many', 'many2many']:
+ # Prefetch only the first view to prevent infinite loop
+ if view_ids:
+ for view_id in view_ids:
+ view = Relation.fields_view_get(view_id=view_id)
+ views[str(view_id)] = view
+ break
+ else:
+ for view_type in mode:
+ views[view_type] = (
+ Relation.fields_view_get(view_type=view_type))
+ break
+ return views
+
+ for attr in ('name', 'icon'):
+ if not element.get(attr):
+ continue
+ fields_attrs.setdefault(element.get(attr), {})
+
+ if element.tag == 'field' and type in ['tree', 'form']:
+ for attr in ('name', 'icon'):
+ fname = element.get(attr)
+ if not fname:
+ continue
+ view_ids = set_view_ids(element)
+ if type != 'form':
+ continue
+ field = cls._fields[fname]
+ relation = get_relation(field)
+ if not relation:
+ continue
+ mode = (
+ element.attrib.pop('mode', None) or 'tree,form').split(',')
+ views = get_views(relation, view_ids, mode)
+ element.attrib['mode'] = ','.join(mode)
+ fields_attrs[fname].setdefault('views', {}).update(views)
+
if type == 'tree' and element.get('name') in fields_width:
element.set('width', str(fields_width[element.get('name')]))
@@ -584,10 +589,9 @@ class ModelView(Model):
if element.get(attr):
fields_attrs.setdefault(element.get(attr), {})
- if childs:
- for field in element:
- fields_attrs = cls.__view_look_dom(field, type,
- fields_width=fields_width, fields_attrs=fields_attrs)
+ for field in element:
+ fields_attrs = cls.__view_look_dom(field, type,
+ fields_width=fields_width, fields_attrs=fields_attrs)
return fields_attrs
@staticmethod