[FIX] merge from trunk and fix handling of view inheritance

main problem, view inheritance model field would use model from the
root view (after following inherit_id links) rather than the base view
(the requested one) -> with divergent models, it was possible for the
requested view itself to never be returned.

bzr revid: xmo@openerp.com-20131212134422-uxg6h21w1jhth9ow
This commit is contained in:
Xavier Morel 2013-12-12 14:44:22 +01:00
commit 0546993327
14 changed files with 15604 additions and 123 deletions

View File

@ -39,7 +39,7 @@
<field name="city"></field>
<field name="zip"></field>
<field name="phone"></field>
<field name="email">info@yourcompany.example.com</field>
<field name="email">info@yourcompany.com</field>
<field name="website">www.yourcompany.com</field>
</record>
@ -68,10 +68,7 @@
<field name="name">Administrator</field>
<field name="company_id" ref="main_company"/>
<field name="customer" eval="False"/>
<field name="email">admin@yourcompany.example.com</field>
<field name="city">Barchon</field>
<field name="zip">4671</field>
<field name="street">Rue de Heuseux 61</field>
<field name="email">admin@example.com</field>
</record>
<record model="res.users" id="base.user_root">
@ -103,7 +100,6 @@ Administrator</field>
<field name="comment">Portal members have specific access rights (such as record rules and restricted menus).
They usually do not belong to the usual OpenERP groups.</field>
</record>
<!--
A group dedicated to the public user only, making groups
restrictions more convenient.
@ -114,5 +110,25 @@ Administrator</field>
They usually do not belong to the usual OpenERP groups.</field>
</record>
<!-- Basic fonts family included in PDF standart, will always be in the font list -->
<record model="res.font" id="base.font_helvetica">
<field name="name">Helvetica</field>
<field name="family">Helvetica</field>
<field name="path">/dev/null</field>
<field name="mode">all</field>
</record>
<record model="res.font" id="base.font_times">
<field name="name">Times</field>
<field name="family">Times</field>
<field name="path">/dev/null</field>
<field name="mode">all</field>
</record>
<record model="res.font" id="base.font_courier">
<field name="name">Courier</field>
<field name="family">Courier</field>
<field name="path">/dev/null</field>
<field name="mode">all</field>
</record>
</data>
</openerp>

File diff suppressed because it is too large Load Diff

View File

@ -82,9 +82,8 @@ class ir_http(osv.AbstractModel):
# what if error in security.check()
# -> res_users.check()
# -> res_users.check_credentials()
except http.SessionExpiredException:
except Exception:
request.session.logout()
raise http.SessionExpiredException("Session expired for request %s" % request.httprequest)
getattr(self, "_auth_method_%s" % auth_method)()
return auth_method

View File

@ -214,7 +214,6 @@ class view(osv.osv):
# Module init currently in progress, only consider views from
# modules whose code is already loaded
conditions.extend([
['model_ids.model', '=', 'ir.ui.view'],
'|',
['model_ids.module', 'in', tuple(self.pool._init_modules)],
['id', 'in', check_view_ids],
@ -380,7 +379,7 @@ class view(osv.osv):
if context is None: context = {}
# if view_id is not a root view, climb back to the top.
v = self.browse(cr, uid, view_id, context=context)
base = v = self.browse(cr, uid, view_id, context=context)
while v.inherit_id:
v = v.inherit_id
root_id = v.id
@ -401,7 +400,8 @@ class view(osv.osv):
})
# and apply inheritance
arch = self.apply_view_inheritance(cr, uid, arch_tree, root_id, v.model, context=context)
arch = self.apply_view_inheritance(
cr, uid, arch_tree, root_id, base.model, context=context)
return dict(view, arch=etree.tostring(arch, encoding='utf-8'))

View File

