diff --git a/openerp/addons/base/res/res_partner.py b/openerp/addons/base/res/res_partner.py
index b0567b0002a..ac825fad91a 100644
--- a/openerp/addons/base/res/res_partner.py
+++ b/openerp/addons/base/res/res_partner.py
@@ -1,10 +1,13 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
+import base64
import datetime
+import hashlib
from lxml import etree
import math
import pytz
+import urllib2
import urlparse
import openerp
@@ -14,6 +17,7 @@ from openerp.osv.expression import get_unaccent_wrapper
from openerp.tools.translate import _
from openerp.exceptions import UserError
+
ADDRESS_FORMAT_LAYOUTS = {
'%(city)s %(state_code)s\n%(zip)s': """
@@ -268,8 +272,7 @@ class res_partner(osv.Model, format_address):
# image: all image fields are base64 encoded and PIL-supported
image = openerp.fields.Binary("Image", attachment=True,
- help="This field holds the image used as avatar for this contact, limited to 1024x1024px",
- default=lambda self: self._get_default_image(False, True))
+ help="This field holds the image used as avatar for this contact, limited to 1024x1024px",)
image_medium = openerp.fields.Binary("Medium-sized image",
compute='_compute_images', inverse='_inverse_image_medium', store=True, attachment=True,
help="Medium-sized image of this contact. It is automatically "\
@@ -301,14 +304,26 @@ class res_partner(osv.Model, format_address):
return [category_id] if category_id else False
@api.model
- def _get_default_image(self, is_company, colorize=False):
- img_path = openerp.modules.get_module_resource(
- 'base', 'static/src/img', 'company_image.png' if is_company else 'avatar.png')
- with open(img_path, 'rb') as f:
- image = f.read()
+ def _get_default_image(self, partner_type, is_company, parent_id):
+ colorize, img_path, image = False, False, False
- # colorize user avatars
- if not is_company:
+ if partner_type in ['contact', 'other'] and parent_id:
+ image = self.browse(parent_id).image.decode('base64')
+
+ if not image and partner_type == 'invoice':
+ img_path = openerp.modules.get_module_resource('base', 'static/src/img', 'money.png')
+ elif not image and partner_type == 'delivery':
+ img_path = openerp.modules.get_module_resource('base', 'static/src/img', 'truck.png')
+ elif not image and is_company:
+ img_path = openerp.modules.get_module_resource('base', 'static/src/img', 'company_image.png')
+ elif not image:
+ img_path = openerp.modules.get_module_resource('base', 'static/src/img', 'avatar.png')
+ colorize = True
+
+ if img_path:
+ with open(img_path, 'rb') as f:
+ image = f.read()
+ if image and colorize:
image = tools.image_colorize(image)
return tools.image_resize_image_big(image.encode('base64'))
@@ -336,7 +351,6 @@ class res_partner(osv.Model, format_address):
'is_company': False,
'company_type': 'person',
'type': 'contact',
- 'image': False,
}
_constraints = [
@@ -386,6 +400,11 @@ class res_partner(osv.Model, format_address):
return {'value': {'country_id': state.country_id.id}}
return {'value': {}}
+ @api.onchange('email')
+ def onchange_email(self):
+ if not self.image and not self.env.context.get('yaml_onchange') and self.email:
+ self.image = self._get_gravatar_image(self.email)
+
@api.multi
def on_change_company_type(self, company_type):
return {'value': {'is_company': company_type == 'company'}}
@@ -545,6 +564,10 @@ class res_partner(osv.Model, format_address):
# migrating to the new API
c_type = vals.get('company_type', self._context.get('default_company_type'))
is_company = vals.get('is_company', self._context.get('default_is_company'))
+ # compute default image in create, because computing gravatar in the onchange
+ # cannot be easily performed if default images are in the way
+ if not vals.get('image'):
+ vals['image'] = self._get_default_image(vals.get('type'), vals.get('is_company'), vals.get('parent_id'))
if c_type:
vals['is_company'] = c_type == 'company'
else:
@@ -704,6 +727,17 @@ class res_partner(osv.Model, format_address):
return self.name_create(cr, uid, email, context=context)[0]
return ids[0]
+ def _get_gravatar_image(self, email):
+ gravatar_image = False
+ email_hash = hashlib.md5(email.lower()).hexdigest()
+ url = "https://www.gravatar.com/avatar/" + email_hash
+ try:
+ image_content = urllib2.urlopen(url + "?d=404&s=128", timeout=5).read()
+ gravatar_image = base64.b64encode(image_content)
+ except Exception:
+ pass
+ return gravatar_image
+
def _email_send(self, cr, uid, ids, email_from, subject, body, on_error=None):
partners = self.browse(cr, uid, ids)
for partner in partners:
diff --git a/openerp/addons/base/res/res_partner_view.xml b/openerp/addons/base/res/res_partner_view.xml
index fe99a686eaf..ee1446e334f 100644
--- a/openerp/addons/base/res/res_partner_view.xml
+++ b/openerp/addons/base/res/res_partner_view.xml
@@ -299,6 +299,7 @@
+
diff --git a/openerp/tools/yaml_import.py b/openerp/tools/yaml_import.py
index f1a8acd969e..f5b6d9e8ce7 100644
--- a/openerp/tools/yaml_import.py
+++ b/openerp/tools/yaml_import.py
@@ -348,6 +348,7 @@ class YamlInterpreter(object):
:return: dictionary mapping the field names and their values, ready to use when calling the create() function
:rtype: dict
"""
+
class dotdict(dict):
""" Dictionary class that allow to access a dictionary value by using '.'. This is needed to eval correctly
statements like 'parent.fieldname' in context.
@@ -455,6 +456,7 @@ class YamlInterpreter(object):
if el.attrib['on_change'] in ('1', 'true'):
# New-style on_change
+ self.context['yaml_onchange'] = True
recs = model.browse(self.cr, SUPERUSER_ID, [], self.context)
result = recs.onchange(record_dict, field_name, onchange_spec)