Change attempted to simplify branding distribution, but based node
branding on final view. To be able to rewrite, node branding must be
based on source views positions before applying inheritance.

Reintroduce manual generation of xpath in distribute_branding as
ElementTree.getpath() can't handle it.

Note: why isn't branding distribution performed during initial views
reading (e.g. inherit_branding)? Surely that would obviate the need
for special casing and manually creating paths no?

bzr revid: xmo@openerp.com-20130919130847-3t8zfpv9m9pcibg0
This commit is contained in:
Xavier Morel 2013-09-19 15:08:47 +02:00
parent 4b89b246a8
commit 724bbffc88
2 changed files with 46 additions and 4 deletions

View File

@ -18,6 +18,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
# #
############################################################################## ##############################################################################
import collections
import copy import copy
import logging import logging
import os import os
@ -260,6 +261,8 @@ class view(osv.osv):
else: else:
node.set('data-oe-id', str(view_id)) node.set('data-oe-id', str(view_id))
node.set('data-oe-xpath', xpath) node.set('data-oe-xpath', xpath)
node.set('data-oe-model', 'ir.ui.view')
node.set('data-oe-field', 'arch')
return specs_tree return specs_tree
@ -682,13 +685,18 @@ class view(osv.osv):
r = self.read_combined(cr, uid, id_, fields=['arch'], context=context) r = self.read_combined(cr, uid, id_, fields=['arch'], context=context)
return r['arch'] 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': if e.get('t-ignore') or e.tag == 'head':
# TODO: find a better name and check if we have a string to boolean helper # TODO: find a better name and check if we have a string to boolean helper
return 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')): if branding and not (e.get('data-oe-model') or e.get('t-field')):
e.attrib.update(branding) 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 not e.get('data-oe-model'): return
# if a branded element contains branded elements distribute own # if a branded element contains branded elements distribute own
@ -702,8 +710,14 @@ class view(osv.osv):
if e.get(attribute)) if e.get(attribute))
if 't-raw' not in e.attrib: 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): 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): def is_node_branded(self, node):
""" Finds out whether a node is branded or qweb-active (bears a """ Finds out whether a node is branded or qweb-active (bears a

View File

@ -35,7 +35,7 @@ import sys
import threading import threading
import time import time
import zipfile import zipfile
from collections import defaultdict from collections import defaultdict, Mapping
from datetime import datetime from datetime import datetime
from itertools import islice, izip, groupby from itertools import islice, izip, groupby
from lxml import etree 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)] 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: # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: