diff --git a/CHANGELOG b/CHANGELOG index e798a56e38..6ff70ef9f7 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,4 @@ +* Allow to inherit views from an other model * Add user warnings * Allow to use a list of id for copy method * Use one lock per database diff --git a/trytond/ir/ui/form.rnc b/trytond/ir/ui/form.rnc index 860cb575f6..1bebb46494 100644 --- a/trytond/ir/ui/form.rnc +++ b/trytond/ir/ui/form.rnc @@ -245,7 +245,7 @@ child2 = } attlist.child2 &= empty -data = element data { attlist.data, xpath+ } +data = element data { attlist.data, xpath* } attlist.data &= empty xpath = element xpath { attlist.xpath, any } diff --git a/trytond/ir/ui/form.rng b/trytond/ir/ui/form.rng index d85f277dd2..326aa9ccb6 100644 --- a/trytond/ir/ui/form.rng +++ b/trytond/ir/ui/form.rng @@ -822,9 +822,9 @@ - + - + diff --git a/trytond/ir/ui/view.py b/trytond/ir/ui/view.py index a16b9b9b71..231f764c0a 100644 --- a/trytond/ir/ui/view.py +++ b/trytond/ir/ui/view.py @@ -6,6 +6,7 @@ from difflib import SequenceMatcher import os import logging from lxml import etree +from trytond.sql_db import table_handler class View(OSV): @@ -23,7 +24,7 @@ class View(OSV): ('calendar', 'Calendar'), ('board', 'Board'), ], 'View Type', select=1) - arch = fields.Text('View Architecture', required=True) + arch = fields.Text('View Architecture') inherit = fields.Many2One('ir.ui.view', 'Inherited View', select=1, ondelete='CASCADE') field_childs = fields.Char('Childs Field', states={ @@ -44,6 +45,17 @@ class View(OSV): }) self._order.insert(0, ('priority', 'ASC')) + def _auto_init(self, cursor, module_name): + super(View, self)._auto_init(cursor, module_name) + table = table_handler(cursor, self._table, self._name, module_name) + + # Migration from 1.0 arch no more required + if 'arch' in table.table: + if table.table['arch']['notnull']: + cursor.execute('ALTER TABLE "' + self._table + '" ' \ + 'ALTER COLUMN "arch" ' \ + 'DROP NOT NULL') + def default_arch(self, cursor, user, context=None): return '' @@ -66,17 +78,13 @@ class View(OSV): trans_views = {} for trans in cursor.dictfetchall(): trans_views[trans['src']] = trans + if not view.arch: + continue xml = view.arch.strip() + if not xml: + continue tree = etree.fromstring(xml) - if view.inherit: - if view.model != view.inherit.model: - logger = logging.getLogger('ir') - logger.error('Invalid model "%s" ' \ - 'with inherited model "%"' % \ - (view.model, view.inherit.model)) - return False - # validate the tree using RelaxNG rng_name = os.path.join(os.path.dirname(__file__), (view.inherit and view.inherit.type or view.type) + '.rng') diff --git a/trytond/osv/orm.py b/trytond/osv/orm.py index ff6026a943..4068967755 100644 --- a/trytond/osv/orm.py +++ b/trytond/osv/orm.py @@ -2250,47 +2250,60 @@ class ORM(object): test = True model = True sql_res = False + inherit_view_id = False while test: if view_id: where = (model and (" and model='%s'" % (self._name,))) or '' cursor.execute('SELECT arch, field_childs, id, type, ' \ - 'inherit ' \ + 'inherit, model ' \ 'FROM ir_ui_view WHERE id = %s ' + where, (view_id,)) else: cursor.execute('SELECT arch, field_childs, id, type, ' \ - 'inherit ' \ + 'inherit, model ' \ 'FROM ir_ui_view ' \ - 'WHERE model = %s AND type = %s AND inherit IS NULL ' \ - 'ORDER BY priority', - (self._name,view_type)) + 'WHERE model = %s AND type = %s' \ + 'ORDER BY inherit DESC, priority', + (self._name, view_type)) sql_res = cursor.fetchone() if not sql_res: break test = sql_res[4] + if test: + inherit_view_id = sql_res[2] view_id = test or sql_res[2] model = False # if a view was found if sql_res: result['type'] = sql_res[3] - result['view_id'] = sql_res[2] + result['view_id'] = view_id result['arch'] = sql_res[0] + if sql_res[5] != self._name: + inherit_obj = self.pool.get(sql_res[5]) + result['arch'] = inherit_obj.fields_view_get(cursor, user, + result['view_id'], context=context)['arch'] + view_id = inherit_view_id + def _inherit_apply_rec(result, inherit_id): # get all views which inherit from (ie modify) this view cursor.execute('SELECT arch, domain, id FROM ir_ui_view ' \ - 'WHERE inherit = %s AND model = %s ' \ - 'ORDER BY priority', (inherit_id, self._name)) + 'WHERE (inherit = %s AND model = %s) OR ' \ + ' (id = %s AND inherit IS NOT NULL) ' + 'ORDER BY priority', + (inherit_id, self._name, inherit_id)) sql_inherit = cursor.fetchall() - for (inherit, domain, view_id) in sql_inherit: + for (arch, domain, view_id) in sql_inherit: if domain: if not eval(domain, {'context': context}): continue - result = _inherit_apply(result, inherit) - result = _inherit_apply_rec(result, view_id) + if not arch or not arch.strip(): + continue + result = _inherit_apply(result, arch) + #result = _inherit_apply_rec(result, view_id) return result - result['arch'] = _inherit_apply_rec(result['arch'], sql_res[2]) + result['arch'] = _inherit_apply_rec(result['arch'], view_id) result['field_childs'] = sql_res[1] or False # otherwise, build some kind of default view