@ -5,9 +5,9 @@
<!--logo-->
<fill color="black"/>
<stroke color="black"/>
<setFont name="DejaVu Sans" size="8"/>
<setFont name="DejaVuSans" size="8"/>
<drawString x="1.3cm" y="19.5cm"><xsl:value-of select="//header-date"/></drawString>
<setFont name="DejaVu Sans Bold" size="10"/>
<setFont name="DejaVuSans-Bold" size="10"/>
<drawString x="13.8cm" y="19.5cm"><xsl:value-of select="//company"/></drawString>
<stroke color="#000000"/>
<lines size="8">1.3cm 19.3cm 28.5cm 19.3cm</lines>

View File

@ -27,7 +27,6 @@ from openerp.osv import fields, osv
from openerp.tools.translate import _
from openerp.tools.safe_eval import safe_eval as eval
from openerp.tools import image_resize_image
from openerp.report.render.rml2pdf import customfonts
class multi_company_default(osv.osv):
"""
@ -183,17 +182,20 @@ class res_company(osv.osv):
def onchange_font_name(self, cr, uid, ids, font, rml_header, rml_header2, rml_header3, context=None):
""" To change default header style of all <para> and drawstring. """
def _change_header(header,font):
""" Replace default fontname use in header and setfont tag """
default_para = re.sub('fontName.?=.?".*"', 'fontName="%s"'% font,header)
return re.sub('(<setFont.?name.?=.?)(".*?")(.)', '\g<1>"%s"\g<3>'% font,default_para)
default_para = re.sub('fontName.?=.?".*"', 'fontName="%s"'% font, header)
return re.sub('(<setFont.?name.?=.?)(".*?")(.)', '\g<1>"%s"\g<3>'% font, default_para)
if not font:
return True
fontname = self.pool.get('res.font').browse(cr, uid, font, context=context).name
return {'value':{
'rml_header': _change_header(rml_header,fontname),
'rml_header2':_change_header(rml_header2,fontname),
'rml_header3':_change_header(rml_header3,fontname)
'rml_header': _change_header(rml_header, fontname),
'rml_header2':_change_header(rml_header2, fontname),
'rml_header3':_change_header(rml_header3, fontname)
}}
def on_change_country(self, cr, uid, ids, country_id, context=None):
@ -294,12 +296,8 @@ class res_company(osv.osv):
def _get_font(self, cr, uid, ids):
font_obj = self.pool.get('res.font')
res = font_obj.search(cr, uid, [('name', '=', 'Helvetica')], limit=1)
if res:
return res[0]
font_obj.init_no_scan(cr, uid)
return font_obj.search(cr, uid, [('name', '=', 'Helvetica')], limit=1)[0]
res = font_obj.search(cr, uid, [('family', '=', 'Helvetica'), ('mode', '=', 'all')], limit=1)
return res and res[0] or False
_header = """
<header>
@ -307,20 +305,20 @@ class res_company(osv.osv):
<frame id="first" x1="28.0" y1="28.0" width="%s" height="%s"/>
<stylesheet>
<!-- Set here the default font to use for all <para> tags -->
<paraStyle name='Normal' fontName="DejaVu Sans"/>
<paraStyle name='Normal' fontName="DejaVuSans"/>
</stylesheet>
<pageGraphics>
<fill color="black"/>
<stroke color="black"/>
<setFont name="DejaVu Sans" size="8"/>
<setFont name="DejaVuSans" size="8"/>
<drawString x="%s" y="%s"> [[ formatLang(time.strftime("%%Y-%%m-%%d"), date=True) ]] [[ time.strftime("%%H:%%M") ]]</drawString>
<setFont name="DejaVu Sans Bold" size="10"/>
<setFont name="DejaVuSans-Bold" size="10"/>
<drawCentredString x="%s" y="%s">[[ company.partner_id.name ]]</drawCentredString>
<stroke color="#000000"/>
<lines>%s</lines>
<!-- Set here the default font to use for all <drawString> tags -->
<!-- don't forget to change the 2 other occurence of <setFont> above if needed -->
<setFont name="DejaVu Sans" size="8"/>
<setFont name="DejaVuSans" size="8"/>
</pageGraphics>
</pageTemplate>
</header>"""
@ -345,13 +343,13 @@ class res_company(osv.osv):
<frame id="first" x1="1.3cm" y1="3.0cm" height="%s" width="19.0cm"/>
<stylesheet>
<!-- Set here the default font to use for all <para> tags -->
<paraStyle name='Normal' fontName="DejaVu Sans"/>
<paraStyle name='Normal' fontName="DejaVuSans"/>
<paraStyle name="main_footer" fontSize="8.0" alignment="CENTER"/>
<paraStyle name="main_header" fontSize="8.0" leading="10" alignment="LEFT" spaceBefore="0.0" spaceAfter="0.0"/>
</stylesheet>
<pageGraphics>
<!-- Set here the default font to use for all <drawString> tags -->
<setFont name="DejaVu Sans" size="8"/>
<setFont name="DejaVuSans" size="8"/>
<!-- You Logo - Change X,Y,Width and Height -->
<image x="1.3cm" y="%s" height="40.0" >[[ company.logo or removeParentNode('image') ]]</image>
<fill color="black"/>
@ -396,7 +394,7 @@ class res_company(osv.osv):
return {'value': {'rml_header': self._header_a4}}
def act_discover_fonts(self, cr, uid, ids, context=None):
return self.pool.get("res.font").discover_fonts(cr, uid, ids, context)
return self.pool.get("res.font").font_scan(cr, uid, context=context)
_defaults = {
'currency_id': _get_euro,

View File

@ -85,7 +85,7 @@
<label for="font" />
<div>
<div>
<field name="font" class="oe_inline" colspan="2" on_change="onchange_font_name(font, rml_header, rml_header2, rml_header3)"/>
<field name="font" class="oe_inline" colspan="2" on_change="onchange_font_name(font, rml_header, rml_header2, rml_header3)" domain="[('mode', 'in', ('normal', 'regular', 'all', 'book'))]" />
<button string="(reload fonts)" name="act_discover_fonts" type="object" class="oe_link" colspan="1"/>
</div>
</div>

View File

@ -2,7 +2,7 @@
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
# Copyright (C) 2013 OpenERP SA (<http://openerp.com>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
@ -20,6 +20,7 @@
##############################################################################
from reportlab.pdfbase import ttfonts
from openerp.modules.registry import RegistryManager
from openerp.osv import fields, osv
from openerp.report.render.rml2pdf import customfonts
@ -40,57 +41,75 @@ _logger = logging.getLogger(__name__)
class res_font(osv.Model):
_name = "res.font"
_description = 'Fonts available'
_order = 'name'
_order = 'family,name,id'
_rec_name = 'family'
_columns = {
'name': fields.char("Name", required=True),
'family': fields.char("Font family", required=True),
'name': fields.char("Font Name", required=True),
'path': fields.char("Path", required=True),
'mode': fields.char("Mode", required=True),
}
_sql_constraints = [
('name_font_uniq', 'unique(name)', 'You can not register two fonts with the same name'),
('name_font_uniq', 'unique(family, name)', 'You can not register two fonts with the same name'),
]
def discover_fonts(self, cr, uid, ids, context=None):
"""Scan fonts on the file system, add them to the list of known fonts
and create font object for the new ones"""
customfonts.CustomTTFonts = customfonts.BaseCustomTTFonts
def font_scan(self, cr, uid, lazy=False, context=None):
"""Action of loading fonts
In lazy mode will scan the filesystem only if there is no founts in the database and sync if no font in CustomTTFonts
In not lazy mode will force scan filesystem and sync
"""
if lazy:
# lazy loading, scan only if no fonts in db
found_fonts_ids = self.search(cr, uid, [('path', '!=', '/dev/null')], context=context)
if not found_fonts_ids:
# no scan yet or no font found on the system, scan the filesystem
self._scan_disk(cr, uid, context=context)
elif len(customfonts.CustomTTFonts) == 0:
# CustomTTFonts list is empty
self._sync(cr, uid, context=context)
else:
self._scan_disk(cr, uid, context=context)
return True
found_fonts = {}
def _scan_disk(self, cr, uid, context=None):
"""Scan the file system and register the result in database"""
found_fonts = []
for font_path in customfonts.list_all_sysfonts():
try:
font = ttfonts.TTFontFile(font_path)
_logger.debug("Found font %s at %s", font.name, font_path)
if not found_fonts.get(font.familyName):
found_fonts[font.familyName] = {'name': font.familyName}
mode = font.styleName.lower().replace(" ", "")
customfonts.CustomTTFonts.append((font.familyName, font.name, font_path, mode))
found_fonts.append((font.familyName, font.name, font_path, font.styleName))
except ttfonts.TTFError:
_logger.warning("Could not register Font %s", font_path)
# add default PDF fonts
for family in customfonts.BasePDFFonts:
if not found_fonts.get(family):
found_fonts[family] = {'name': family}
for family, name, path, mode in found_fonts:
if not self.search(cr, uid, [('family', '=', family), ('name', '=', name)], context=context):
self.create(cr, uid, {
'family': family, 'name': name,
'path': path, 'mode': mode,
}, context=context)
# remove deleted fonts
existing_font_ids = self.search(cr, uid, [], context=context)
existing_font_names = []
for font in self.browse(cr, uid, existing_font_ids):
existing_font_names.append(font.name)
if font.name not in found_fonts.keys():
self.unlink(cr, uid, font.id, context=context)
# remove fonts not present on the disk anymore
existing_font_names = [name for (family, name, path, mode) in found_fonts]
inexistant_fonts = self.search(cr, uid, [('name', 'not in', existing_font_names), ('path', '!=', '/dev/null')], context=context)
if inexistant_fonts:
self.unlink(cr, uid, inexistant_fonts, context=context)
# add unknown fonts
for family, vals in found_fonts.items():
if family not in existing_font_names:
self.create(cr, uid, vals, context=context)
RegistryManager.signal_caches_change(cr.dbname)
self._sync(cr, uid, context=context)
return True
def init_no_scan(self, cr, uid, context=None):
"""Add demo data for PDF fonts without scan (faster for db creation)"""
for font in customfonts.BasePDFFonts:
if not self.search(cr, uid, [('name', '=', font)], context=context):
self.create(cr, uid, {'name':font}, context=context)
return True
def _sync(self, cr, uid, context=None):
"""Set the customfonts.CustomTTFonts list to the content of the database"""
customfonts.CustomTTFonts = []
found_fonts_ids = self.search(cr, uid, [('path', '!=', '/dev/null')], context=context)
for font in self.browse(cr, uid, found_fonts_ids, context=None):
customfonts.CustomTTFonts.append((font.family, font.name, font.path, font.mode))
return True
def clear_caches(self):
"""Force worker to resync at next report loading by setting an empty font list"""
customfonts.CustomTTFonts = []
return super(res_font, self).clear_caches()

View File

@ -1,11 +1,11 @@
# -*- encoding: utf-8 -*-
from functools import partial
from lxml import etree as ET
from lxml.builder import E
import unittest2
from lxml import etree as ET
from lxml.builder import E
from openerp.tests import common
from openerp.osv.orm import except_orm
from openerp.tools import mute_logger
Field = E.field
@ -431,7 +431,7 @@ class TestNoModel(common.TransactionCase):
class test_views(common.TransactionCase):
def test_20_remove_unexisting_attribute(self):
def test_nonexistent_attribute_removal(self):
Views = self.registry('ir.ui.view')
Views.create(self.cr, self.uid, {
'name': 'Test View',
@ -456,7 +456,7 @@ class test_views(common.TransactionCase):
self.cr.execute(query, kw)
return self.cr.fetchone()[0]
def test_10_validate_custom_views(self):
def test_custom_view_validation(self):
Views = self.registry('ir.ui.view')
model = 'ir.actions.act_url'
@ -488,3 +488,138 @@ class test_views(common.TransactionCase):
""",
)
self.assertTrue(validate()) # inherited view
def test_view_inheritance(self):
Views = self.registry('ir.ui.view')
v1 = Views.create(self.cr, self.uid, {
'name': "bob",
'model': 'ir.ui.view',
'arch': """
<form string="Base title" version="7.0">
<separator string="separator" colspan="4"/>
<footer>
<button name="action_next" type="object" string="Next button"/>
or
<button string="Skip" special="cancel" />
</footer>
</form>
"""
})
v2 = Views.create(self.cr, self.uid, {
'name': "edmund",
'model': 'ir.ui.view',
'inherit_id': v1,
'arch': """
<data>
<form position="attributes" version="7.0">
<attribute name="string">Replacement title</attribute>
</form>
<footer position="replace">
<footer>
<button name="action_next" type="object" string="New button"/>
</footer>
</footer>
<separator string="separator" position="replace">
<p>Replacement data</p>
</separator>
</data>
"""
})
v3 = Views.create(self.cr, self.uid, {
'name': 'jake',
'model': 'ir.ui.view',
'inherit_id': v1,
'priority': 17,
'arch': """
<footer position="attributes">
<attribute name="thing">bob</attribute>
</footer>
"""
})
view = self.registry('ir.ui.view').fields_view_get(
self.cr, self.uid, v2, view_type='form', context={
# fucking what?
'check_view_ids': [v2, v3]
})
self.assertEqual(view['type'], 'form')
self.assertEqual(
ET.tostring(ET.fromstring(
view['arch'],
parser=ET.XMLParser(remove_blank_text=True)
)),
'<form string="Replacement title" version="7.0">'
'<p>Replacement data</p>'
'<footer thing="bob">'
'<button name="action_next" type="object" string="New button"/>'
'</footer>'
'</form>')
def test_view_inheritance_divergent_models(self):
Views = self.registry('ir.ui.view')
v1 = Views.create(self.cr, self.uid, {
'name': "bob",
'model': 'ir.ui.view.custom',
'arch': """
<form string="Base title" version="7.0">
<separator string="separator" colspan="4"/>
<footer>
<button name="action_next" type="object" string="Next button"/>
or
<button string="Skip" special="cancel" />
</footer>
</form>
"""
})
v2 = Views.create(self.cr, self.uid, {
'name': "edmund",
'model': 'ir.ui.view',
'inherit_id': v1,
'arch': """
<data>
<form position="attributes" version="7.0">
<attribute name="string">Replacement title</attribute>
</form>
<footer position="replace">
<footer>
<button name="action_next" type="object" string="New button"/>
</footer>
</footer>
<separator string="separator" position="replace">
<p>Replacement data</p>
</separator>
</data>
"""
})
v3 = Views.create(self.cr, self.uid, {
'name': 'jake',
'model': 'ir.ui.menu',
'inherit_id': v1,
'priority': 17,
'arch': """
<footer position="attributes">
<attribute name="thing">bob</attribute>
</footer>
"""
})
view = self.registry('ir.ui.view').fields_view_get(
self.cr, self.uid, v2, view_type='form', context={
# fucking what?
'check_view_ids': [v2, v3]
})
self.assertEqual(view['type'], 'form')
self.assertEqual(
ET.tostring(ET.fromstring(
view['arch'],
parser=ET.XMLParser(remove_blank_text=True)
)),
'<form string="Replacement title" version="7.0">'
'<p>Replacement data</p>'
'<footer>'
'<button name="action_next" type="object" string="New button"/>'
'</footer>'
'</form>')

