[MERGE] from trunk after fonts have been added

bzr revid: xmo@openerp.com-20131015114534-bmuu05j125s9mbo9
This commit is contained in:
Xavier Morel
2013-10-15 13:45:34 +02:00
7 changed files with 155 additions and 91 deletions
+7 -1
View File
@@ -47,7 +47,13 @@ Depends:
Conflicts: tinyerp-server, openerp-server, openerp-web
Replaces: tinyerp-server, openerp-server, openerp-web
Recommends:
graphviz, ghostscript, postgresql, python-matplotlib, poppler-utils
antiword,
graphviz,
ghostscript,
postgresql,
python-gevent,
python-matplotlib,
poppler-utils
Description: OpenERP Enterprise Resource Management
OpenERP, previously known as TinyERP, is a complete ERP and CRM. The main
features are accounting (analytic and financial), stock management, sales and
+1
View File
@@ -25,6 +25,7 @@ import res_partner
import res_bank
import res_config
import res_currency
import res_font
import res_company
import res_users
import res_request
+18 -9
View File
@@ -112,9 +112,6 @@ class res_company(osv.osv):
def _get_companies_from_partner(self, cr, uid, ids, context=None):
return self.pool['res.company'].search(cr, uid, [('partner_id', 'in', ids)], context=context)
def _get_font(self, cr, uid, context=None):
return sorted(customfonts.RegisterCustomFonts())
_columns = {
'name': fields.related('partner_id', 'name', string='Company Name', size=128, required=True, store=True, type='char'),
@@ -128,7 +125,7 @@ class res_company(osv.osv):
'rml_footer': fields.text('Report Footer', help="Footer text displayed at the bottom of all reports."),
'rml_footer_readonly': fields.related('rml_footer', type='text', string='Report Footer', readonly=True),
'custom_footer': fields.boolean('Custom Footer', help="Check this to define the report footer manually. Otherwise it will be filled in automatically."),
'font': fields.selection(_get_font, "Font",help="Set the font into the report header, will be used for every RML report of the company"),
'font': fields.many2one('res.font', string="Font",help="Set the font into the report header, it will be used as default font in the RML reports of the user company"),
'logo': fields.related('partner_id', 'image', string="Logo", type="binary"),
'logo_web': fields.function(_get_logo_web, string="Logo Web", type="binary", store={
'res.company': (lambda s, c, u, i, x: i, ['partner_id'], 10),
@@ -192,10 +189,11 @@ class res_company(osv.osv):
default_para = re.sub('fontName.?=.?".*"', 'fontName="%s"'% font,header)
return re.sub('(<setFont.?name.?=.?)(".*?")(.)', '\g<1>"%s"\g<3>'% font,default_para)
fontname = self.pool.get('res.font').browse(cr, uid, font, context=context).name
return {'value':{
'rml_header': _change_header(rml_header,font),
'rml_header2':_change_header(rml_header2,font),
'rml_header3':_change_header(rml_header3,font)
'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,6 +292,15 @@ class res_company(osv.osv):
def _get_logo(self, cr, uid, ids):
return open(os.path.join( tools.config['root_path'], 'addons', 'base', 'res', 'res_company_logo.png'), 'rb') .read().encode('base64')
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]
_header = """
<header>
<pageTemplate>
@@ -388,6 +395,9 @@ class res_company(osv.osv):
return {'value': {'rml_header': self._header_letter}}
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)
_defaults = {
'currency_id': _get_euro,
'paper_format': 'a4',
@@ -395,12 +405,11 @@ class res_company(osv.osv):
'rml_header2': _header2,
'rml_header3': _header3,
'logo':_get_logo,
'font':'Helvetica',
'font':_get_font,
}
_constraints = [
(osv.osv._check_recursion, 'Error! You can not create recursive companies.', ['parent_id'])
]
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+9 -1
View File
@@ -80,7 +80,15 @@
<field name="custom_footer" on_change="onchange_footer(custom_footer, phone, fax, email, website, vat, company_registry, bank_ids)"/>
<field name="rml_footer" attrs="{'invisible': [('custom_footer','=',False)]}"/>
<field name="rml_footer_readonly" attrs="{'invisible': [('custom_footer','=',True)]}"/>
<field name="font" on_change="onchange_font_name(font, rml_header, rml_header2, rml_header3)"/>
</group>
<group>
<label for="font" />
<div>
<div>
<field name="font" class="oe_inline" colspan="2"/>
<button string="(reload fonts)" name="act_discover_fonts" type="object" class="oe_link" colspan="1"/>
</div>
</div>
</group>
</page>
<page string="Header/Footer" groups="base.group_no_one">
+96
View File
@@ -0,0 +1,96 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from reportlab.pdfbase import ttfonts
from openerp.osv import fields, osv
from openerp.report.render.rml2pdf import customfonts
import logging
"""This module allows the mapping of some system-available TTF fonts to
the reportlab engine.
This file could be customized per distro (although most Linux/Unix ones)
should have the same filenames, only need the code below).
Due to an awful configuration that ships with reportlab at many Linux
and Ubuntu distros, we have to override the search path, too.
"""
_logger = logging.getLogger(__name__)
class res_font(osv.Model):
_name = "res.font"
_description = 'Fonts available'
_order = 'name'
_columns = {
'name': fields.char("Name", required=True),
}
_sql_constraints = [
('name_font_uniq', 'unique(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
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))
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}
# 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)
# add unknown fonts
for family, vals in found_fonts.items():
if family not in existing_font_names:
self.create(cr, uid, vals, 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
+19 -79
View File
@@ -37,18 +37,30 @@ should have the same filenames, only need the code below).
Due to an awful configuration that ships with reportlab at many Linux
and Ubuntu distros, we have to override the search path, too.
"""
_fonts_cache = {'registered_fonts': [], 'total_system_fonts': 0}
_logger = logging.getLogger(__name__)
# Basic fonts familly included in PDF standart, will always be in the font list
# Basic fonts family included in PDF standart, will always be in the font list
BasePDFFonts = [
('Helvetica', 'Helvetica'),
('Times', 'Times'),
('Courier', 'Courier'),
'Helvetica',
'Times',
'Courier'
]
# List of fonts found on the disk
CustomTTFonts = []
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'),
]
# Search path for TTF files, in addition of rl_config.TTFSearchPath
TTFSearchPath = [
@@ -73,7 +85,7 @@ TTFSearchPath = [
'c:/windows/fonts'
]
def all_sysfonts_list():
def list_all_sysfonts():
"""
This function returns list of font directories of system.
"""
@@ -89,76 +101,6 @@ def all_sysfonts_list():
filepath.append(os.path.join(dirname, filename))
return filepath
def init_new_font(familyName, name, font_dir):
return {
'regular':(familyName, name, font_dir, 'regular'),
'italic':(),
'bold':(familyName, name, font_dir, 'bold'),
'bolditalic':(),
}
def RegisterCustomFonts():
"""
This function prepares a list for all system fonts to be registered
in reportlab and returns the updated list with new fonts.
"""
global CustomTTFonts
all_system_fonts = all_sysfonts_list()
if len(all_system_fonts) != _fonts_cache['total_system_fonts']:
font_modes, last_family, registered_font_list, _fonts_cache['registered_fonts'] = {}, "", [], list(BasePDFFonts)
#Prepares a list of registered fonts. Remove such fonts those don't have cmap for Unicode.
for dirname in all_system_fonts:
try:
font_info = ttfonts.TTFontFile(dirname)
if font_info.styleName in ('Regular','Normal','Book','Medium', 'Roman'):
_fonts_cache['registered_fonts'].append((font_info.name, font_info.fullName))
registered_font_list.append((font_info.familyName, font_info.name, dirname, font_info.styleName.lower().replace(" ", "")))
_logger.debug("Found font %s at %s", font_info.name, dirname)
except:
_logger.warning("Could not register Font %s", dirname)
#Prepare font list for mapping.Each font family requires four type of modes(regular,bold,italic,bolditalic).
#If all modes are not found, dummy entries are made for remaining modes.
for familyName, name, font_dir, mode in sorted(registered_font_list):
if not last_family or not font_modes:
last_family = familyName
font_modes = init_new_font(familyName, name, font_dir)
if last_family != familyName:
# new font familly, adding previous to the list of fonts
if not font_modes['italic']:
font_modes['italic'] = font_modes['regular'][:3]+('italic',)
if not font_modes['bolditalic']:
font_modes['bolditalic'] = font_modes['bold'][:3]+('bolditalic',)
CustomTTFonts.extend(font_modes.values())
font_modes = init_new_font(familyName, name, font_dir)
if (mode== 'normal') or (mode == 'regular') or (mode == 'medium') or (mode == 'book') or (mode == 'roman'):
font_modes['regular'] = (familyName, name, font_dir, 'regular')
elif (mode == 'italic') or (mode == 'oblique'):
font_modes['italic'] = (familyName, name, font_dir, 'italic')
elif mode == 'bold':
font_modes['bold'] = (familyName, name, font_dir, 'bold')
elif (mode == 'bolditalic') or (mode == 'boldoblique'):
font_modes['bolditalic'] = (familyName, name, font_dir, 'bolditalic')
last_family = familyName
# add the last one
if font_modes:
if not font_modes['italic']:
font_modes['italic'] = font_modes['regular'][:3]+('italic',)
if not font_modes['bolditalic']:
font_modes['bolditalic'] = font_modes['bold'][:3]+('bolditalic',)
CustomTTFonts.extend(font_modes.values())
_fonts_cache['total_system_fonts'] = len(all_system_fonts)
# remove duplicates
CustomTTFonts = sorted(list(set(CustomTTFonts)))
_fonts_cache['registered_fonts'] = sorted(list(set(_fonts_cache['registered_fonts'])))
return _fonts_cache['registered_fonts']
def SetCustomFonts(rmldoc):
""" Map some font names to the corresponding TTF fonts
@@ -167,8 +109,6 @@ def SetCustomFonts(rmldoc):
This function is called once per report, so it should
avoid system-wide processing (cache it, instead).
"""
if not _fonts_cache['registered_fonts']:
RegisterCustomFonts()
for name, font, filename, mode in CustomTTFonts:
if os.path.isabs(filename) and os.path.exists(filename):
rmldoc.setTTFontMapping(name, font, filename, mode)
+5 -1
View File
@@ -3,7 +3,6 @@
#-----------------------------------------------------------
import datetime
import errno
import fcntl
import logging
import os
import os.path
@@ -21,6 +20,11 @@ import time
import traceback
import werkzeug.serving
try:
import fcntl
except ImportError:
pass
try:
from setproctitle import setproctitle
except ImportError: