diff --git a/openerp/osv/orm.py b/openerp/osv/orm.py
index 6238b77921c..70dc221dafb 100644
--- a/openerp/osv/orm.py
+++ b/openerp/osv/orm.py
@@ -48,6 +48,7 @@ import re
import time
import traceback
import types
+import simplejson
import openerp.netsvc as netsvc
from lxml import etree
@@ -71,6 +72,76 @@ module_class_list = {}
# Super-user identifier (aka Administrator aka root)
ROOT_USER_ID = 1
+def transfer_field_to_modifiers(field, modifiers):
+ for a in ('invisible', 'readonly', 'required'):
+ if field.get(a):
+ modifiers[a] = field.get(a)
+
+
+# Don't deal with groups, it is done by check_group().
+def transfer_node_to_modifiers(node, modifiers):
+ if node.get('attrs'):
+ modifiers.update(eval(node.get('attrs')))
+
+ if node.get('states'):
+ # TODO combine with AND or OR, use implicit AND for now.
+ modifiers.setdefault('invisible', [])\
+ .append(('state', 'not in', node.get('states').split(',')))
+
+ for a in ('invisible', 'readonly', 'required'):
+ if node.get(a):
+ try:
+ # TODO only simple expression as it is evaluated server-side
+ modifiers[a] = bool(eval(node.get(a)))
+ except:
+ print ">>> Can't seem to eval this thing:", node.get(a)
+
+def simplify_modifiers(modifiers):
+ for a in ('invisible', 'readonly', 'required'):
+ if a in modifiers and not modifiers[a]:
+ del modifiers[a]
+
+
+def transfer_modifiers_to_node(modifiers, node):
+ if modifiers:
+ simplify_modifiers(modifiers)
+ node.set('modifiers', simplejson.dumps(modifiers))
+
+
+def test_modifiers(what, expected):
+ modifiers = {}
+ if isinstance(what, basestring):
+ node = etree.fromstring(what)
+ transfer_node_to_modifiers(node, modifiers)
+ simplify_modifiers(modifiers)
+ json = simplejson.dumps(modifiers)
+ assert json == expected, "%s != %s" % (json, expected)
+ elif isinstance(what, dict):
+ transfer_field_to_modifiers(what, modifiers)
+ simplify_modifiers(modifiers)
+ json = simplejson.dumps(modifiers)
+ assert json == expected, "%s != %s" % (json, expected)
+
+
+def tests():
+ test_modifiers('', '{}')
+ test_modifiers('', '{"invisible": true}')
+ test_modifiers('', '{"readonly": true}')
+ test_modifiers('', '{"required": true}')
+ test_modifiers('', '{}')
+ test_modifiers('', '{}')
+ test_modifiers('', '{}')
+ test_modifiers('', '{"invisible": true, "required": true}') # TODO order is not guaranteed
+ test_modifiers('', '{"invisible": true}')
+ test_modifiers('', '{"required": true}')
+ test_modifiers("""""", '{"invisible": [["b", "=", "c"]]}')
+
+ # The dictionary is supposed to be the result of fields_get().
+ test_modifiers({}, '{}')
+ test_modifiers({"invisible": True}, '{"invisible": true}')
+ test_modifiers({"invisible": False}, '{}')
+
+
def check_object_name(name):
""" Check if the given name is a valid openerp object name.
@@ -1343,8 +1414,6 @@ class orm_template(object):
children = True
modifiers = {}
- if node.get('attrs'):
- modifiers = eval(node.get('attrs')) # get the attrs before they are (possibly) deleted by check_group below
def encode(s):
if isinstance(s, unicode):
@@ -1359,7 +1428,7 @@ class orm_template(object):
can_see = any(access_pool.check_groups(cr, user, group) for group in groups)
if not can_see:
node.set('invisible', '1')
- modifiers.setdefault('invisible', '1')
+ modifiers['invisible'] = True
if 'attrs' in node.attrib:
del(node.attrib['attrs']) #avoid making field visible later
del(node.attrib['groups'])
@@ -1432,13 +1501,9 @@ class orm_template(object):
fields[node.get('name')] = attrs
# TODO a true fields_get is unnecessary (no need for the translation)
+ # TODO do this in _view_look_dom_arch instead of here
field = self.fields_get(cr, user, [node.get('name')], context)[node.get('name')]
- for a in ('invisible', 'readonly', 'required'):
- if field.get(a):
- modifiers[a] = field.get(a)
- # The view architeture overrides the python model.
- if node.get(a):
- modifiers[a] = node.get(a)
+ transfer_field_to_modifiers(field, modifiers)
elif node.tag in ('form', 'tree'):
result = self.view_header_get(cr, user, False, node.tag, context)
@@ -1452,6 +1517,12 @@ class orm_template(object):
check_group(node)
+ # The view architeture overrides the python model.
+ # Get the attrs before they are (possibly) deleted by check_group below
+ transfer_node_to_modifiers(node, modifiers)
+
+ # TODO remove attrs couterpart in modifiers when invisible is true ?
+
# translate view
if 'lang' in context:
if node.get('string') and not result:
@@ -1479,8 +1550,7 @@ class orm_template(object):
if children or (node.tag == 'field' and f.tag in ('filter','separator')):
fields.update(self.__view_look_dom(cr, user, f, view_id, context))
- if modifiers:
- node.set('modifiers', str(modifiers))
+ transfer_modifiers_to_node(modifiers, node)
return fields
def _disable_workflow_buttons(self, cr, user, node):