From 8206b5b4cc92b6befd98ebec7f7ef8af588a9b68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Theys?= Date: Thu, 1 Aug 2019 11:20:25 +0000 Subject: [PATCH 1/6] [IMP] fields: add image field PR: #34925 --- addons/product/models/product.py | 29 ++--- odoo/addons/base/models/image_mixin.py | 19 +--- odoo/addons/test_new_api/ir.model.access.csv | 1 + odoo/addons/test_new_api/models.py | 12 ++ .../test_new_api/tests/test_new_fields.py | 107 ++++++++++++++++++ odoo/fields.py | 29 ++++- 6 files changed, 165 insertions(+), 32 deletions(-) diff --git a/addons/product/models/product.py b/addons/product/models/product.py index cdb4a74a498..250cc578c74 100644 --- a/addons/product/models/product.py +++ b/addons/product/models/product.py @@ -123,38 +123,31 @@ class ProductProduct(models.Model): # all image fields are base64 encoded and PIL-supported # all image_raw fields are technical and should not be displayed to the user - image_raw_original = fields.Binary("Raw Original Image") + image_raw_original = fields.Image("Raw Original Image") # resized fields stored (as attachment) for performance - image_raw_big = fields.Binary("Raw Big-sized Image", compute='_compute_images', store=True) - image_raw_large = fields.Binary("Raw Large-sized Image", compute='_compute_images', store=True) - image_raw_medium = fields.Binary("Raw Medium-sized Image", compute='_compute_images', store=True) - image_raw_small = fields.Binary("Raw Small-sized Image", compute='_compute_images', store=True) + image_raw_big = fields.Image("Raw Big-sized Image", related="image_raw_original", max_width=1024, max_height=1024, store=True) + image_raw_large = fields.Image("Raw Large-sized Image", related="image_raw_original", max_width=256, max_height=256, store=True) + image_raw_medium = fields.Image("Raw Medium-sized Image", related="image_raw_original", max_width=128, max_height=128, store=True) + image_raw_small = fields.Image("Raw Small-sized Image", related="image_raw_original", max_width=64, max_height=64, store=True) can_image_raw_be_zoomed = fields.Boolean("Can image raw be zoomed", compute='_compute_images', store=True) # Computed fields that are used to create a fallback to the template if # necessary, it's recommended to display those fields to the user. - image_original = fields.Binary("Original Image", compute='_compute_image_original', inverse='_set_image_original', help="Image in its original size, as it was uploaded.") - image_big = fields.Binary("Big-sized Image", compute='_compute_image_big', help="1024px * 1024px") - image_large = fields.Binary("Large-sized Image", compute='_compute_image_large', help="256px * 256px") - image_medium = fields.Binary("Medium-sized Image", compute='_compute_image_medium', help="128px * 128px") - image_small = fields.Binary("Small-sized Image", compute='_compute_image_small', help="64px * 64px") + image_original = fields.Image("Original Image", compute='_compute_image_original', inverse='_set_image_original', help="Image in its original size, as it was uploaded.") + image_big = fields.Image("Big-sized Image", compute='_compute_image_big', help="1024px * 1024px") + image_large = fields.Image("Large-sized Image", compute='_compute_image_large', help="256px * 256px") + image_medium = fields.Image("Medium-sized Image", compute='_compute_image_medium', help="128px * 128px") + image_small = fields.Image("Small-sized Image", compute='_compute_image_small', help="64px * 64px") can_image_be_zoomed = fields.Boolean("Can image be zoomed", compute='_compute_can_image_be_zoomed') - image = fields.Binary("Image", compute='_compute_image', inverse='_set_image') + image = fields.Image("Image", compute='_compute_image', inverse='_set_image') @api.depends('image_raw_original') def _compute_images(self): for record in self: image = record.image_raw_original - # for performance: avoid calling unnecessary methods when falsy - images = image and tools.image_get_resized_images(image, big_name=False) - record.image_raw_big = image and tools.image_get_resized_images(image, - large_name=False, medium_name=False, small_name=False)['image'] - record.image_raw_large = image and images['image_large'] - record.image_raw_medium = image and images['image_medium'] - record.image_raw_small = image and images['image_small'] record.can_image_raw_be_zoomed = image and tools.is_image_size_above(image) def _compute_image_original(self): diff --git a/odoo/addons/base/models/image_mixin.py b/odoo/addons/base/models/image_mixin.py index 855415e385f..1941ca41774 100644 --- a/odoo/addons/base/models/image_mixin.py +++ b/odoo/addons/base/models/image_mixin.py @@ -10,29 +10,22 @@ class ImageMixin(models.AbstractModel): # all image fields are base64 encoded and PIL-supported - image_original = fields.Binary("Original Image", help="Image in its original size, as it was uploaded.") + image_original = fields.Image("Original Image", help="Image in its original size, as it was uploaded.") # resized fields stored (as attachment) for performance - image_big = fields.Binary("Big-sized Image", compute='_compute_images', store=True, help="1024px * 1024px") - image_large = fields.Binary("Large-sized Image", compute='_compute_images', store=True, help="256px * 256px") - image_medium = fields.Binary("Medium-sized Image", compute='_compute_images', store=True, help="128px * 128px") - image_small = fields.Binary("Small-sized Image", compute='_compute_images', store=True, help="64px * 64px") + image_big = fields.Image("Big-sized Image", related="image_original", max_width=1024, max_height=1024, store=True, help="1024px * 1024px") + image_large = fields.Image("Large-sized Image", related="image_original", max_width=256, max_height=256, store=True, help="256px * 256px") + image_medium = fields.Image("Medium-sized Image", related="image_original", max_width=128, max_height=128, store=True, help="128px * 128px") + image_small = fields.Image("Small-sized Image", related="image_original", max_width=64, max_height=64, store=True, help="64px * 64px") can_image_be_zoomed = fields.Boolean("Can image raw be zoomed", compute='_compute_images', store=True) - image = fields.Binary("Image", compute='_compute_image', inverse='_set_image') + image = fields.Image("Image", compute='_compute_image', inverse='_set_image') @api.depends('image_original') def _compute_images(self): for record in self: image = record.image_original - # for performance: avoid calling unnecessary methods when falsy - images = image and tools.image_get_resized_images(image, big_name=False) - record.image_big = image and tools.image_get_resized_images(image, - large_name=False, medium_name=False, small_name=False)['image'] - record.image_large = image and images['image_large'] - record.image_medium = image and images['image_medium'] - record.image_small = image and images['image_small'] record.can_image_be_zoomed = image and tools.is_image_size_above(image) @api.depends('image_big') diff --git a/odoo/addons/test_new_api/ir.model.access.csv b/odoo/addons/test_new_api/ir.model.access.csv index e071b1b25f1..3db5381a4b9 100644 --- a/odoo/addons/test_new_api/ir.model.access.csv +++ b/odoo/addons/test_new_api/ir.model.access.csv @@ -32,3 +32,4 @@ access_test_new_api_field_with_caps,access_test_new_api_field_with_caps,model_te access_test_new_api_req_m2o,access_test_new_api_req_m2o,model_test_new_api_req_m2o,,1,1,1,1 access_test_new_api_attachment,access_test_new_api_attachment,model_test_new_api_attachment,,1,1,1,1 access_test_new_api_attachment_host,access_test_new_api_attachment_host,model_test_new_api_attachment_host,,1,1,1,1 +access_test_new_api_model_image,access_test_new_api_model_image,model_test_new_api_model_image,,1,1,1,1 diff --git a/odoo/addons/test_new_api/models.py b/odoo/addons/test_new_api/models.py index 031b55aa3ac..e045754bcc2 100644 --- a/odoo/addons/test_new_api/models.py +++ b/odoo/addons/test_new_api/models.py @@ -480,6 +480,18 @@ class ComputeCascade(models.Model): record.baz = "<%s>" % (record.bar or "") +class ModelImage(models.Model): + _name = 'test_new_api.model_image' + _description = 'Test Image field' + + name = fields.Char(required=True) + + image = fields.Image() + image_512 = fields.Image("Image 512", related='image', max_width=512, max_height=512, store=True, readonly=False) + image_256 = fields.Image("Image 256", related='image', max_width=256, max_height=256, store=False, readonly=False) + image_128 = fields.Image("Image 128", max_width=128, max_height=128) + + class BinarySvg(models.Model): _name = 'test_new_api.binary_svg' _description = 'Test SVG upload' diff --git a/odoo/addons/test_new_api/tests/test_new_fields.py b/odoo/addons/test_new_api/tests/test_new_fields.py index d372f6f23ae..d12072a58a3 100644 --- a/odoo/addons/test_new_api/tests/test_new_fields.py +++ b/odoo/addons/test_new_api/tests/test_new_fields.py @@ -1,7 +1,10 @@ # # test cases for new-style fields # +import base64 from datetime import date, datetime, time +import io +from PIL import Image from odoo import fields from odoo.exceptions import AccessError, UserError @@ -1330,6 +1333,110 @@ class TestFields(common.TransactionCase): self.assertEqual(field.related, ('monetary_id', 'amount')) self.assertEqual(field.currency_field, 'base_currency_id') + def test_94_image(self): + f = io.BytesIO() + Image.new('RGB', (4000, 2000), '#4169E1').save(f, 'PNG') + f.seek(0) + image_w = base64.b64encode(f.read()) + + f = io.BytesIO() + Image.new('RGB', (2000, 4000), '#4169E1').save(f, 'PNG') + f.seek(0) + image_h = base64.b64encode(f.read()) + + record = self.env['test_new_api.model_image'].create({ + 'name': 'image', + 'image': image_w, + 'image_128': image_w, + }) + + # test create (no resize) + self.assertEqual(record.image, image_w) + # test create (resize, width limited) + self.assertEqual(Image.open(io.BytesIO(base64.b64decode(record.image_128))).size, (128, 64)) + # test create related store (resize, width limited) + self.assertEqual(Image.open(io.BytesIO(base64.b64decode(record.image_512))).size, (512, 256)) + # test create related no store (resize, width limited) + self.assertEqual(Image.open(io.BytesIO(base64.b64decode(record.image_256))).size, (256, 128)) + + record.write({ + 'image': image_h, + 'image_128': image_h, + }) + + # test write (no resize) + self.assertEqual(record.image, image_h) + # test write (resize, height limited) + self.assertEqual(Image.open(io.BytesIO(base64.b64decode(record.image_128))).size, (64, 128)) + # test write related store (resize, height limited) + self.assertEqual(Image.open(io.BytesIO(base64.b64decode(record.image_512))).size, (256, 512)) + # test write related no store (resize, height limited) + self.assertEqual(Image.open(io.BytesIO(base64.b64decode(record.image_256))).size, (128, 256)) + + record = self.env['test_new_api.model_image'].create({ + 'name': 'image', + 'image': image_h, + 'image_128': image_h, + }) + + # test create (no resize) + self.assertEqual(record.image, image_h) + # test create (resize, height limited) + self.assertEqual(Image.open(io.BytesIO(base64.b64decode(record.image_128))).size, (64, 128)) + # test create related store (resize, height limited) + self.assertEqual(Image.open(io.BytesIO(base64.b64decode(record.image_512))).size, (256, 512)) + # test create related no store (resize, height limited) + self.assertEqual(Image.open(io.BytesIO(base64.b64decode(record.image_256))).size, (128, 256)) + + record.write({ + 'image': image_w, + 'image_128': image_w, + }) + + # test write (no resize) + self.assertEqual(record.image, image_w) + # test write (resize, width limited) + self.assertEqual(Image.open(io.BytesIO(base64.b64decode(record.image_128))).size, (128, 64)) + # test write related store (resize, width limited) + self.assertEqual(Image.open(io.BytesIO(base64.b64decode(record.image_512))).size, (512, 256)) + # test write related store (resize, width limited) + self.assertEqual(Image.open(io.BytesIO(base64.b64decode(record.image_256))).size, (256, 128)) + + # test create inverse store + record = self.env['test_new_api.model_image'].create({ + 'name': 'image', + 'image_512': image_w, + }) + record.invalidate_cache(fnames=['image_512'], ids=record.ids) + self.assertEqual(Image.open(io.BytesIO(base64.b64decode(record.image_512))).size, (512, 256)) + self.assertEqual(Image.open(io.BytesIO(base64.b64decode(record.image))).size, (4000, 2000)) + self.assertEqual(Image.open(io.BytesIO(base64.b64decode(record.image_256))).size, (256, 128)) + # test write inverse store + record.write({ + 'image_512': image_h, + }) + record.invalidate_cache(fnames=['image_512'], ids=record.ids) + self.assertEqual(Image.open(io.BytesIO(base64.b64decode(record.image_512))).size, (256, 512)) + self.assertEqual(Image.open(io.BytesIO(base64.b64decode(record.image))).size, (2000, 4000)) + self.assertEqual(Image.open(io.BytesIO(base64.b64decode(record.image_256))).size, (128, 256)) + + # test create inverse no store + record = self.env['test_new_api.model_image'].create({ + 'name': 'image', + 'image_256': image_w, + }) + record.invalidate_cache(fnames=['image_256'], ids=record.ids) + self.assertEqual(Image.open(io.BytesIO(base64.b64decode(record.image_512))).size, (512, 256)) + self.assertEqual(Image.open(io.BytesIO(base64.b64decode(record.image))).size, (4000, 2000)) + self.assertEqual(Image.open(io.BytesIO(base64.b64decode(record.image_256))).size, (256, 128)) + # test write inverse no store + record.write({ + 'image_256': image_h, + }) + self.assertEqual(Image.open(io.BytesIO(base64.b64decode(record.image_512))).size, (256, 512)) + self.assertEqual(Image.open(io.BytesIO(base64.b64decode(record.image))).size, (2000, 4000)) + self.assertEqual(Image.open(io.BytesIO(base64.b64decode(record.image_256))).size, (128, 256)) + class TestX2many(common.TransactionCase): def test_definition_many2many(self): diff --git a/odoo/fields.py b/odoo/fields.py index 41779826d6e..8d866204765 100644 --- a/odoo/fields.py +++ b/odoo/fields.py @@ -23,7 +23,7 @@ except ImportError: import psycopg2 from .tools import float_repr, float_round, frozendict, html_sanitize, human_size, pg_varchar, \ - ustr, OrderedSet, pycompat, sql, date_utils, unique, IterableGenerator + ustr, OrderedSet, pycompat, sql, date_utils, unique, IterableGenerator, image_process from .tools import DEFAULT_SERVER_DATE_FORMAT as DATE_FORMAT from .tools import DEFAULT_SERVER_DATETIME_FORMAT as DATETIME_FORMAT from .tools.translate import html_translate, _ @@ -1906,6 +1906,33 @@ class Binary(Field): atts.unlink() +class Image(Binary): + _slots = { + 'max_width': 0, + 'max_height': 0, + } + + def create(self, record_values): + new_record_values = [] + for record, value in record_values: + new_record_values.append((record, self._image_process(value))) + super(Image, self).create(new_record_values) + + def write(self, records, value): + value = self._image_process(value) + super(Image, self).write(records, value) + + def _image_process(self, value): + if value and (self.max_width or self.max_height): + value = image_process(value, size=(self.max_width, self.max_height)) + return value + + def _compute_related(self, records): + super(Image, self)._compute_related(records) + for record in records: + record[self.name] = self._image_process(record[self.name]) + + class Selection(Field): """ :param selection: specifies the possible values for this field. From 58a2ffa26f1a3b0f9630ce16d11b758d18e20a21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Theys?= Date: Thu, 1 Aug 2019 11:20:33 +0000 Subject: [PATCH 2/6] [IMP] *: rename image fields image_original => image_1920 (now resized to 1920) image_big => image_1024 image_large => image_256 image_medium => image_128 image_small => image_64 image replaced by image_1920 (when writing) or by image_1024 (when displaying what was previously the big size) + add new intermediate format: image_512 PR: #34925 --- addons/account/views/account_move_views.xml | 2 +- .../views/account_analytic_default_view.xml | 2 +- addons/calendar/views/calendar_views.xml | 2 +- addons/crm/views/crm_lead_views.xml | 6 +- addons/event_sale/models/event.py | 4 +- addons/fleet/models/fleet_vehicle.py | 8 +- addons/fleet/models/fleet_vehicle_model.py | 12 +-- .../fleet/views/fleet_vehicle_cost_views.xml | 2 +- .../fleet/views/fleet_vehicle_model_views.xml | 6 +- addons/fleet/views/fleet_vehicle_views.xml | 6 +- addons/gamification/data/goal_base.xml | 2 +- addons/gamification/models/badge.py | 4 +- .../models/gamification_karma_rank.py | 4 +- addons/gamification/views/badge.xml | 2 +- addons/gamification/views/challenge.xml | 2 +- addons/gamification/views/goal.xml | 2 +- addons/gamification/views/mail_templates.xml | 2 +- addons/hr/models/hr_employee.py | 6 +- addons/hr/models/hr_employee_public.py | 8 +- addons/hr/views/hr_employee_public_views.xml | 4 +- addons/hr/views/hr_employee_views.xml | 6 +- addons/hr/views/res_users.xml | 2 +- .../static/src/xml/attendance.xml | 6 +- .../views/hr_attendance_view.xml | 2 +- .../hr_attendance/views/hr_employee_view.xml | 2 +- .../hr_contract/views/hr_contract_views.xml | 4 +- addons/hr_expense/data/hr_expense_demo.xml | 4 +- addons/hr_expense/views/hr_expense_views.xml | 6 +- .../hr_holidays/report/hr_leave_reports.xml | 2 +- .../views/hr_leave_allocation_views.xml | 4 +- addons/hr_holidays/views/hr_leave_views.xml | 4 +- .../views/maintenance_views.xml | 2 +- .../data/hr_recruitment_data.xml | 4 +- .../views/hr_recruitment_views.xml | 2 +- .../hr_timesheet/views/hr_timesheet_views.xml | 2 +- .../views/hr_work_entry_views.xml | 2 +- .../im_livechat/models/im_livechat_channel.py | 6 +- .../views/im_livechat_channel_views.xml | 4 +- addons/lunch/controllers/main.py | 2 +- addons/lunch/models/lunch_product.py | 4 +- .../report/lunch_cashmove_report_views.xml | 2 +- addons/lunch/views/lunch_cashmove_views.xml | 2 +- addons/lunch/views/lunch_orders_views.xml | 2 +- addons/lunch/views/lunch_product_views.xml | 6 +- addons/lunch/wizard/lunch_line_wizard.py | 4 +- .../lunch/wizard/lunch_line_wizard_views.xml | 2 +- addons/mail/controllers/main.py | 2 +- addons/mail/models/mail_channel.py | 6 +- addons/mail/models/mail_message.py | 2 +- .../static/src/js/composers/basic_composer.js | 2 +- addons/mail/static/src/js/followers.js | 4 +- .../static/src/js/models/messages/message.js | 2 +- .../static/src/js/models/threads/channel.js | 2 +- .../static/src/js/models/threads/dm_chat.js | 2 +- addons/mail/static/src/xml/activity.xml | 6 +- addons/mail/views/mail_channel_views.xml | 4 +- addons/mail/views/mail_message_views.xml | 2 +- addons/mail/views/res_partner_views.xml | 2 +- .../maintenance/views/maintenance_views.xml | 6 +- addons/mrp/data/mrp_demo.xml | 26 +++--- addons/mrp/views/ir_attachment_view.xml | 2 +- addons/mrp/views/mrp_workorder_views.xml | 2 +- addons/note/views/note_views.xml | 2 +- addons/payment/models/payment_acquirer.py | 4 +- .../views/payment_portal_templates.xml | 2 +- addons/payment/views/payment_views.xml | 4 +- .../point_of_sale/data/point_of_sale_data.xml | 2 +- .../point_of_sale/data/point_of_sale_demo.xml | 22 ++--- addons/point_of_sale/models/pos_category.py | 4 +- addons/point_of_sale/static/src/js/models.js | 2 +- addons/point_of_sale/static/src/js/screens.js | 6 +- .../point_of_sale/views/pos_category_view.xml | 4 +- .../point_of_sale/views/pos_session_view.xml | 2 +- .../portal/static/src/xml/portal_chatter.xml | 2 +- .../data/pos_restaurant_demo.xml | 36 ++++---- addons/product/data/product_demo.xml | 52 +++++------ addons/product/models/product.py | 91 +++++++++--------- addons/product/models/product_template.py | 10 ++ addons/product/tests/test_variants.py | 24 ++--- .../product/views/product_template_views.xml | 6 +- addons/product/views/product_views.xml | 10 +- addons/project/views/project_views.xml | 6 +- addons/purchase/views/portal_templates.xml | 2 +- .../views/purchase_requisition_views.xml | 2 +- addons/sale/data/mail_data.xml | 2 +- addons/sale/data/sale_demo.xml | 2 +- addons/sale/models/product_template.py | 4 +- addons/sale/static/src/js/variant_mixin.js | 2 +- .../data/sale_demo.xml | 2 +- .../src/js/product_configurator_modal.js | 4 +- .../views/templates.xml | 12 +-- addons/sales_team/views/crm_team_views.xml | 2 +- addons/stock/data/stock_demo2.xml | 2 +- .../views/stock_landed_cost_views.xml | 2 +- .../views/stock_picking_batch_views.xml | 2 +- addons/survey/views/survey_templates.xml | 2 +- addons/web/controllers/main.py | 2 +- addons/web/static/src/js/chrome/user_menu.js | 2 +- .../web/static/src/js/fields/basic_fields.js | 2 +- .../src/js/views/calendar/calendar_view.js | 2 +- addons/web/tests/test_image.py | 6 +- addons/website_blog/models/website_blog.py | 2 +- .../website_blog/views/website_blog_views.xml | 2 +- .../website_crm_partner_assign_templates.xml | 4 +- .../views/website_customer_templates.xml | 6 +- .../website_event_track/models/event_track.py | 4 +- .../views/event_track_templates.xml | 6 +- .../views/event_track_views.xml | 2 +- addons/website_forum/views/forum.xml | 2 +- addons/website_forum/views/website_forum.xml | 12 +-- .../website_hr_recruitment_templates.xml | 2 +- .../views/website_livechat.xml | 8 +- .../views/website_mail_channel_templates.xml | 2 +- .../views/website_membership_templates.xml | 2 +- addons/website_profile/controllers/main.py | 4 +- .../website_profile/views/website_profile.xml | 12 +-- .../website_sale/data/mail_template_data.xml | 2 +- addons/website_sale/models/product.py | 8 +- addons/website_sale/models/product_image.py | 2 +- .../static/src/js/website_sale.js | 4 +- .../src/scss/website_sale_frontend.scss | 2 +- .../static/src/xml/website_sale_utils.xml | 2 +- .../tests/test_website_sale_image.py | 92 ++++++++++--------- addons/website_sale/views/product_views.xml | 14 +-- addons/website_sale/views/templates.xml | 20 ++-- .../website_sale_comparison_template.xml | 4 +- .../data/product_demo.xml | 2 +- .../data/website_sale_slides_demo.xml | 8 +- .../views/website_sale_wishlist_template.xml | 2 +- addons/website_slides/controllers/main.py | 6 +- addons/website_slides/data/mail_data.xml | 4 +- .../data/slide_channel_demo.xml | 14 +-- .../website_slides/data/slide_slide_demo.xml | 30 +++--- addons/website_slides/models/slide_slide.py | 16 ++-- .../src/js/slides_course_fullscreen_player.js | 2 +- .../src/xml/website_slides_fullscreen.xml | 2 +- .../views/slide_channel_views.xml | 2 +- .../views/slide_slide_views.xml | 2 +- .../views/website_slides_templates_course.xml | 8 +- .../website_slides_templates_homepage.xml | 12 +-- .../views/website_slides_templates_lesson.xml | 6 +- .../website_slides_templates_lesson_embed.xml | 6 +- .../website_slides_templates_profile.xml | 2 +- .../data/slide_slide_demo.xml | 4 +- .../views/website_profile.xml | 2 +- doc/reference/javascript_reference.rst | 2 +- odoo/addons/base/models/image_mixin.py | 30 ++---- odoo/addons/base/models/res_partner.py | 6 +- odoo/addons/base/models/res_users.py | 4 +- odoo/addons/base/tests/test_ir_http.py | 2 +- odoo/addons/base/views/res_partner_views.xml | 28 +++--- odoo/addons/base/views/res_users_views.xml | 8 +- odoo/tools/image.py | 38 +++----- 153 files changed, 524 insertions(+), 537 deletions(-) diff --git a/addons/account/views/account_move_views.xml b/addons/account/views/account_move_views.xml index a59a00f0e8d..11e539aa60b 100644 --- a/addons/account/views/account_move_views.xml +++ b/addons/account/views/account_move_views.xml @@ -103,7 +103,7 @@
- +
diff --git a/addons/account_analytic_default/views/account_analytic_default_view.xml b/addons/account_analytic_default/views/account_analytic_default_view.xml index f86ba13a513..ab568e3cd96 100644 --- a/addons/account_analytic_default/views/account_analytic_default_view.xml +++ b/addons/account_analytic_default/views/account_analytic_default_view.xml @@ -59,7 +59,7 @@
- +
From to
Product
diff --git a/addons/calendar/views/calendar_views.xml b/addons/calendar/views/calendar_views.xml index ff19273d798..e6845169f79 100644 --- a/addons/calendar/views/calendar_views.xml +++ b/addons/calendar/views/calendar_views.xml @@ -275,7 +275,7 @@ event_limit="3" color="partner_id"> - + diff --git a/addons/crm/views/crm_lead_views.xml b/addons/crm/views/crm_lead_views.xml index a10ba85000f..56822dfe6c3 100644 --- a/addons/crm/views/crm_lead_views.xml +++ b/addons/crm/views/crm_lead_views.xml @@ -247,7 +247,7 @@
- +
@@ -355,7 +355,7 @@
- +
@@ -424,7 +424,7 @@
- +
diff --git a/addons/event_sale/models/event.py b/addons/event_sale/models/event.py index ba407dc8f60..98485e5dd1d 100644 --- a/addons/event_sale/models/event.py +++ b/addons/event_sale/models/event.py @@ -239,8 +239,8 @@ class EventRegistration(models.Model): def summary(self): res = super(EventRegistration, self).summary() - if self.event_ticket_id.product_id.image_medium: - res['image'] = '/web/image/product.product/%s/image_medium' % self.event_ticket_id.product_id.id + if self.event_ticket_id.product_id.image_128: + res['image'] = '/web/image/product.product/%s/image_128' % self.event_ticket_id.product_id.id information = res.setdefault('information', {}) information.append((_('Name'), self.name)) information.append((_('Ticket'), self.event_ticket_id.name or _('None'))) diff --git a/addons/fleet/models/fleet_vehicle.py b/addons/fleet/models/fleet_vehicle.py index 3a713a0140e..bc977182d20 100644 --- a/addons/fleet/models/fleet_vehicle.py +++ b/addons/fleet/models/fleet_vehicle.py @@ -73,8 +73,8 @@ class FleetVehicle(models.Model): power = fields.Integer('Power', help='Power in kW of the vehicle') co2 = fields.Float('CO2 Emissions', help='CO2 emissions of the vehicle') image = fields.Binary(related='model_id.image', string="Logo", readonly=False) - image_medium = fields.Binary(related='model_id.image_medium', string="Logo (medium)", readonly=False) - image_small = fields.Binary(related='model_id.image_small', string="Logo (small)", readonly=False) + image_128 = fields.Binary(related='model_id.image_128', string="Logo (medium)", readonly=False) + image_64 = fields.Binary(related='model_id.image_64', string="Logo (small)", readonly=False) contract_renewal_due_soon = fields.Boolean(compute='_compute_contract_reminder', search='_search_contract_renewal_due_soon', string='Has Contracts to renew', multi='contract_info') contract_renewal_overdue = fields.Boolean(compute='_compute_contract_reminder', search='_search_get_overdue_contract_reminder', @@ -206,9 +206,9 @@ class FleetVehicle(models.Model): @api.onchange('model_id') def _onchange_model(self): if self.model_id: - self.image_medium = self.model_id.image + self.image_128 = self.model_id.image else: - self.image_medium = False + self.image_128 = False @api.model def create(self, vals): diff --git a/addons/fleet/models/fleet_vehicle_model.py b/addons/fleet/models/fleet_vehicle_model.py index e945da2ac71..596945c27ce 100644 --- a/addons/fleet/models/fleet_vehicle_model.py +++ b/addons/fleet/models/fleet_vehicle_model.py @@ -15,8 +15,8 @@ class FleetVehicleModel(models.Model): manager_id = fields.Many2one('res.users', 'Fleet Manager', default=lambda self: self.env.uid, domain=lambda self: [('groups_id', 'in', self.env.ref('fleet.fleet_group_manager').id)]) image = fields.Binary(related='brand_id.image', string="Logo", readonly=False) - image_medium = fields.Binary(related='brand_id.image_medium', string="Logo (medium)", readonly=False) - image_small = fields.Binary(related='brand_id.image_small', string="Logo (small)", readonly=False) + image_128 = fields.Binary(related='brand_id.image_128', string="Logo (medium)", readonly=False) + image_64 = fields.Binary(related='brand_id.image_64', string="Logo (small)", readonly=False) @api.depends('name', 'brand_id') def name_get(self): @@ -31,9 +31,9 @@ class FleetVehicleModel(models.Model): @api.onchange('brand_id') def _onchange_brand(self): if self.brand_id: - self.image_medium = self.brand_id.image + self.image_128 = self.brand_id.image else: - self.image_medium = False + self.image_128 = False class FleetVehicleModelBrand(models.Model): @@ -44,11 +44,11 @@ class FleetVehicleModelBrand(models.Model): name = fields.Char('Make', required=True) image = fields.Binary("Logo", help="This field holds the image used as logo for the brand, limited to 1024x1024px.") - image_medium = fields.Binary("Medium-sized image", + image_128 = fields.Binary("Medium-sized image", help="Medium-sized logo of the brand. It is automatically " "resized as a 128x128px image, with aspect ratio preserved. " "Use this field in form views or some kanban views.") - image_small = fields.Binary("Small-sized image", + image_64 = fields.Binary("Small-sized image", help="Small-sized logo of the brand. It is automatically " "resized as a 64x64px image, with aspect ratio preserved. " "Use this field anywhere a small image is required.") diff --git a/addons/fleet/views/fleet_vehicle_cost_views.xml b/addons/fleet/views/fleet_vehicle_cost_views.xml index a21159c3611..211c1910020 100644 --- a/addons/fleet/views/fleet_vehicle_cost_views.xml +++ b/addons/fleet/views/fleet_vehicle_cost_views.xml @@ -365,7 +365,7 @@
- +
diff --git a/addons/fleet/views/fleet_vehicle_model_views.xml b/addons/fleet/views/fleet_vehicle_model_views.xml index ecb8741ec98..85bdb4650a9 100644 --- a/addons/fleet/views/fleet_vehicle_model_views.xml +++ b/addons/fleet/views/fleet_vehicle_model_views.xml @@ -6,7 +6,7 @@
- +