View File

@ -187,9 +187,16 @@ class WebRequest(object):
@service_model.check
def checked_call(dbname, *a, **kw):
return self.func(*a, **kw)
if self.db:
return checked_call(self.db, *args, **kwargs)
return self.func(*args, **kwargs)
# FIXME: code and rollback management could be cleaned
try:
if self.db:
return checked_call(self.db, *args, **kwargs)
return self.func(*args, **kwargs)
except Exception:
if self._cr:
self._cr.rollback()
raise
@property
def debug(self):
@ -401,13 +408,9 @@ class HttpRequest(WebRequest):
self.params = params
def dispatch(self):
try:
r = self._call_function(**self.params)
except (werkzeug.exceptions.HTTPException), e:
r = e
else:
if not r:
r = werkzeug.wrappers.Response(status=204) # no content
r = self._call_function(**self.params)
if not r:
r = werkzeug.wrappers.Response(status=204) # no content
return r
def make_response(self, data, headers=None, cookies=None):

View File

@ -24,8 +24,6 @@ import re
from lxml import etree
import openerp
import openerp
import openerp.tools as tools
import openerp.modules
@ -33,6 +31,9 @@ import print_xml
import render
import urllib
from openerp import SUPERUSER_ID
from openerp.report.render.rml2pdf import customfonts
#
# coerce any type to a unicode string (to preserve non-ascii characters)
# and escape XML entities
@ -91,13 +92,16 @@ class report_rml(report_int):
}
def create(self, cr, uid, ids, datas, context):
registry = openerp.registry(cr.dbname)
xml = self.create_xml(cr, uid, ids, datas, context)
xml = tools.ustr(xml).encode('utf8')
report_type = datas.get('report_type', 'pdf')
if report_type == 'raw':
return xml, report_type
registry['res.font'].font_scan(cr, SUPERUSER_ID, lazy=True, context=context)
rml = self.create_rml(cr, xml, uid, context)
registry = openerp.registry(cr.dbname)
ir_actions_report_xml_obj = registry['ir.actions.report.xml']
report_xml_ids = ir_actions_report_xml_obj.search(cr, uid, [('report_name', '=', self.name[7:])], context=context)
self.title = report_xml_ids and ir_actions_report_xml_obj.browse(cr,uid,report_xml_ids)[0].name or 'OpenERP Report'

