diff --git a/doc/graph.t2t b/doc/graph.t2t
new file mode 100644
index 0000000000..ff5063ba2e
--- /dev/null
+++ b/doc/graph.t2t
@@ -0,0 +1,47 @@
+
+== Graph view ==
+
+The dtd that describe the xml for a graph view is stored in trytond/ir/ui/graph.dtd.
+
+* XML description:
+
+- tag "graph":
+
+ - "type": vbar, hbar, line, pie
+
+ - "string": the name of the graph
+
+ - "background": an hexaecimal value for the color of the background
+
+ - "color": the main color
+
+ - "legend": a boolean to specify if the legend must be display
+
+- tag "x", "y":
+
+ Describe the field that must be used for axis.
+ "x" must contain only one tag "field" and "y" must at least one but may contain many.
+
+- tag "field":
+
+ - "name": the name of the field on the object to use
+
+ - "string": allow to override the string that comes from the object
+
+ - "key": can be used to distinguish fields with the same name but that are different with domain
+
+ - "domain": a string that is evaluate with the object value as context. If the result is true the field value is added to the graph otherwise not
+
+ - "fill": defined if the graph must be fill
+
+
+* Example:
+
+
+
+
+
+
+
+
+
diff --git a/trytond/ir/default.py b/trytond/ir/default.py
index ff48bfbc10..4e29b90377 100644
--- a/trytond/ir/default.py
+++ b/trytond/ir/default.py
@@ -1,5 +1,6 @@
"Default"
from trytond.osv import fields, OSV
+from decimal import Decimal
class Default(OSV):
@@ -37,6 +38,8 @@ class Default(OSV):
test_clause = False
continue
break
+ ctx = {}
+ ctx['Decimal'] = Decimal
for default in self.browse(cursor, user, default_ids, context=context):
if default.field.name not in res:
res[default.field.name] = eval(default.value)
diff --git a/trytond/ir/ui/board.dtd b/trytond/ir/ui/board.dtd
new file mode 100644
index 0000000000..7053fda7b7
--- /dev/null
+++ b/trytond/ir/ui/board.dtd
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/trytond/ir/ui/form.dtd b/trytond/ir/ui/form.dtd
new file mode 100644
index 0000000000..9247bc527b
--- /dev/null
+++ b/trytond/ir/ui/form.dtd
@@ -0,0 +1,92 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/trytond/ir/ui/graph.dtd b/trytond/ir/ui/graph.dtd
new file mode 100644
index 0000000000..24bf60eb4f
--- /dev/null
+++ b/trytond/ir/ui/graph.dtd
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/trytond/ir/ui/tree.dtd b/trytond/ir/ui/tree.dtd
new file mode 100644
index 0000000000..751424b487
--- /dev/null
+++ b/trytond/ir/ui/tree.dtd
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/trytond/ir/ui/view.py b/trytond/ir/ui/view.py
index 89ede93c7c..05ec59635f 100644
--- a/trytond/ir/ui/view.py
+++ b/trytond/ir/ui/view.py
@@ -2,6 +2,8 @@
from trytond.osv import fields, OSV
from xml import dom
from difflib import SequenceMatcher
+import os
+from trytond.netsvc import Logger, LOG_ERROR, LOG_WARNING
class View(OSV):
@@ -31,8 +33,7 @@ class View(OSV):
]
def default_arch(self, cursor, user, context=None):
- return '\n' \
- '\n\t\n'
+ return ''
def default_priority(self, cursor, user, context=None):
return 16
@@ -59,6 +60,24 @@ class View(OSV):
('db_id', 'in', ids),
])
for view in views:
+ logger = Logger()
+ try:
+ from Ft.Xml.Domlette import ValidatingReader
+ xml = '\n\n'\
+ % (view.inherit and 'data' or view.type,
+ os.path.dirname(__file__),
+ view.inherit and view.inherit.type or view.type)
+ xml += view.arch.strip()
+ try:
+ ValidatingReader.parseString(xml)
+ except Exception, exception:
+ logger.notify_channel('ir', LOG_ERROR,
+ 'Invalid xml view: %s' % (str(exception)))
+ return False
+ except:
+ logger.notify_channel('ir', LOG_WARNING,
+ 'Could not import Ft.Xml.Domlette, please install 4Suite ' \
+ 'to have xml validation')
try:
document = dom.minidom.parseString(view.arch)
except:
diff --git a/trytond/osv/orm.py b/trytond/osv/orm.py
index bf7efd1383..d8da2b7873 100644
--- a/trytond/osv/orm.py
+++ b/trytond/osv/orm.py
@@ -1208,6 +1208,9 @@ class ORM(object):
obj = self.pool.get(fld_def._obj)
if not obj.search(cursor, user, [('id', '=', field_value)]):
continue
+ if isinstance(field_value, (int, long)):
+ field_value = obj.name_get(cursor, user, field_value,
+ context=context)[0]
if fld_def._type in ('many2many'):
obj = self.pool.get(fld_def._obj)
field_value2 = []
@@ -1220,7 +1223,7 @@ class ORM(object):
if fld_def._type in ('one2many'):
obj = self.pool.get(fld_def._obj)
field_value2 = []
- for i in range(len(field_value)):
+ for i in range(len(field_value or [])):
field_value2.append({})
for field2 in field_value[i]:
if obj._columns[field2]._type \
@@ -1229,12 +1232,41 @@ class ORM(object):
if not obj2.search(cursor, user,
[('id', '=', field_value[i][field2])]):
continue
+ if isinstance(field_value[i][field2],
+ (int, long)):
+ field_value[i][field2] = obj2.name_get(
+ cursor, user,
+ field_value[i][field2],
+ context=context)[0]
# TODO add test for many2many and one2many
field_value2[i][field2] = field_value[i][field2]
field_value = field_value2
value[field] = field_value
+ value = self._default_on_change(cursor, user, value, context=context)
return value
+ def _default_on_change(self, cursor, user, value, context=None):
+ res = value.copy()
+ val = {}
+ for i in self._inherits.keys():
+ val.update(self.pool.get(i)._default_on_change(cursor, user,
+ value, context=context))
+ for field in value.keys():
+ if field in self._columns:
+ if self._columns[field].on_change:
+ args = {}
+ for arg in self._columns[field].on_change:
+ args[arg] = value.get(arg, False)
+ val.update(getattr(self, 'on_change_' + field)(cursor, user,
+ [], args, context=context))
+ if self._columns[field]._type in ('many2many', 'one2many'):
+ obj = self.pool.get(self._columns[field]._obj)
+ for val2 in res[field]:
+ val2.update(obj._default_on_change(cursor, user,
+ val, context=context))
+ res.update(val)
+ return res
+
def unlink(self, cursor, user, ids, context=None):
if context is None:
context = {}
diff --git a/trytond/res/user.py b/trytond/res/user.py
index 739bfc1c08..eb8d634f6e 100644
--- a/trytond/res/user.py
+++ b/trytond/res/user.py
@@ -19,7 +19,8 @@ class User(OSV):
#address_id = fields.Many2One('res.partner.address', 'Address')
active = fields.Boolean('Active')
action = fields.Many2One('ir.action', 'Home Action')
- menu = fields.Many2One('ir.action', 'Menu Action')
+ menu = fields.Many2One('ir.action', 'Menu Action',
+ domain=[('usage','=','menu')], required=True)
groups = fields.Many2Many('res.group', 'res_group_user_rel',
'uid', 'gid', 'Groups')
rule_groups = fields.Many2Many('ir.rule.group', 'user_rule_group_rel',
diff --git a/trytond/res/user.xml b/trytond/res/user.xml
index d5842f1c42..fd31e00528 100644
--- a/trytond/res/user.xml
+++ b/trytond/res/user.xml
@@ -33,9 +33,7 @@
-
+