[MER] Merging trunk
bzr revid: rim@openerp.com-20131022132053-341j20pmlo4wcgjd
This commit is contained in:
@@ -22,9 +22,9 @@
|
||||
import openerp
|
||||
from openerp import SUPERUSER_ID
|
||||
from openerp import tools
|
||||
from openerp.osv import osv, fields
|
||||
from openerp.osv import orm, fields
|
||||
|
||||
class decimal_precision(osv.osv):
|
||||
class decimal_precision(orm.Model):
|
||||
_name = 'decimal.precision'
|
||||
_columns = {
|
||||
'name': fields.char('Usage', size=50, select=True, required=True),
|
||||
@@ -71,4 +71,29 @@ def get_precision(application):
|
||||
return (16, res)
|
||||
return change_digit
|
||||
|
||||
class DecimalPrecisionFloat(orm.AbstractModel):
|
||||
""" Override qweb.field.float to add a `decimal_precision` domain option
|
||||
and use that instead of the column's own value if it is specified
|
||||
"""
|
||||
_inherit = 'ir.qweb.field.float'
|
||||
|
||||
|
||||
def precision(self, cr, uid, column, options=None, context=None):
|
||||
dp = options and options.get('decimal_precision')
|
||||
if dp:
|
||||
return self.pool['decimal.precision'].precision_get(
|
||||
cr, uid, dp)
|
||||
|
||||
return super(DecimalPrecisionFloat, self).precision(
|
||||
cr, uid, column, options=options, context=context)
|
||||
|
||||
class DecimalPrecisionTestModel(orm.Model):
|
||||
_name = 'decimal.precision.test'
|
||||
|
||||
_columns = {
|
||||
'float': fields.float(),
|
||||
'float_2': fields.float(digits=(16, 2)),
|
||||
'float_4': fields.float(digits=(16, 4)),
|
||||
}
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import test_qweb_float
|
||||
|
||||
checks = [
|
||||
test_qweb_float
|
||||
]
|
||||
@@ -0,0 +1,66 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from openerp.tests import common
|
||||
|
||||
class TestFloatExport(common.TransactionCase):
|
||||
def setUp(self):
|
||||
super(TestFloatExport, self).setUp()
|
||||
self.Model = self.registry('decimal.precision.test')
|
||||
|
||||
def get_converter(self, name):
|
||||
converter = self.registry('ir.qweb.field.float')
|
||||
column = self.Model._all_columns[name].column
|
||||
|
||||
return lambda value, options=None: converter.value_to_html(
|
||||
self.cr, self.uid, value, column, options=options, context=None)
|
||||
|
||||
def test_basic_float(self):
|
||||
converter = self.get_converter('float')
|
||||
self.assertEqual(
|
||||
converter(42.0),
|
||||
"42.0")
|
||||
self.assertEqual(
|
||||
converter(42.12345),
|
||||
"42.12345")
|
||||
|
||||
converter = self.get_converter('float_2')
|
||||
self.assertEqual(
|
||||
converter(42.0),
|
||||
"42.00")
|
||||
self.assertEqual(
|
||||
converter(42.12345),
|
||||
"42.12")
|
||||
|
||||
converter = self.get_converter('float_4')
|
||||
self.assertEqual(
|
||||
converter(42.0),
|
||||
'42.0000')
|
||||
self.assertEqual(
|
||||
converter(42.12345),
|
||||
'42.1234')
|
||||
|
||||
def test_precision_domain(self):
|
||||
DP = self.registry('decimal.precision')
|
||||
DP.create(self.cr, self.uid, {
|
||||
'name': 'A',
|
||||
'digits': 2,
|
||||
})
|
||||
DP.create(self.cr, self.uid, {
|
||||
'name': 'B',
|
||||
'digits': 6,
|
||||
})
|
||||
|
||||
converter = self.get_converter('float')
|
||||
self.assertEqual(
|
||||
converter(42.0, {'decimal_precision': 'A'}),
|
||||
'42.00')
|
||||
self.assertEqual(
|
||||
converter(42.0, {'decimal_precision': 'B'}),
|
||||
'42.000000')
|
||||
|
||||
converter = self.get_converter('float_4')
|
||||
self.assertEqual(
|
||||
converter(42.12345, {'decimal_precision': 'A'}),
|
||||
'42.12')
|
||||
self.assertEqual(
|
||||
converter(42.12345, {'decimal_precision': 'B'}),
|
||||
'42.123450')
|
||||
@@ -39,12 +39,12 @@ class Field(orm.AbstractModel):
|
||||
_inherit = 'ir.qweb.field'
|
||||
|
||||
def attributes(self, cr, uid, field_name, record, options,
|
||||
source_element, g_att, t_att, qweb_context):
|
||||
source_element, g_att, t_att, qweb_context, context=None):
|
||||
column = record._model._all_columns[field_name].column
|
||||
return itertools.chain(
|
||||
super(Field, self).attributes(cr, uid, field_name, record, options,
|
||||
source_element, g_att, t_att,
|
||||
qweb_context),
|
||||
qweb_context, context=context),
|
||||
[('data-oe-translate', 1 if column.translate else 0)]
|
||||
)
|
||||
|
||||
@@ -67,7 +67,27 @@ class Float(orm.AbstractModel):
|
||||
_name = 'website.qweb.field.float'
|
||||
_inherit = ['website.qweb.field', 'ir.qweb.field.float']
|
||||
|
||||
value_from_string = float
|
||||
def from_html(self, cr, uid, model, column, element, context=None):
|
||||
lang = self.user_lang(cr, uid, context=context)
|
||||
|
||||
value = element.text_content().strip()
|
||||
|
||||
return float(value.replace(lang.thousands_sep, '')
|
||||
.replace(lang.decimal_point, '.'))
|
||||
|
||||
class Date(orm.AbstractModel):
|
||||
_name = 'website.qweb.field.date'
|
||||
_inherit = ['website.qweb.field', 'ir.qweb.field.date']
|
||||
|
||||
def from_html(self, cr, uid, model, column, element, context=None):
|
||||
raise NotImplementedError("Can not parse and save localized dates")
|
||||
|
||||
class DateTime(orm.AbstractModel):
|
||||
_name = 'website.qweb.field.datetime'
|
||||
_inherit = ['website.qweb.field', 'ir.qweb.field.datetime']
|
||||
|
||||
def from_html(self, cr, uid, model, column, element, context=None):
|
||||
raise NotImplementedError("Can not parse and save localized datetimes")
|
||||
|
||||
class Text(orm.AbstractModel):
|
||||
_name = 'website.qweb.field.text'
|
||||
@@ -127,7 +147,7 @@ class Image(orm.AbstractModel):
|
||||
_inherit = ['website.qweb.field', 'ir.qweb.field.image']
|
||||
|
||||
def to_html(self, cr, uid, field_name, record, options,
|
||||
source_element, t_att, g_att, qweb_context):
|
||||
source_element, t_att, g_att, qweb_context, context=None):
|
||||
assert source_element.nodeName != 'img',\
|
||||
"Oddly enough, the root tag of an image field can not be img. " \
|
||||
"That is because the image goes into the tag, or it gets the " \
|
||||
@@ -135,9 +155,9 @@ class Image(orm.AbstractModel):
|
||||
|
||||
return super(Image, self).to_html(
|
||||
cr, uid, field_name, record, options,
|
||||
source_element, t_att, g_att, qweb_context)
|
||||
source_element, t_att, g_att, qweb_context, context=context)
|
||||
|
||||
def record_to_html(self, cr, uid, field_name, record, column, options=None):
|
||||
def record_to_html(self, cr, uid, field_name, record, column, options=None, context=None):
|
||||
cls = ''
|
||||
if 'class' in options:
|
||||
cls = ' class="%s"' % werkzeug.utils.escape(options['class'])
|
||||
@@ -183,4 +203,9 @@ class Monetary(orm.AbstractModel):
|
||||
_inherit = ['website.qweb.field', 'ir.qweb.field.monetary']
|
||||
|
||||
def from_html(self, cr, uid, model, column, element, context=None):
|
||||
return float(element.find('span').text)
|
||||
lang = self.user_lang(cr, uid, context=context)
|
||||
|
||||
value = element.find('span').text.strip()
|
||||
|
||||
return float(value.replace(lang.thousands_sep, '')
|
||||
.replace(lang.decimal_point, '.'))
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from urlparse import urlparse
|
||||
|
||||
from lxml import etree, html
|
||||
from openerp.osv import osv, fields
|
||||
|
||||
from openerp.osv import osv, fields
|
||||
from openerp.addons.base import ir
|
||||
|
||||
class view(osv.osv):
|
||||
_inherit = "ir.ui.view"
|
||||
@@ -82,15 +84,39 @@ class view(osv.osv):
|
||||
return out
|
||||
|
||||
def replace_arch_section(self, cr, uid, view_id, section_xpath, replacement, context=None):
|
||||
arch = replacement
|
||||
if section_xpath:
|
||||
previous_arch = etree.fromstring(self.browse(cr, uid, view_id, context=context).arch.encode('utf-8'))
|
||||
# remove branding from replacement section
|
||||
for att in ir.ir_ui_view.MOVABLE_BRANDING:
|
||||
replacement.attrib.pop(att, None)
|
||||
|
||||
if not section_xpath:
|
||||
# replace all of the arch, not just a fragment
|
||||
arch = replacement
|
||||
else:
|
||||
arch = etree.fromstring(self.browse(cr, uid, view_id, context=context).arch.encode('utf-8'))
|
||||
# ensure there's only one match
|
||||
[previous_section] = previous_arch.xpath(section_xpath)
|
||||
[previous_section] = arch.xpath(section_xpath)
|
||||
|
||||
previous_section.getparent().replace(previous_section, replacement)
|
||||
arch = previous_arch
|
||||
|
||||
return arch
|
||||
|
||||
def _normalize_urls(self, element):
|
||||
attr = None
|
||||
if element.tag == 'form':
|
||||
attr = 'action' if 'action' in element.attrib else None
|
||||
elif element.tag in ['a', 'link']:
|
||||
attr = 'href' if 'href' in element.attrib else None
|
||||
elif element.tag in ['frame', 'iframe', 'script']:
|
||||
attr = 'src' if 'src' in element.attrib else None
|
||||
if attr:
|
||||
value = element.attrib[attr]
|
||||
if not urlparse(value).scheme:
|
||||
element.attrib.pop(attr)
|
||||
element.attrib['t-' + attr] = value
|
||||
for el in list(element):
|
||||
self._normalize_urls(el)
|
||||
return element
|
||||
|
||||
def save(self, cr, uid, res_id, value, xpath=None, context=None):
|
||||
""" Update a view section. The view section may embed fields to write
|
||||
|
||||
@@ -103,6 +129,8 @@ class view(osv.osv):
|
||||
arch_section = html.fromstring(
|
||||
value, parser=html.HTMLParser(encoding='utf-8'))
|
||||
|
||||
self._normalize_urls(arch_section)
|
||||
|
||||
if xpath is None:
|
||||
# value is an embedded field on its own, not a view section
|
||||
self.save_embedded_field(cr, uid, arch_section, context=context)
|
||||
|
||||
@@ -386,6 +386,17 @@ class base_language_install(osv.osv):
|
||||
'website_ids': fields.many2many('website', string='Websites to translate'),
|
||||
}
|
||||
|
||||
def default_get(self, cr, uid, fields, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
defaults = super(base_language_install, self).default_get(cr, uid, fields, context)
|
||||
website_id = context.get('params', {}).get('website_id')
|
||||
if website_id:
|
||||
if 'website_ids' not in defaults:
|
||||
defaults['website_ids'] = []
|
||||
defaults['website_ids'].append(website_id)
|
||||
return defaults
|
||||
|
||||
def lang_install(self, cr, uid, ids, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
|
||||
@@ -5,7 +5,10 @@ access_website_converter_test,access_website_converter_test,model_website_conver
|
||||
access_website_converter_test_sub,access_website_converter_test_sub,model_website_converter_test_sub,,1,1,1,1
|
||||
access_website_qweb,access_website_qweb,model_website_qweb,,0,0,0,0
|
||||
access_website_qweb_field,access_website_qweb_field,model_website_qweb_field,,0,0,0,0
|
||||
access_website_qweb_field_integer,access_website_qweb_field_integer,model_website_qweb_field_integer,,0,0,0,0
|
||||
access_website_qweb_field_float,access_website_qweb_field_float,model_website_qweb_field_float,,0,0,0,0
|
||||
access_website_qweb_field_date,access_website_qweb_field_date,model_website_qweb_field_date,,0,0,0,0
|
||||
access_website_qweb_field_datetime,access_website_qweb_field_datetime,model_website_qweb_field_datetime,,0,0,0,0
|
||||
access_website_qweb_field_text,access_website_qweb_field_text,model_website_qweb_field_text,,0,0,0,0
|
||||
access_website_qweb_field_selection,access_website_qweb_field_selection,model_website_qweb_field_selection,,0,0,0,0
|
||||
access_website_qweb_field_many2one,access_website_qweb_field_many2one,model_website_qweb_field_many2one,,0,0,0,0
|
||||
|
||||
|
@@ -350,6 +350,7 @@
|
||||
// The detail attribute indicates the number of times a mouse button has been pressed
|
||||
// we just want the triple click
|
||||
if (e.detail !== 3) { return; }
|
||||
e.preventDefault();
|
||||
|
||||
// Get closest block-level element to the triple-clicked
|
||||
// element (using ckeditor's block list because why not)
|
||||
|
||||
@@ -28,7 +28,7 @@ class TestConvertBack(common.TransactionCase):
|
||||
e.setAttribute('t-field', field_value)
|
||||
|
||||
rendered = self.registry('website.qweb').render_tag_field(
|
||||
e, {'field': field_value}, '', ir_qweb.QWebContext({
|
||||
e, {'field': field_value}, '', ir_qweb.QWebContext(self.cr, self.uid, {
|
||||
'record': record,
|
||||
}))
|
||||
element = html.fromstring(
|
||||
@@ -53,6 +53,7 @@ class TestConvertBack(common.TransactionCase):
|
||||
|
||||
def test_float(self):
|
||||
self.field_roundtrip('float', 42.567890)
|
||||
self.field_roundtrip('float', 324542.567890)
|
||||
|
||||
def test_numeric(self):
|
||||
self.field_roundtrip('numeric', 42.77)
|
||||
|
||||
@@ -111,7 +111,7 @@
|
||||
<a t-att-href="url_for('', lang=lg.code)" role="menuitem">
|
||||
<strong t-att-class="'icon-circle' if lg.code == lang
|
||||
else 'icon-circle-blank'"></strong>
|
||||
<t t-esc="lg.name"/>
|
||||
<t t-esc="lg.name.split('/').pop()"/>
|
||||
</a>
|
||||
</li>
|
||||
<li t-if="editable" class="divider"/>
|
||||
@@ -120,7 +120,7 @@
|
||||
<t t-if="request.httprequest.query_string">
|
||||
<t t-set="url_return" t-value="url_return + '?' + request.httprequest.query_string"/>
|
||||
</t>
|
||||
<a t-attf-href="/web#action=base.action_view_base_language_install&url_return=#{url_return}">
|
||||
<a t-attf-href="/web#action=base.action_view_base_language_install&website_id=#{website.id}&url_return=#{url_return}">
|
||||
Add a language...
|
||||
</a>
|
||||
</li>
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
</div>
|
||||
<div class="oe_product_image text-center">
|
||||
<a t-href="/shop/product/#{ product.id }/" t-keep-query="category,search,facettes">
|
||||
<img class="img" t-att-src="product.img('image')"/>
|
||||
<span t-field="product.image" t-field-options='{"widget": "image"}'/>
|
||||
</a>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
Reference in New Issue
Block a user