View File

@ -21,10 +21,9 @@
##############################################################################
from reportlab import rl_config
from reportlab.lib import fonts
from reportlab.pdfbase import pdfmetrics, ttfonts
import logging
import os,platform
import glob
import os
# .apidoc title: TTF Font Table
@ -39,35 +38,14 @@ and Ubuntu distros, we have to override the search path, too.
"""
_logger = logging.getLogger(__name__)
# Basic fonts family included in PDF standart, will always be in the font list
BasePDFFonts = [
'Helvetica',
'Times',
'Courier'
]
# List of fonts found on the disk
CustomTTFonts = BaseCustomTTFonts = [ ('Helvetica', "DejaVu Sans", "DejaVuSans.ttf", 'normal'),
('Helvetica', "DejaVu Sans Bold", "DejaVuSans-Bold.ttf", 'bold'),
('Helvetica', "DejaVu Sans Oblique", "DejaVuSans-Oblique.ttf", 'italic'),
('Helvetica', "DejaVu Sans BoldOblique", "DejaVuSans-BoldOblique.ttf", 'bolditalic'),
('Times', "Liberation Serif", "LiberationSerif-Regular.ttf", 'normal'),
('Times', "Liberation Serif Bold", "LiberationSerif-Bold.ttf", 'bold'),
('Times', "Liberation Serif Italic", "LiberationSerif-Italic.ttf", 'italic'),
('Times', "Liberation Serif BoldItalic", "LiberationSerif-BoldItalic.ttf", 'bolditalic'),
('Courier', "FreeMono", "FreeMono.ttf", 'normal'),
('Courier', "FreeMono Bold", "FreeMonoBold.ttf", 'bold'),
('Courier', "FreeMono Oblique", "FreeMonoOblique.ttf", 'italic'),
('Courier', "FreeMono BoldOblique", "FreeMonoBoldOblique.ttf", 'bolditalic'),
]
CustomTTFonts = []
# Search path for TTF files, in addition of rl_config.TTFSearchPath
TTFSearchPath = [
'/usr/share/fonts/truetype', # SuSE
'/usr/share/fonts/dejavu', '/usr/share/fonts/liberation', # Fedora, RHEL
'/usr/share/fonts/truetype/*','/usr/local/share/fonts' # Ubuntu,
'/usr/share/fonts/TTF/*', # at Mandriva/Mageia
'/usr/share/fonts/TTF/*', # Mandriva/Mageia
'/usr/share/fonts/TTF', # Arch Linux
'/usr/lib/openoffice/share/fonts/truetype/',
'~/.fonts',
@ -95,10 +73,8 @@ def list_all_sysfonts():
# TTFOpenFile is not very good at it.
searchpath = list(set(TTFSearchPath + rl_config.TTFSearchPath))
for dirname in searchpath:
dirname = os.path.expanduser(dirname)
if os.path.exists(dirname):
for filename in [x for x in os.listdir(dirname) if x.lower().endswith('.ttf')]:
filepath.append(os.path.join(dirname, filename))
for filename in glob.glob(os.path.join(os.path.expanduser(dirname), '*.[Tt][Tt][Ff]')):
filepath.append(filename)
return filepath
def SetCustomFonts(rmldoc):
@ -109,9 +85,9 @@ def SetCustomFonts(rmldoc):
This function is called once per report, so it should
avoid system-wide processing (cache it, instead).
"""
for name, font, filename, mode in CustomTTFonts:
for family, font, filename, mode in CustomTTFonts:
if os.path.isabs(filename) and os.path.exists(filename):
rmldoc.setTTFontMapping(name, font, filename, mode)
rmldoc.setTTFontMapping(family, font, filename, mode)
return True
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -56,8 +56,11 @@ def select_fontname(fontname, default_fontname):
try:
pdfmetrics.getFont(fontname)
except Exception:
_logger.warning('Could not locate font %s, substituting default: %s',
fontname, default_fontname)
addition = ""
if " " in fontname:
addition = ". Your font contains spaces which is not valid in RML."
_logger.warning('Could not locate font %s, substituting default: %s%s',
fontname, default_fontname, addition)
fontname = default_fontname
return fontname
@ -307,7 +310,7 @@ class _rml_doc(object):
addMapping(face, 0, 1, fontname) #italic
addMapping(face, 1, 0, fontname) #bold
addMapping(face, 1, 1, fontname) #italic and bold
elif (mode== 'normal') or (mode == 'regular'):
elif (mode== 'normal') or (mode == 'regular') or (mode == 'book'):
addMapping(face, 0, 0, fontname) #normal
elif mode == 'italic':
addMapping(face, 0, 1, fontname) #italic

View File

@ -34,6 +34,7 @@ import zipfile
import common
import openerp
from openerp import SUPERUSER_ID
from openerp.osv.fields import float as float_field, function as function_field, datetime as datetime_field
from openerp.tools.translate import _
from openerp.tools import DEFAULT_SERVER_DATE_FORMAT, DEFAULT_SERVER_DATETIME_FORMAT
@ -419,10 +420,13 @@ class report_sxw(report_rml, preprocess.report):
context = {}
if self.internal_header:
context.update(internal_header=self.internal_header)
# skip osv.fields.sanitize_binary_value() because we want the raw bytes in all cases
context.update(bin_raw=True)
registry = openerp.registry(cr.dbname)
ir_obj = registry['ir.actions.report.xml']
registry['res.font'].font_scan(cr, SUPERUSER_ID, lazy=True, context=context)
report_xml_ids = ir_obj.search(cr, uid,
[('report_name', '=', self.name[7:])], context=context)
if report_xml_ids: