diff --git a/openerp/addons/base/ir/ir_ui_view.py b/openerp/addons/base/ir/ir_ui_view.py index 1bf642ac202..3845d916843 100644 --- a/openerp/addons/base/ir/ir_ui_view.py +++ b/openerp/addons/base/ir/ir_ui_view.py @@ -18,6 +18,7 @@ # along with this program. If not, see . # ############################################################################## +import collections import copy import logging import os @@ -260,6 +261,8 @@ class view(osv.osv): else: node.set('data-oe-id', str(view_id)) node.set('data-oe-xpath', xpath) + node.set('data-oe-model', 'ir.ui.view') + node.set('data-oe-field', 'arch') return specs_tree @@ -682,13 +685,18 @@ class view(osv.osv): r = self.read_combined(cr, uid, id_, fields=['arch'], context=context) return r['arch'] - def distribute_branding(self, e, branding=None): + def distribute_branding(self, e, branding=None, parent_xpath='', + index_map=misc.ConstantMapping(1)): if e.get('t-ignore') or e.tag == 'head': # TODO: find a better name and check if we have a string to boolean helper return + + node_path = e.get('data-oe-xpath') + if node_path is None: + node_path = "%s/%s[%d]" % (parent_xpath, e.tag, index_map[e.tag]) if branding and not (e.get('data-oe-model') or e.get('t-field')): e.attrib.update(branding) - e.set('data-oe-xpath', e.getroottree().getpath(e)) + e.set('data-oe-xpath', node_path) if not e.get('data-oe-model'): return # if a branded element contains branded elements distribute own @@ -702,8 +710,14 @@ class view(osv.osv): if e.get(attribute)) if 't-raw' not in e.attrib: + # TODO: collections.Counter if remove p2.6 compat + # running index by tag type, for XPath query generation + indexes = collections.defaultdict(lambda: 0) for child in e.iterchildren(tag=etree.Element): - self.distribute_branding(child, distributed_branding) + indexes[child.tag] += 1 + self.distribute_branding(child, distributed_branding, + parent_xpath=node_path, + index_map=indexes) def is_node_branded(self, node): """ Finds out whether a node is branded or qweb-active (bears a diff --git a/openerp/tools/misc.py b/openerp/tools/misc.py index 65e7c38e536..bdbb4d13e0f 100644 --- a/openerp/tools/misc.py +++ b/openerp/tools/misc.py @@ -35,7 +35,7 @@ import sys import threading import time import zipfile -from collections import defaultdict +from collections import defaultdict, Mapping from datetime import datetime from itertools import islice, izip, groupby from lxml import etree @@ -1066,4 +1066,32 @@ def stripped_sys_argv(*strip_args): return [x for i, x in enumerate(args) if not strip(args, i)] +class ConstantMapping(Mapping): + """ + An immutable mapping returning the provided value for every single key. + + Useful for default value to methods + """ + __slots__ = ['_value'] + def __init__(self, val): + self._value = val + + def __len__(self): + """ + defaultdict updates its length for each individually requested key, is + that really useful? + """ + return 0 + + def __iter__(self): + """ + same as len, defaultdict udpates its iterable keyset with each key + requested, is there a point for this? + """ + return iter([]) + + def __getitem__(self, item): + return self._value + + # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: