[ADD] pagebreak to core qweb
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import print_function
|
||||
import ast
|
||||
import copy
|
||||
import json
|
||||
import logging
|
||||
from collections import OrderedDict
|
||||
@@ -54,7 +55,38 @@ class IrQWeb(models.AbstractModel, QWeb):
|
||||
context = dict(self.env.context, dev_mode='qweb' in tools.config['dev_mode'])
|
||||
context.update(options)
|
||||
|
||||
return super(IrQWeb, self).render(id_or_xml_id, values=values, **context)
|
||||
result = super(IrQWeb, self).render(id_or_xml_id, values=values, **context)
|
||||
|
||||
if b'data-pagebreak=' not in result:
|
||||
return result
|
||||
|
||||
fragments = html.fragments_fromstring(result)
|
||||
|
||||
for fragment in fragments:
|
||||
for row in fragment.iterfind('.//tr[@data-pagebreak]'):
|
||||
table = next(row.iterancestors('table'))
|
||||
newtable = html.Element('table', attrib=dict(table.attrib))
|
||||
thead = table.find('thead')
|
||||
if thead:
|
||||
newtable.append(copy.deepcopy(thead))
|
||||
# TODO: copy caption & tfoot as well?
|
||||
# TODO: move rows in a tbody if row.getparent() is one?
|
||||
|
||||
pos = row.get('data-pagebreak')
|
||||
assert pos in ('before', 'after')
|
||||
for sibling in row.getparent().iterchildren('tr'):
|
||||
if sibling is row:
|
||||
if pos == 'after':
|
||||
newtable.append(sibling)
|
||||
break
|
||||
newtable.append(sibling)
|
||||
|
||||
table.addprevious(newtable)
|
||||
table.addprevious(html.Element('div', attrib={
|
||||
'style': 'page-break-after: always'
|
||||
}))
|
||||
|
||||
return b''.join(html.tostring(f) for f in fragments)
|
||||
|
||||
def default_values(self):
|
||||
""" attributes add to the values for each computed template
|
||||
|
||||
@@ -7,7 +7,8 @@ import os.path
|
||||
import re
|
||||
import sys
|
||||
|
||||
from lxml import etree
|
||||
from lxml import etree, html
|
||||
from lxml.builder import E
|
||||
|
||||
from odoo.modules import get_module_resource
|
||||
from odoo.tests.common import TransactionCase
|
||||
@@ -555,6 +556,81 @@ class TestQWeb(TransactionCase):
|
||||
template
|
||||
)
|
||||
|
||||
class TestPageSplit(TransactionCase):
|
||||
# need to explicitly assertTreesEqual because I guess it's registered for
|
||||
# equality between _Element *or* HtmlElement but we're comparing a parsed
|
||||
# HtmlElement and a convenience _Element
|
||||
def test_split_before(self):
|
||||
t = self.env['ir.ui.view'].create({
|
||||
'name': 'test',
|
||||
'type': 'qweb',
|
||||
'arch_db': '''<t t-name='test'>
|
||||
<div>
|
||||
<table>
|
||||
<tr></tr>
|
||||
<tr data-pagebreak="before"></tr>
|
||||
<tr></tr>
|
||||
</table>
|
||||
</div>
|
||||
</t>
|
||||
'''
|
||||
})
|
||||
rendered = html.fromstring(self.env['ir.qweb'].render(t.id))
|
||||
ref = E.div(
|
||||
E.table(E.tr()),
|
||||
E.div({'style': 'page-break-after: always'}),
|
||||
E.table(E.tr({'data-pagebreak': 'before'}), E.tr())
|
||||
)
|
||||
print(etree.tostring(rendered))
|
||||
print(etree.tostring(ref))
|
||||
self.assertTreesEqual(rendered, ref)
|
||||
|
||||
def test_split_after(self):
|
||||
t = self.env['ir.ui.view'].create({
|
||||
'name': 'test',
|
||||
'type': 'qweb',
|
||||
'arch_db': '''<t t-name='test'>
|
||||
<div>
|
||||
<table>
|
||||
<tr></tr>
|
||||
<tr data-pagebreak="after"></tr>
|
||||
<tr></tr>
|
||||
</table>
|
||||
</div>
|
||||
</t>
|
||||
'''
|
||||
})
|
||||
rendered = html.fromstring(self.env['ir.qweb'].render(t.id))
|
||||
self.assertTreesEqual(
|
||||
rendered,
|
||||
E.div(
|
||||
E.table(E.tr(), E.tr({'data-pagebreak': 'after'})),
|
||||
E.div({'style': 'page-break-after: always'}),
|
||||
E.table(E.tr())
|
||||
)
|
||||
)
|
||||
|
||||
def test_dontsplit(self):
|
||||
t = self.env['ir.ui.view'].create({
|
||||
'name': 'test',
|
||||
'type': 'qweb',
|
||||
'arch_db': '''<t t-name='test'>
|
||||
<div>
|
||||
<table>
|
||||
<tr></tr>
|
||||
<tr></tr>
|
||||
<tr></tr>
|
||||
</table>
|
||||
</div>
|
||||
</t>
|
||||
'''
|
||||
})
|
||||
rendered = html.fromstring(self.env['ir.qweb'].render(t.id))
|
||||
self.assertTreesEqual(
|
||||
rendered,
|
||||
E.div(E.table(E.tr(), E.tr(), E.tr()))
|
||||
)
|
||||
|
||||
def load_tests(loader, suite, _):
|
||||
# can't override TestQWeb.__dir__ because dir() called on *class* not
|
||||
# instance
|
||||
|
||||
@@ -107,6 +107,8 @@ class TreeCase(unittest.TestCase):
|
||||
self.addTypeEqualityFunc(html.HtmlElement, self.assertTreesEqual)
|
||||
|
||||
def assertTreesEqual(self, n1, n2, msg=None):
|
||||
self.assertIsNotNone(n1, msg)
|
||||
self.assertIsNotNone(n2, msg)
|
||||
self.assertEqual(n1.tag, n2.tag, msg)
|
||||
# Because lxml.attrib is an ordereddict for which order is important
|
||||
# to equality, even though *we* don't care
|
||||
@@ -116,7 +118,7 @@ class TreeCase(unittest.TestCase):
|
||||
self.assertEqual((n1.tail or u'').strip(), (n2.tail or u'').strip(), msg)
|
||||
|
||||
for c1, c2 in izip_longest(n1, n2):
|
||||
self.assertEqual(c1, c2, msg)
|
||||
self.assertTreesEqual(c1, c2, msg)
|
||||
|
||||
|
||||
class MetaCase(type):
|
||||
|
||||
Reference in New Issue
Block a user