From 6279bcf4b3b37ec61c159e77a2603e8c61b592fd Mon Sep 17 00:00:00 2001 From: "Turkesh Patel (Open ERP)" Date: Fri, 11 Oct 2013 13:00:04 +0530 Subject: [PATCH 01/24] [IMP] improved code to set tooltip suffix in sparkline bar, pass suffix in opetion insted of overriding widget. bzr revid: tpa@tinyerp.com-20131011073004-0swv6l1aomjt71xp --- addons/crm/crm_case_section_view.xml | 4 ++-- addons/crm/static/src/js/crm_case_section.js | 14 -------------- addons/sale_crm/sale_crm_view.xml | 6 +++--- 3 files changed, 5 insertions(+), 19 deletions(-) diff --git a/addons/crm/crm_case_section_view.xml b/addons/crm/crm_case_section_view.xml index 78727b396d3..7bc2b914e2c 100644 --- a/addons/crm/crm_case_section_view.xml +++ b/addons/crm/crm_case_section_view.xml @@ -144,11 +144,11 @@
diff --git a/addons/crm/static/src/js/crm_case_section.js b/addons/crm/static/src/js/crm_case_section.js index 83e4205f4e5..e027313d6dc 100644 --- a/addons/crm/static/src/js/crm_case_section.js +++ b/addons/crm/static/src/js/crm_case_section.js @@ -1,5 +1,4 @@ openerp.crm = function(openerp) { -var _t = openerp.web._t; openerp.web_kanban.KanbanRecord.include({ on_card_clicked: function() { if (this.view.dataset.model === 'crm.case.section') { @@ -9,17 +8,4 @@ var _t = openerp.web._t; } }, }); - - openerp.web_kanban.SparklineBarWidgetSalesTeam = openerp.web_kanban.SparklineBarWidget.extend({ - set_offset:function(){ - var self = this; - var currency_symbol = ""; - if (self.getParent()){ - currency_symbol = self.getParent().record.currency_symbol.raw_value; - }; - return _.str.sprintf("{{offset:offset}}: {{value}} %s",self.$el.closest("div[class='oe_salesteams_leads']").attr('class') ? _t('Lead(s)') : currency_symbol) - } - }); - -openerp.web_kanban.fields_registry.add("sparkline_bar_sales", "openerp.web_kanban.SparklineBarWidgetSalesTeam"); }; diff --git a/addons/sale_crm/sale_crm_view.xml b/addons/sale_crm/sale_crm_view.xml index 9e9cdbd415c..2e55ec8fa89 100644 --- a/addons/sale_crm/sale_crm_view.xml +++ b/addons/sale_crm/sale_crm_view.xml @@ -272,7 +272,7 @@
Sales Orders - + Revenue of confirmed sales orders per month.
Click to acces the Sales Analysis.
@@ -282,7 +282,7 @@
Invoices - + Revenue of sent invoices per month.
Click to see a detailed analysis of invoices.
@@ -290,7 +290,7 @@
Quotations - + Revenue of created quotations per month.
Click to see a detailed analysis.
From cfcafee87cf8dc9e450c239d35512042e9670dd5 Mon Sep 17 00:00:00 2001 From: niv-openerp Date: Fri, 11 Oct 2013 11:54:24 +0200 Subject: [PATCH 02/24] [IMP] Added some documentation in the framwork. bzr revid: nicolas.vanhoren@openerp.com-20131011095424-midppkv5czebt1f2 --- addons/web/static/src/js/openerpframework.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/addons/web/static/src/js/openerpframework.js b/addons/web/static/src/js/openerpframework.js index 027452b42fb..062ecb8fe80 100644 --- a/addons/web/static/src/js/openerpframework.js +++ b/addons/web/static/src/js/openerpframework.js @@ -138,6 +138,7 @@ var openerp = {}; throw new Error("You can only instanciate objects with the 'new' operator"); } // All construction is actually done in the init method + this._super = null; if (!initializing && this.init) { var ret = this.init.apply(this, arguments); if (ret) { return ret; } @@ -385,6 +386,14 @@ var Events = openerp.Class.extend({ } }); +/** + Mixin containing an event system. Events are also registered by specifying the target object + (the object which will receive the event when it is raised). Both the event-emitting object + and the target object store or reference to each other. This is used to correctly remove all + reference to the event handler when any of the object is destroyed (when the destroy() method + from ParentedMixin is called). Removing those references is necessary to avoid memory leak + and phantom events (events which are raised and sent to a previously destroyed object). +*/ openerp.EventDispatcherMixin = _.extend({}, openerp.ParentedMixin, { __eventDispatcherMixin: true, init: function() { From e059b1c5c0efde36893e16dea9b8b5f6dd1694ac Mon Sep 17 00:00:00 2001 From: niv-openerp Date: Fri, 11 Oct 2013 14:34:16 +0200 Subject: [PATCH 03/24] Added test with openerp sessions bzr revid: nicolas.vanhoren@openerp.com-20131011123416-wsfr0g1pusa0wftp --- addons/web/static/test/jsonrpc.js | 30 ++++++++++++------------------ 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/addons/web/static/test/jsonrpc.js b/addons/web/static/test/jsonrpc.js index a8b901d3b1c..f8a1d325375 100644 --- a/addons/web/static/test/jsonrpc.js +++ b/addons/web/static/test/jsonrpc.js @@ -113,25 +113,16 @@ function (test) { });*/ }); - -// desactivated because I can't manage to make these work in the runbot -/* var login = "admin"; var password = "admin"; -var db = null; ropenerp.testing.section('jsonrpc-auth', { - setup: function() { - var session = new openerp.Session(); - return session.session_reload().then(function() { - db = session.db; - ok(db, "db must be valid"); - }); - }, + rpc: "rpc", }, function (test) { - test('basic-auth', {asserts: 4}, function () { - var session = new openerp.Session(); + test('basic-auth', {asserts: 3}, function () { + var db = ropenerp.session.db; + var session = new openerp.Session(null, null, {override_session: true}); equal(session.uid, undefined, "uid is expected to be undefined"); return session.session_authenticate(db, login, password).then(function() { equal(session.uid, 1, "Admin's uid must be 1"); @@ -145,14 +136,16 @@ function (test) { }); }); }); - test('share-sessions', {asserts: 7}, function () { - var session = new openerp.Session(); + test('share-sessions', {asserts: 6}, function () { + var db = ropenerp.session.db; + var session = new openerp.Session(null, null, {override_session: true}); var session2; return session.session_authenticate(db, login, password).then(function() { equal(session.uid, 1, "Admin's uid must be 1"); session2 = new openerp.Session(null, null, {session_id: session.session_id}); equal(session2.uid, undefined, "uid should be undefined"); equal(session2.override_session, true, "overwrite_session should be true"); + console.log("session_id", session.session_id); return session2.session_reload(); }).then(function() { equal(session2.uid, session.uid); @@ -167,8 +160,9 @@ function (test) { }); }); }); - test('models', {asserts: 3}, function () { - var session = new openerp.Session(); + test('models', {asserts: 2}, function () { + var db = ropenerp.session.db; + var session = new openerp.Session(null, null, {override_session: true}); return session.session_authenticate(db, login, password).then(function() { return session.model("res.users").call("search_read", {fields: ["login"], domain: [["id", "=", 1]]}); }).then(function(result) { @@ -176,6 +170,6 @@ function (test) { equal(result[0].login, "admin", "Must have admin's login"); }); }); -});*/ +}); })(); From 62ba3155a0bc37579bc0ae184fcac8c588455ffa Mon Sep 17 00:00:00 2001 From: "Turkesh Patel (Open ERP)" Date: Fri, 11 Oct 2013 18:14:04 +0530 Subject: [PATCH 04/24] [IMP] remove type parameter from __get_bar_values and make base_currency_id alwas defined bzr revid: tpa@tinyerp.com-20131011124404-xoytwxfso8rg5lmb --- addons/crm/crm.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/addons/crm/crm.py b/addons/crm/crm.py index bb4d13cf5aa..8f0e6a82591 100644 --- a/addons/crm/crm.py +++ b/addons/crm/crm.py @@ -100,7 +100,7 @@ class crm_case_section(osv.osv): def get_full_name(self, cr, uid, ids, field_name, arg, context=None): return dict(self.name_get(cr, uid, ids, context=context)) - def __get_bar_values(self, cr, uid, obj, domain, read_fields, value_field, groupby_field, type=None, context=None): + def __get_bar_values(self, cr, uid, obj, domain, read_fields, value_field, groupby_field, context=None): """ Generic method to generate data for bar chart values using SparklineBarWidget. This method performs obj.read_group(cr, uid, domain, read_fields, groupby_field). @@ -127,21 +127,22 @@ class crm_case_section(osv.osv): month = self._period_number - (relativedelta.relativedelta(month_begin, group_begin_date).months + 1) section_result[month] = {'value': 0, 'tooltip': group_begin_date.strftime('%B')} inner_groupby = (group.get('__context', {})).get('group_by',[]) - if type == "Lead" or not inner_groupby: + if value_field == 'create_date_count' or not inner_groupby: section_result[month]['value'] = group.get(value_field, 0) continue - elif inner_groupby: + if inner_groupby: inner_group_obj = obj.read_group(cr, uid, group.get('__domain'), read_fields, inner_groupby, context=context) for groupby in inner_group_obj: + user = self.pool.get('res.users').browse(cr, uid, uid, context=context) + base_currency_id = user.company_id.currency_id.id if inner_groupby[0] == 'company_id': base_currency_id = self.pool.get('res.company').browse(cr, uid, groupby['__domain'][0][2], context=context).currency_id.id elif inner_groupby[0] == 'pricelist_id': base_currency_id = self.pool.get('product.pricelist').browse(cr, uid, groupby['__domain'][0][2], context=context).currency_id.id elif inner_groupby[0] == 'currency_id': base_currency_id = self.pool.get('res.currency.rate').search_read(cr, uid, [('rate', '=', 1)], ['currency_id'], limit=1, context=context)[0]['currency_id'][0] - user = self.pool.get('res.users').browse(cr, uid, uid, context=context) value = self.pool.get('res.currency').compute(cr, uid, base_currency_id, user.company_id.currency_id.id, groupby.get(value_field, 0)) - section_result[month]['value'] = section_result[month]['value'] + value + section_result[month]['value'] += value return section_result def _get_opportunities_data(self, cr, uid, ids, field_name, arg, context=None): @@ -158,7 +159,7 @@ class crm_case_section(osv.osv): for id in ids: res[id] = dict() lead_domain = date_domain + [('type', '=', 'lead'), ('section_id', '=', id)] - res[id]['monthly_open_leads'] = self.__get_bar_values(cr, uid, obj, lead_domain, ['create_date','company_id'], 'create_date_count', ['create_date', 'company_id'], type="Lead", context=context) + res[id]['monthly_open_leads'] = self.__get_bar_values(cr, uid, obj, lead_domain, ['create_date','company_id'], 'create_date_count', ['create_date', 'company_id'], context=context) opp_domain = date_domain + [('type', '=', 'opportunity'), ('section_id', '=', id)] res[id]['monthly_planned_revenue'] = self.__get_bar_values(cr, uid, obj, opp_domain, ['planned_revenue', 'create_date', 'company_id'], 'planned_revenue', ['create_date', 'company_id'], context=context) return res From 083d3fc91e149dae323e664b0ec1ff581125450b Mon Sep 17 00:00:00 2001 From: niv-openerp Date: Fri, 11 Oct 2013 15:30:54 +0200 Subject: [PATCH 05/24] Added tests about timeouts and implemented it in jsonprpc2 bzr revid: nicolas.vanhoren@openerp.com-20131011133054-0dx3wxqcqbdocnlf --- addons/web/static/src/js/openerpframework.js | 20 ++++++++++- addons/web/static/test/jsonrpc.js | 36 ++++++++++++++++++++ 2 files changed, 55 insertions(+), 1 deletion(-) diff --git a/addons/web/static/src/js/openerpframework.js b/addons/web/static/src/js/openerpframework.js index 062ecb8fe80..ab10d304b30 100644 --- a/addons/web/static/src/js/openerpframework.js +++ b/addons/web/static/src/js/openerpframework.js @@ -817,7 +817,7 @@ var genericJsonRpc = function(fct_name, params, fct) { return result.result; } }, function() { - console.error("JsonRPC communication error", _.toArray(arguments)); + //console.error("JsonRPC communication error", _.toArray(arguments)); var def = $.Deferred(); return def.reject.apply(def, ["communication"].concat(_.toArray(arguments))); }); @@ -899,11 +899,29 @@ openerp.jsonpRpc = function(url, fct_name, params, settings) { }); // append the iframe to the DOM (will trigger the first load) $form.after($iframe); + if (settings.timeout) { + realSetTimeout(function() { + deferred.reject({}); + }, settings.timeout); + } return deferred; } }); }; +var realSetTimeout = function(fct, millis) { + var finished = new Date().getTime() + millis; + var wait = function() { + var current = new Date().getTime(); + if (current < finished) { + setTimeout(wait, finished - current); + } else { + fct(); + } + }; + setTimeout(wait, millis); +}; + openerp.Session = openerp.Class.extend(openerp.PropertiesMixin, { triggers: { 'request': 'Request sent', diff --git a/addons/web/static/test/jsonrpc.js b/addons/web/static/test/jsonrpc.js index f8a1d325375..93aa9894455 100644 --- a/addons/web/static/test/jsonrpc.js +++ b/addons/web/static/test/jsonrpc.js @@ -111,6 +111,42 @@ function (test) { notEqual(result, origin_tmp, "Values in the different sessions should be different"); }); });*/ + test('timeout-jsonrpc', {asserts: 1}, function () { + var session = new openerp.Session(); + return session.rpc("/gen_session_id", {}, {timeout: 1}).then(function() { + ok(false, "the request incorrectly succeeded"); + return $.when(); + }, function(a, e) { + e.preventDefault(); + ok(true, "the request correctly failed"); + return $.when(); + }); + }); + test('timeout-jsonprpc', {asserts: 1}, function () { + var session = new openerp.Session(); + session.origin_server = false; + return session.rpc("/gen_session_id", {}, {timeout: 1}).then(function() { + ok(false, "the request incorrectly succeeded"); + return $.when(); + }, function(a, e) { + e.preventDefault(); + ok(true, "the request correctly failed"); + return $.when(); + }); + }); + // desactivated because the phantomjs runner crash + test('timeout-jsonprpc2', {asserts: 1}, function () { + var session = new openerp.Session(); + session.origin_server = false; + return session.rpc("/gen_session_id", {}, {force2step: true, timeout: 1}).then(function() { + ok(false, "the request incorrectly succeeded"); + return $.when(); + }, function(a, e) { + e.preventDefault(); + ok(true, "the request correctly failed"); + return $.when(); + }); + }); }); var login = "admin"; From 6475f3225d71047ce1e60438ada3781fce5f1553 Mon Sep 17 00:00:00 2001 From: niv-openerp Date: Fri, 11 Oct 2013 15:32:08 +0200 Subject: [PATCH 06/24] Removed jsonprpc2 test because it fails in phantomjs bzr revid: nicolas.vanhoren@openerp.com-20131011133208-gjz0iprk63447qub --- addons/web/static/test/jsonrpc.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/web/static/test/jsonrpc.js b/addons/web/static/test/jsonrpc.js index 93aa9894455..46b7ceeac6e 100644 --- a/addons/web/static/test/jsonrpc.js +++ b/addons/web/static/test/jsonrpc.js @@ -135,7 +135,7 @@ function (test) { }); }); // desactivated because the phantomjs runner crash - test('timeout-jsonprpc2', {asserts: 1}, function () { + /*test('timeout-jsonprpc2', {asserts: 1}, function () { var session = new openerp.Session(); session.origin_server = false; return session.rpc("/gen_session_id", {}, {force2step: true, timeout: 1}).then(function() { @@ -146,7 +146,7 @@ function (test) { ok(true, "the request correctly failed"); return $.when(); }); - }); + });*/ }); var login = "admin"; From d2eb959710137f6ecb4f91d06d4e22bfda3b6de9 Mon Sep 17 00:00:00 2001 From: Antony Lesuisse Date: Sun, 13 Oct 2013 04:13:22 +0200 Subject: [PATCH 07/24] [FIX] ensure the use the registry signaling for registries loaded with -d bzr revid: al@openerp.com-20131013021322-5ej7ovpcrf7ilnn5 --- openerp/cli/server.py | 5 +++++ openerp/service/server.py | 1 - 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/openerp/cli/server.py b/openerp/cli/server.py index 24987c098e4..97737a38c3f 100644 --- a/openerp/cli/server.py +++ b/openerp/cli/server.py @@ -168,6 +168,11 @@ def main(args): import_translation() sys.exit(0) + # This needs to be done now to ensure the use of the multiprocessing + # signaling mecanism for registries loaded with -d + if config['workers']: + openerp.multi_process = True + # preload registryies, needed for -u --stop_after_init rc = 0 if config['db_name']: diff --git a/openerp/service/server.py b/openerp/service/server.py index 80a7155926b..7fa6dae0015 100644 --- a/openerp/service/server.py +++ b/openerp/service/server.py @@ -828,7 +828,6 @@ def start(): global server load_server_wide_modules() if config['workers']: - openerp.multi_process = True server = PreforkServer(openerp.service.wsgi_server.application) elif openerp.evented: server = GeventServer(openerp.service.wsgi_server.application) From 81e03814e88c198f1bd04c36bb29085f4a9810db Mon Sep 17 00:00:00 2001 From: Martin Trigaux Date: Mon, 14 Oct 2013 11:40:25 +0200 Subject: [PATCH 08/24] [IMP] base_setup: adapt fonts to many2one instead of list bzr revid: mat@openerp.com-20131014094025-05989gbpdghu2rwt --- addons/base_setup/res_config.py | 7 ++----- addons/base_setup/res_config_view.xml | 1 + 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/addons/base_setup/res_config.py b/addons/base_setup/res_config.py index bbb54e4538a..ea640a74859 100644 --- a/addons/base_setup/res_config.py +++ b/addons/base_setup/res_config.py @@ -26,9 +26,6 @@ from openerp.report.render.rml2pdf import customfonts class base_config_settings(osv.osv_memory): _name = 'base.config.settings' _inherit = 'res.config.settings' - - def _get_font(self, cr, uid, context=None): - return sorted(customfonts.RegisterCustomFonts()) _columns = { 'module_multi_company': fields.boolean('Manage multiple companies', @@ -44,11 +41,11 @@ class base_config_settings(osv.osv_memory): 'module_base_import': fields.boolean("Allow users to import data from CSV files"), 'module_google_drive': fields.boolean('Attach Google documents to any record', help="""This installs the module google_docs."""), - 'font': fields.selection(_get_font, "Select Font", help="Set your favorite font into company header"), + 'font': fields.many2one('res.font', string="Report Font", help="Set the font into the report header, it will be used for every RML report of the user company"), } _defaults= { - 'font': lambda self,cr,uid,c: self.pool.get('res.users').browse(cr, uid, uid, c).company_id.font or 'Helvetica', + 'font': lambda self,cr,uid,c: self.pool.get('res.users').browse(cr, uid, uid, c).company_id.font.id, } def open_company(self, cr, uid, ids, context=None): diff --git a/addons/base_setup/res_config_view.xml b/addons/base_setup/res_config_view.xml index e0434480a37..a235d98bdde 100644 --- a/addons/base_setup/res_config_view.xml +++ b/addons/base_setup/res_config_view.xml @@ -95,6 +95,7 @@
+
From b3a8a4493dbfe1efe59a47efcfc24b85e0353e67 Mon Sep 17 00:00:00 2001 From: Martin Trigaux Date: Mon, 14 Oct 2013 11:41:22 +0200 Subject: [PATCH 09/24] [IMP] fonts: adapt fonts to many2one instead of list bzr revid: mat@openerp.com-20131014094122-6ndc5scni2xyzksy --- openerp/addons/base/res/__init__.py | 1 + openerp/addons/base/res/res_company.py | 17 +-- openerp/addons/base/res/res_company_view.xml | 1 + openerp/addons/base/res/res_font.py | 145 +++++++++++++++++++ 4 files changed, 155 insertions(+), 9 deletions(-) create mode 100644 openerp/addons/base/res/res_font.py diff --git a/openerp/addons/base/res/__init__.py b/openerp/addons/base/res/__init__.py index 50807e20116..041a42f9f14 100644 --- a/openerp/addons/base/res/__init__.py +++ b/openerp/addons/base/res/__init__.py @@ -29,6 +29,7 @@ import res_company import res_users import res_request import res_lang +import res_font import ir_property # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/openerp/addons/base/res/res_company.py b/openerp/addons/base/res/res_company.py index d61963dbce4..e922cfbbe1e 100644 --- a/openerp/addons/base/res/res_company.py +++ b/openerp/addons/base/res/res_company.py @@ -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, will be used for every RML report of the 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('("%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): @@ -388,6 +386,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").act_discover_fonts(cr, uid, ids, context) + _defaults = { 'currency_id': _get_euro, 'paper_format': 'a4', @@ -395,12 +396,10 @@ class res_company(osv.osv): 'rml_header2': _header2, 'rml_header3': _header3, 'logo':_get_logo, - 'font':'Helvetica', } _constraints = [ (osv.osv._check_recursion, 'Error! You can not create recursive companies.', ['parent_id']) ] - # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/openerp/addons/base/res/res_company_view.xml b/openerp/addons/base/res/res_company_view.xml index e9acf7940b3..ebf6cb534b3 100644 --- a/openerp/addons/base/res/res_company_view.xml +++ b/openerp/addons/base/res/res_company_view.xml @@ -81,6 +81,7 @@ +
From 3798b1ed96a901048439f2870a98555c8c29fd31 Mon Sep 17 00:00:00 2001 From: Martin Trigaux Date: Mon, 14 Oct 2013 12:15:23 +0200 Subject: [PATCH 11/24] [IMP] better labels bzr revid: mat@openerp.com-20131014101523-bwb4lda2rxbqpb8a --- openerp/addons/base/res/res_company.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openerp/addons/base/res/res_company.py b/openerp/addons/base/res/res_company.py index e922cfbbe1e..7579ede7bdf 100644 --- a/openerp/addons/base/res/res_company.py +++ b/openerp/addons/base/res/res_company.py @@ -125,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.many2one('res.font', string="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), From 59efdc209aa7688c90c79e7f5e54f6dd0eb241a3 Mon Sep 17 00:00:00 2001 From: Martin Trigaux Date: Mon, 14 Oct 2013 12:33:08 +0200 Subject: [PATCH 12/24] [FIX] base_setup: correctly handle new font value bzr revid: mat@openerp.com-20131014103308-jynnbs2cy0nsehhn --- addons/base_setup/res_config.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/addons/base_setup/res_config.py b/addons/base_setup/res_config.py index 556b358506e..fd28a5fc8ca 100644 --- a/addons/base_setup/res_config.py +++ b/addons/base_setup/res_config.py @@ -71,7 +71,8 @@ class base_config_settings(osv.osv_memory): wizard = self.browse(cr, uid, ids)[0] if wizard.font: user = self.pool.get('res.users').browse(cr, uid, uid, context) - user.company_id.write({'font':wizard.font,'rml_header': self._change_header(user.company_id.rml_header,wizard.font), 'rml_header2': self._change_header(user.company_id.rml_header2,wizard.font), 'rml_header3': self._change_header(user.company_id.rml_header3,wizard.font)}) + font_name = wizard.font.name + user.company_id.write({'font': wizard.font.id,'rml_header': self._change_header(user.company_id.rml_header,font_name), 'rml_header2': self._change_header(user.company_id.rml_header2, font_name), 'rml_header3': self._change_header(user.company_id.rml_header3, font_name)}) return {} # Preferences wizard for Sales & CRM. From 53e8625ceaa1d546f7c3c7060525675d0dcb2c6f Mon Sep 17 00:00:00 2001 From: Martin Trigaux Date: Mon, 14 Oct 2013 14:38:15 +0200 Subject: [PATCH 13/24] [FIX] font: cleaning and better default data bzr revid: mat@openerp.com-20131014123815-6tnegdiv4cnaimtf --- openerp/addons/base/res/__init__.py | 2 +- openerp/addons/base/res/res_company.py | 10 ++ openerp/addons/base/res/res_font.py | 93 ++++--------------- openerp/report/render/rml2pdf/customfonts.py | 98 ++++---------------- 4 files changed, 49 insertions(+), 154 deletions(-) diff --git a/openerp/addons/base/res/__init__.py b/openerp/addons/base/res/__init__.py index 041a42f9f14..24bded0cc7f 100644 --- a/openerp/addons/base/res/__init__.py +++ b/openerp/addons/base/res/__init__.py @@ -25,11 +25,11 @@ import res_partner import res_bank import res_config import res_currency +import res_font import res_company import res_users import res_request import res_lang -import res_font import ir_property # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/openerp/addons/base/res/res_company.py b/openerp/addons/base/res/res_company.py index 7579ede7bdf..438ee08cd26 100644 --- a/openerp/addons/base/res/res_company.py +++ b/openerp/addons/base/res/res_company.py @@ -292,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 = """
@@ -396,6 +405,7 @@ class res_company(osv.osv): 'rml_header2': _header2, 'rml_header3': _header3, 'logo':_get_logo, + 'font':_get_font, } _constraints = [ diff --git a/openerp/addons/base/res/res_font.py b/openerp/addons/base/res/res_font.py index e67939c541d..d4209c614b7 100644 --- a/openerp/addons/base/res/res_font.py +++ b/openerp/addons/base/res/res_font.py @@ -19,12 +19,11 @@ # ############################################################################## -from reportlab import rl_config -from reportlab.pdfbase import pdfmetrics, ttfonts +from reportlab.pdfbase import ttfonts from openerp.osv import fields, osv +from openerp.report.render.rml2pdf import customfonts import logging -import os,platform """This module allows the mapping of some system-available TTF fonts to the reportlab engine. @@ -35,72 +34,8 @@ 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 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'), -] - - -# Search path for TTF files, in addition of rl_config.TTFSearchPath -TTFSearchPath = [ - '~/test', - '/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', # Arch Linux - '/usr/lib/openoffice/share/fonts/truetype/', - '~/.fonts', - '~/.local/share/fonts', - - # mac os X - from - # http://developer.apple.com/technotes/tn/tn2024.html - '~/Library/Fonts', - '/Library/Fonts', - '/Network/Library/Fonts', - '/System/Library/Fonts', - - # windows - 'c:/winnt/fonts', - 'c:/windows/fonts' -] - -def list_all_sysfonts(): - """ - This function returns list of font directories of system. - """ - filepath = [] - - # Perform the search for font files ourselves, as reportlab's - # 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)) - return filepath - class res_font(osv.Model): _name = "res.font" @@ -112,14 +47,16 @@ class res_font(osv.Model): } _sql_constraints = [ - ('name_font_uniq', 'unique(name)', 'You can not register to fonts with the same name'), + ('name_font_uniq', 'unique(name)', 'You can not register two fonts with the same name'), ] - def act_discover_fonts(self, cr, uid, ids, context=None): - CustomTTFonts = BaseCustomTTFonts + 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 list_all_sysfonts(): + 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) @@ -128,12 +65,12 @@ class res_font(osv.Model): mode = font.styleName.lower().replace(" ", "") - CustomTTFonts.append((font.familyName, font.name, font_path, mode)) + 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 BasePDFFonts: + for family in customfonts.BasePDFFonts: if not found_fonts.get(family): found_fonts[family] = {'name': family} @@ -141,5 +78,13 @@ class res_font(osv.Model): # to make sure we always have updated list, delete all and recreate self.unlink(cr, uid, self.search(cr, uid, [], context=context), context=context) for family, vals in found_fonts.items(): - self.create(cr, uid, vals, context=context) + if not self.search(cr, uid, [('name', '=', family)], context=context): + 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 \ No newline at end of file diff --git a/openerp/report/render/rml2pdf/customfonts.py b/openerp/report/render/rml2pdf/customfonts.py index ede2d91aaed..7f89f324bf7 100644 --- a/openerp/report/render/rml2pdf/customfonts.py +++ b/openerp/report/render/rml2pdf/customfonts.py @@ -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) From 3bc24a9f3b62d6c32f851960139dfa239b808529 Mon Sep 17 00:00:00 2001 From: Martin Trigaux Date: Mon, 14 Oct 2013 16:53:39 +0200 Subject: [PATCH 14/24] [FIX] font: correct action for reloading bzr revid: mat@openerp.com-20131014145339-p1uz9iwfyf3uhyhr --- addons/base_setup/res_config.py | 3 +++ addons/base_setup/res_config_view.xml | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/addons/base_setup/res_config.py b/addons/base_setup/res_config.py index fd28a5fc8ca..06c57f2df5a 100644 --- a/addons/base_setup/res_config.py +++ b/addons/base_setup/res_config.py @@ -75,6 +75,9 @@ class base_config_settings(osv.osv_memory): user.company_id.write({'font': wizard.font.id,'rml_header': self._change_header(user.company_id.rml_header,font_name), 'rml_header2': self._change_header(user.company_id.rml_header2, font_name), 'rml_header3': self._change_header(user.company_id.rml_header3, font_name)}) return {} + def act_discover_fonts(self, cr, uid, ids, context=None): + return self.pool.get("res.font").discover_fonts(cr, uid, ids, context) + # Preferences wizard for Sales & CRM. # It is defined here because it is inherited independently in modules sale, crm, # plugin_outlook and plugin_thunderbird. diff --git a/addons/base_setup/res_config_view.xml b/addons/base_setup/res_config_view.xml index 6a2c226f467..34a59444fd2 100644 --- a/addons/base_setup/res_config_view.xml +++ b/addons/base_setup/res_config_view.xml @@ -95,7 +95,7 @@
-
From b9c3d93416aabe9617b496a9a4f171d686f56cb5 Mon Sep 17 00:00:00 2001 From: Martin Trigaux Date: Mon, 14 Oct 2013 17:05:07 +0200 Subject: [PATCH 15/24] [IMP] font: handle better the difference of fonts bzr revid: mat@openerp.com-20131014150507-4ueuyyneo6h2f6ju --- openerp/addons/base/res/res_company.py | 2 +- openerp/addons/base/res/res_company_view.xml | 11 +++++++++-- openerp/addons/base/res/res_font.py | 12 +++++++++--- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/openerp/addons/base/res/res_company.py b/openerp/addons/base/res/res_company.py index 438ee08cd26..6e74dbf1547 100644 --- a/openerp/addons/base/res/res_company.py +++ b/openerp/addons/base/res/res_company.py @@ -396,7 +396,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").act_discover_fonts(cr, uid, ids, context) + return self.pool.get("res.font").discover_fonts(cr, uid, ids, context) _defaults = { 'currency_id': _get_euro, diff --git a/openerp/addons/base/res/res_company_view.xml b/openerp/addons/base/res/res_company_view.xml index ebf6cb534b3..d0f35223bba 100644 --- a/openerp/addons/base/res/res_company_view.xml +++ b/openerp/addons/base/res/res_company_view.xml @@ -80,8 +80,15 @@ - -
+ diff --git a/openerp/addons/base/res/res_font.py b/openerp/addons/base/res/res_font.py index d4209c614b7..4218b0b7955 100644 --- a/openerp/addons/base/res/res_font.py +++ b/openerp/addons/base/res/res_font.py @@ -74,11 +74,17 @@ class res_font(osv.Model): 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) - # to make sure we always have updated list, delete all and recreate - self.unlink(cr, uid, self.search(cr, uid, [], context=context), context=context) + # add unknown fonts for family, vals in found_fonts.items(): - if not self.search(cr, uid, [('name', '=', family)], context=context): + if family not in existing_font_names: self.create(cr, uid, vals, context=context) return True From 554093ae8677fc1bc9664057654028e92f83e4d9 Mon Sep 17 00:00:00 2001 From: Martin Trigaux Date: Mon, 14 Oct 2013 17:07:24 +0200 Subject: [PATCH 16/24] [IMP] base_setup: better view for fonts bzr revid: mat@openerp.com-20131014150724-820j9wcduapbzrpz --- addons/base_setup/res_config_view.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/base_setup/res_config_view.xml b/addons/base_setup/res_config_view.xml index 34a59444fd2..fab2f48e8ab 100644 --- a/addons/base_setup/res_config_view.xml +++ b/addons/base_setup/res_config_view.xml @@ -90,8 +90,8 @@ - -