diff --git a/setup.py b/setup.py
index 3a735e7d4c..1f19b80136 100644
--- a/setup.py
+++ b/setup.py
@@ -44,7 +44,7 @@ setup(name=PACKAGE,
'trytond': ['init.sql'],
'trytond.ir': ['*.xml'],
'trytond.ir.module': ['*.xml'],
- 'trytond.ir.ui': ['*.xml', '*.dtd'],
+ 'trytond.ir.ui': ['*.xml', '*.rng', '*.rnc'],
'trytond.res': ['*.xml'],
'trytond.webdav': ['*.xml'],
'trytond.workflow': ['*.xml'],
diff --git a/trytond/ir/property.py b/trytond/ir/property.py
index 77bf2468f8..774a622560 100644
--- a/trytond/ir/property.py
+++ b/trytond/ir/property.py
@@ -7,38 +7,16 @@ class Property(OSV):
"Property"
_name = 'ir.property'
_description = __doc__
- name = fields.Char('Name', size=128)
+ name = fields.Char('Name')
#TODO add function field for other type than many2one
- value = fields.Reference('Value', selection='models_get2', size=128)
- res = fields.Reference('Resource', selection='models_get', size=128)
+ value = fields.Reference('Value', selection='models_get')
+ res = fields.Reference('Resource', selection='models_get')
field = fields.Many2One('ir.model.field', 'Field',
- ondelete='cascade', required=True)
-
- def models_get2(self, cursor, user, context=None):
- model_field_obj = self.pool.get('ir.model.field')
- #TODO add domain for only reference fields
- ids = model_field_obj.search(cursor, user, [])
- res = []
- done = {}
- for model_field in model_field_obj.browse(cursor, user, ids,
- context=context):
- if model_field.relation not in done:
- res.append([model_field.relation, model_field.relation])
- done[model_field.relation] = True
- return res
+ ondelete='CASCADE', required=True)
def models_get(self, cursor, user, context=None):
- model_field_obj = self.pool.get('ir.model.field')
- #TODO add domain for only reference fields
- ids = model_field_obj.search(cursor, user, [])
- res = []
- done = {}
- for model_field in model_field_obj.browse(cursor, user, ids,
- context=context):
- if model_field.model.id not in done:
- res.append([model_field.model.model,
- model_field.model.name])
- done[model_field.model.id] = True
+ cursor.execute('SELECT model, name FROM ir_model ORDER BY name ASC')
+ res = cursor.fetchall() + [('', '')]
return res
def get(self, cursor, user, name, model, res_ids=None, context=None):
diff --git a/trytond/ir/ui/board.dtd b/trytond/ir/ui/board.dtd
deleted file mode 100644
index 204f4b03a9..0000000000
--- a/trytond/ir/ui/board.dtd
+++ /dev/null
@@ -1,57 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/trytond/ir/ui/board.rnc b/trytond/ir/ui/board.rnc
new file mode 100644
index 0000000000..9bd3d79d56
--- /dev/null
+++ b/trytond/ir/ui/board.rnc
@@ -0,0 +1,145 @@
+namespace a = "http://relaxng.org/ns/compatibility/annotations/1.0"
+
+board =
+ element board {
+ attlist.board,
+ (image
+ | separator
+ | labe
+ | newline
+ | notebook
+ | group
+ | hpaned
+ | vpaned
+ | action)*
+ }
+attlist.board &=
+ [ a:defaultValue = "Unknown" ] attribute string { text }?
+attlist.board &= [ a:defaultValue = "4" ] attribute col { text }?
+image = element image { attlist.image, empty }
+attlist.image &= attribute name { text }
+attlist.image &= [ a:defaultValue = "1" ] attribute colspan { text }?
+attlist.image &=
+ [ a:defaultValue = "0" ] attribute expand { "0" | "1" }?
+attlist.image &= [ a:defaultValue = "0" ] attribute fill { "0" | "1" }?
+attlist.image &= attribute help { text }?
+attlist.image &= attribute states { text }?
+separator = element separator { attlist.separator, empty }
+attlist.separator &= [ a:defaultValue = "" ] attribute string { text }?
+attlist.separator &= attribute name { text }?
+attlist.separator &= attribute states { text }?
+attlist.separator &=
+ [ a:defaultValue = "0.0" ] attribute align { text }?
+attlist.separator &=
+ [ a:defaultValue = "1" ] attribute colspan { text }?
+attlist.separator &=
+ [ a:defaultValue = "0" ] attribute expand { "0" | "1" }?
+attlist.separator &=
+ [ a:defaultValue = "0" ] attribute fill { "0" | "1" }?
+attlist.separator &= attribute help { text }?
+label = element label { attlist.label, empty }
+attlist.label &= [ a:defaultValue = "" ] attribute string { text }?
+attlist.label &= attribute name { text }?
+attlist.label &= attribute states { text }?
+attlist.label &= [ a:defaultValue = "0.0" ] attribute align { text }?
+attlist.label &=
+ [ a:defaultValue = "0" ] attribute expand { "0" | "1" }?
+attlist.label &= [ a:defaultValue = "0" ] attribute fill { "0" | "1" }?
+attlist.label &=
+ [ a:defaultValue = "0" ] attribute xexpand { "0" | "1" }?
+attlist.label &= [ a:defaultValue = "1" ] attribute xfill { "0" | "1" }?
+attlist.label &= [ a:defaultValue = "1" ] attribute colspan { text }?
+attlist.label &= attribute help { text }?
+newline = element newline { attlist.newline, empty }
+attlist.newline &= empty
+notebook = element notebook { attlist.notebook, page* }
+attlist.notebook &=
+ attribute tabpos { "up" | "down" | "left" | "right" }?
+attlist.notebook &= [ a:defaultValue = "4" ] attribute colspan { text }?
+page =
+ element page {
+ attlist.page,
+ (image
+ | separator
+ | labe
+ | newline
+ | notebook
+ | group
+ | hpaned
+ | vpaned
+ | action)*
+ }
+attlist.page &= attribute angle { text }?
+attlist.page &=
+ [ a:defaultValue = "Unknown" ] attribute string { text }?
+attlist.page &= [ a:defaultValue = "4" ] attribute col { text }?
+group =
+ element group {
+ attlist.group,
+ (image
+ | separator
+ | labe
+ | newline
+ | notebook
+ | group
+ | hpaned
+ | vpaned
+ | action)*
+ }
+attlist.group &= attribute string { text }?
+attlist.group &= [ a:defaultValue = "1" ] attribute colspan { text }?
+attlist.group &=
+ [ a:defaultValue = "0" ] attribute expand { "0" | "1" }?
+attlist.group &= [ a:defaultValue = "1" ] attribute fill { "0" | "1" }?
+attlist.group &= [ a:defaultValue = "1" ] attribute rowspan { text }?
+attlist.group &= [ a:defaultValue = "4" ] attribute col { text }?
+hpaned = element hpaned { attlist.hpaned, child1?, child2? }
+attlist.hpaned &= [ a:defaultValue = "4" ] attribute colspan { text }?
+attlist.hpaned &= attribute position { text }?
+vpaned = element vpaned { attlist.vpaned, child1?, child2? }
+attlist.vpaned &= [ a:defaultValue = "4" ] attribute colspan { text }?
+attlist.vpaned &= attribute position { text }?
+child1 =
+ element child1 {
+ attlist.child1,
+ (image
+ | separator
+ | labe
+ | newline
+ | notebook
+ | group
+ | hpaned
+ | vpaned
+ | action)*
+ }
+attlist.child1 &= empty
+child2 =
+ element child2 {
+ attlist.child2,
+ (image
+ | separator
+ | labe
+ | newline
+ | notebook
+ | group
+ | hpaned
+ | vpaned
+ | action)*
+ }
+attlist.child2 &= empty
+data = element data { attlist.data, xpath+ }
+attlist.data &= empty
+xpath = element xpath { attlist.xpath, any }
+attlist.xpath &= attribute expr { text }
+attlist.xpath &=
+ [ a:defaultValue = "inside" ]
+ attribute position { "inside" | "replace" | "after" | "before" }?
+action |= notAllowed
+labe |= notAllowed
+start = data | board | label
+any =
+ (element * {
+ attribute * { text }*,
+ any
+ }
+ | text)*
diff --git a/trytond/ir/ui/board.rng b/trytond/ir/ui/board.rng
new file mode 100644
index 0000000000..8534f60a4d
--- /dev/null
+++ b/trytond/ir/ui/board.rng
@@ -0,0 +1,477 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0
+ 1
+
+
+
+
+
+
+
+
+ 0
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0
+ 1
+
+
+
+
+
+
+
+
+ 0
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0
+ 1
+
+
+
+
+
+
+
+
+ 0
+ 1
+
+
+
+
+
+
+
+
+ 0
+ 1
+
+
+
+
+
+
+
+
+ 0
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ up
+ down
+ left
+ right
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0
+ 1
+
+
+
+
+
+
+
+
+ 0
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ inside
+ replace
+ after
+ before
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/trytond/ir/ui/form.dtd b/trytond/ir/ui/form.dtd
deleted file mode 100644
index 461241e7ad..0000000000
--- a/trytond/ir/ui/form.dtd
+++ /dev/null
@@ -1,106 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/trytond/ir/ui/form.rnc b/trytond/ir/ui/form.rnc
new file mode 100644
index 0000000000..961262ee11
--- /dev/null
+++ b/trytond/ir/ui/form.rnc
@@ -0,0 +1,256 @@
+namespace a = "http://relaxng.org/ns/compatibility/annotations/1.0"
+
+form =
+ element form {
+ attlist.form,
+ (label
+ | field
+ | image
+ | separator
+ | newline
+ | button
+ | notebook
+ | group
+ | hpaned
+ | vpaned
+ | properties)*
+ }
+attlist.form &=
+ [ a:defaultValue = "Unknown" ] attribute string { text }?
+attlist.form &= attribute on_write { text }?
+attlist.form &= [ a:defaultValue = "4" ] attribute col { text }?
+attlist.form &= attribute cursor { text }?
+
+tree = element tree { attlist.tree, field+ }
+attlist.tree &=
+ [ a:defaultValue = "Unknown" ] attribute string { text }?
+attlist.tree &= attribute on_write { text }?
+attlist.tree &= attribute editable { "top" | "bottom" }?
+attlist.tree &= attribute sequence { text }?
+attlist.tree &= attribute colors { text }?
+
+graph = element graph { attlist.graph, x, y }
+attlist.graph &=
+ [ a:defaultValue = "vbar" ]
+ attribute type { "vbar" | "hbar" | "line" | "pie" }?
+attlist.graph &=
+ [ a:defaultValue = "Unknown" ] attribute string { text }?
+attlist.graph &=
+ [ a:defaultValue = "#f5f5f5" ] attribute background { text }?
+attlist.graph &= [ a:defaultValue = "blue" ] attribute color { text }?
+attlist.graph &=
+ [ a:defaultValue = "1" ] attribute legend { "0" | "1" }?
+
+x = element x { attlist.x, field }
+attlist.x &= empty
+
+y = element y { attlist.y, field+ }
+attlist.y &= empty
+
+label = element label { attlist.label, empty }
+attlist.label &= [ a:defaultValue = "" ] attribute string { text }?
+attlist.label &= attribute name { text }?
+attlist.label &= attribute states { text }?
+attlist.label &= [ a:defaultValue = "0.0" ] attribute align { text }?
+attlist.label &=
+ [ a:defaultValue = "0" ] attribute expand { "0" | "1" }?
+attlist.label &= [ a:defaultValue = "0" ] attribute fill { "0" | "1" }?
+attlist.label &=
+ [ a:defaultValue = "0" ] attribute xexpand { "0" | "1" }?
+attlist.label &= [ a:defaultValue = "1" ] attribute xfill { "0" | "1" }?
+attlist.label &= [ a:defaultValue = "1" ] attribute colspan { text }?
+attlist.label &= attribute help { text }?
+
+field = element field { attlist.field, (tree | form | graph)* }
+attlist.field &= attribute name { text }
+attlist.field &= [ a:defaultValue = "1" ] attribute colspan { text }?
+attlist.field &=
+ attribute widget {
+ "date"
+ | "char"
+ | "many2one"
+ | "date"
+ | "one2many"
+ | "selection"
+ | "float"
+ | "numeric"
+ | "float_time"
+ | "interger"
+ | "datetime"
+ | "boolean"
+ | "text"
+ | "url"
+ | "email"
+ | "callto"
+ | "sip"
+ | "sha"
+ | "reference"
+ | "binary"
+ | "many2many"
+ | "image"
+ }?
+attlist.field &= attribute saves { "0" | "1" }?
+attlist.field &= attribute expand { "0" | "1" }?
+attlist.field &= attribute fill { "0" | "1" }?
+attlist.field &= attribute empty { "0" | "1" }?
+attlist.field &=
+ [ a:defaultValue = "1" ] attribute xexpand { "0" | "1" }?
+attlist.field &= [ a:defaultValue = "1" ] attribute xfill { "0" | "1" }?
+attlist.field &= attribute help { text }?
+attlist.field &= attribute width { text }?
+attlist.field &= attribute height { text }?
+attlist.field &= attribute readonly { text }?
+attlist.field &= attribute required { text }?
+attlist.field &=
+ [ a:defaultValue = "0" ] attribute tree_invisible { "0" | "1" }?
+attlist.field &= attribute mode { text }?
+attlist.field &=
+ [ a:defaultValue = "0" ] attribute completion { "0" | "1" }?
+attlist.field &=
+ [ a:defaultValue = "0" ] attribute invisible { "0" | "1" }?
+attlist.field &= attribute sum { text }?
+attlist.field &= attribute key { text }?
+attlist.field &= attribute domain { text }?
+attlist.field &= attribute color { text }?
+image = element image { attlist.image, empty }
+attlist.image &= attribute name { text }
+attlist.image &= [ a:defaultValue = "1" ] attribute colspan { text }?
+attlist.image &=
+ [ a:defaultValue = "0" ] attribute expand { "0" | "1" }?
+attlist.image &= [ a:defaultValue = "0" ] attribute fill { "0" | "1" }?
+attlist.image &= attribute help { text }?
+attlist.image &= attribute states { text }?
+separator = element separator { attlist.separator, empty }
+attlist.separator &= [ a:defaultValue = "" ] attribute string { text }?
+attlist.separator &= attribute name { text }?
+attlist.separator &= attribute states { text }?
+attlist.separator &=
+ [ a:defaultValue = "0.0" ] attribute align { text }?
+attlist.separator &=
+ [ a:defaultValue = "1" ] attribute colspan { text }?
+attlist.separator &=
+ [ a:defaultValue = "0" ] attribute expand { "0" | "1" }?
+attlist.separator &=
+ [ a:defaultValue = "0" ] attribute fill { "0" | "1" }?
+attlist.separator &= attribute help { text }?
+newline = element newline { attlist.newline, empty }
+attlist.newline &= empty
+button = element button { attlist.button, empty }
+attlist.button &= [ a:defaultValue = "1" ] attribute colspan { text }?
+attlist.button &= attribute help { text }?
+attlist.button &=
+ [ a:defaultValue = "Unknown" ] attribute string { text }?
+attlist.button &= attribute icon { text }?
+attlist.button &=
+ [ a:defaultValue = "workflow" ]
+ attribute type { "workflow" | "object" | "action" }?
+attlist.button &= attribute confirm { text }?
+attlist.button &= attribute name { text }
+attlist.button &= attribute states { text }?
+notebook = element notebook { attlist.notebook, page* }
+attlist.notebook &=
+ attribute tabpos { "up" | "down" | "left" | "right" }?
+attlist.notebook &= [ a:defaultValue = "4" ] attribute colspan { text }?
+page =
+ element page {
+ attlist.page,
+ (label
+ | field
+ | image
+ | separator
+ | newline
+ | button
+ | notebook
+ | group
+ | hpaned
+ | vpaned
+ | properties)*
+ }
+attlist.page &= attribute angle { text }?
+attlist.page &=
+ [ a:defaultValue = "Unknown" ] attribute string { text }?
+attlist.page &= [ a:defaultValue = "4" ] attribute col { text }?
+group =
+ element group {
+ attlist.group,
+ (label
+ | field
+ | image
+ | separator
+ | newline
+ | button
+ | notebook
+ | group
+ | hpaned
+ | vpaned
+ | properties)*
+ }
+attlist.group &= attribute string { text }?
+attlist.group &= [ a:defaultValue = "1" ] attribute colspan { text }?
+attlist.group &=
+ [ a:defaultValue = "0" ] attribute expand { "0" | "1" }?
+attlist.group &= [ a:defaultValue = "1" ] attribute fill { "0" | "1" }?
+attlist.group &= [ a:defaultValue = "1" ] attribute rowspan { text }?
+attlist.group &= [ a:defaultValue = "4" ] attribute col { text }?
+
+hpaned = element hpaned { attlist.hpaned, child1?, child2? }
+attlist.hpaned &= [ a:defaultValue = "4" ] attribute colspan { text }?
+attlist.hpaned &= attribute position { text }?
+
+vpaned = element vpaned { attlist.vpaned, child1?, child2? }
+attlist.vpaned &= [ a:defaultValue = "4" ] attribute colspan { text }?
+attlist.vpaned &= attribute position { text }?
+
+child1 =
+ element child1 {
+ attlist.child1,
+ (label
+ | field
+ | image
+ | separator
+ | newline
+ | button
+ | notebook
+ | group
+ | hpaned
+ | vpaned
+ | properties)*
+ }
+attlist.child1 &= empty
+
+child2 =
+ element child2 {
+ attlist.child2,
+ (label
+ | field
+ | image
+ | separator
+ | newline
+ | button
+ | notebook
+ | group
+ | hpaned
+ | vpaned
+ | properties)*
+ }
+attlist.child2 &= empty
+
+properties = element properties { attlist.properties, empty }
+attlist.properties &= empty
+
+data = element data { attlist.data, xpath+ }
+attlist.data &= empty
+
+xpath = element xpath { attlist.xpath, any }
+attlist.xpath &= attribute expr { text }
+attlist.xpath &=
+ [ a:defaultValue = "inside" ]
+ attribute position { "inside" | "replace" | "after" | "before" }?
+
+any =
+ (element * {
+ attribute * { text }*,
+ any
+ }
+ | text)*
+start = data | form
diff --git a/trytond/ir/ui/form.rng b/trytond/ir/ui/form.rng
new file mode 100644
index 0000000000..439c6ca690
--- /dev/null
+++ b/trytond/ir/ui/form.rng
@@ -0,0 +1,841 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ top
+ bottom
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ vbar
+ hbar
+ line
+ pie
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0
+ 1
+
+
+
+
+
+
+
+
+ 0
+ 1
+
+
+
+
+
+
+
+
+ 0
+ 1
+
+
+
+
+
+
+
+
+ 0
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ date
+ char
+ many2one
+ date
+ one2many
+ selection
+ float
+ numeric
+ float_time
+ interger
+ datetime
+ boolean
+ text
+ url
+ email
+ callto
+ sip
+ sha
+ reference
+ binary
+ many2many
+ image
+
+
+
+
+
+
+
+
+ 0
+ 1
+
+
+
+
+
+
+
+
+ 0
+ 1
+
+
+
+
+
+
+
+
+ 0
+ 1
+
+
+
+
+
+
+
+
+ 0
+ 1
+
+
+
+
+
+
+
+
+ 0
+ 1
+
+
+
+
+
+
+
+
+ 0
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0
+ 1
+
+
+
+
+
+
+
+
+ 0
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0
+ 1
+
+
+
+
+
+
+
+
+ 0
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0
+ 1
+
+
+
+
+
+
+
+
+ 0
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ workflow
+ object
+ action
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ up
+ down
+ left
+ right
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0
+ 1
+
+
+
+
+
+
+
+
+ 0
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ inside
+ replace
+ after
+ before
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/trytond/ir/ui/graph.dtd b/trytond/ir/ui/graph.dtd
deleted file mode 100644
index 396512c75d..0000000000
--- a/trytond/ir/ui/graph.dtd
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/trytond/ir/ui/graph.rnc b/trytond/ir/ui/graph.rnc
new file mode 100644
index 0000000000..4b299e786e
--- /dev/null
+++ b/trytond/ir/ui/graph.rnc
@@ -0,0 +1,40 @@
+namespace a = "http://relaxng.org/ns/compatibility/annotations/1.0"
+
+graph = element graph { attlist.graph, x, y }
+attlist.graph &=
+ [ a:defaultValue = "vbar" ]
+ attribute type { "vbar" | "hbar" | "line" | "pie" }?
+attlist.graph &=
+ [ a:defaultValue = "Unknown" ] attribute string { text }?
+attlist.graph &=
+ [ a:defaultValue = "#f5f5f5" ] attribute background { text }?
+attlist.graph &= [ a:defaultValue = "blue" ] attribute color { text }?
+attlist.graph &=
+ [ a:defaultValue = "1" ] attribute legend { "0" | "1" }?
+x = element x { attlist.x, field }
+attlist.x &= empty
+y = element y { attlist.y, field+ }
+attlist.y &= empty
+field = element field { attlist.field, empty }
+attlist.field &= attribute name { text }
+attlist.field &= attribute string { text }?
+attlist.field &= attribute key { text }?
+attlist.field &= attribute domain { text }?
+attlist.field &= attribute fill { "0" | "1" }?
+attlist.field &= attribute empty { "0" | "1" }?
+attlist.field &= attribute color { text }?
+attlist.field &= attribute widget { "float_time" }?
+data = element data { attlist.data, xpath+ }
+attlist.data &= empty
+xpath = element xpath { attlist.xpath, any }
+attlist.xpath &= attribute expr { text }
+attlist.xpath &=
+ [ a:defaultValue = "inside" ]
+ attribute position { "inside" | "replace" | "after" | "before" }?
+start = data | graph
+any =
+ (element * {
+ attribute * { text }*,
+ any
+ }
+ | text)*
diff --git a/trytond/ir/ui/graph.rng b/trytond/ir/ui/graph.rng
new file mode 100644
index 0000000000..22efa7454b
--- /dev/null
+++ b/trytond/ir/ui/graph.rng
@@ -0,0 +1,177 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ vbar
+ hbar
+ line
+ pie
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0
+ 1
+
+
+
+
+
+
+
+
+ 0
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+ float_time
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ inside
+ replace
+ after
+ before
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/trytond/ir/ui/tree.dtd b/trytond/ir/ui/tree.dtd
deleted file mode 100644
index 81a82650f3..0000000000
--- a/trytond/ir/ui/tree.dtd
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/trytond/ir/ui/tree.rnc b/trytond/ir/ui/tree.rnc
new file mode 100644
index 0000000000..c54f8615c1
--- /dev/null
+++ b/trytond/ir/ui/tree.rnc
@@ -0,0 +1,55 @@
+namespace a = "http://relaxng.org/ns/compatibility/annotations/1.0"
+
+tree = element tree { attlist.tree, field+ }
+attlist.tree &=
+ [ a:defaultValue = "Unknown" ] attribute string { text }?
+attlist.tree &= attribute on_write { text }?
+attlist.tree &= attribute editable { "top" | "bottom" }?
+attlist.tree &= attribute sequence { text }?
+attlist.tree &= attribute colors { text }?
+attlist.tree &=
+ [ a:defaultValue = "0" ] attribute toolbar { "0" | "1" }?
+field = element field { attlist.field, empty }
+attlist.field &= attribute name { text }
+attlist.field &= attribute readonly { text }?
+attlist.field &= attribute required { text }?
+attlist.field &=
+ attribute widget {
+ "char"
+ | "many2one"
+ | "date"
+ | "one2many"
+ | "selection"
+ | "float"
+ | "numeric"
+ | "float_time"
+ | "interger"
+ | "datetime"
+ | "boolean"
+ | "text"
+ | "url"
+ | "email"
+ | "callto"
+ | "sip"
+ }?
+attlist.field &=
+ [ a:defaultValue = "0" ] attribute select { "0" | "1" | "2" }?
+attlist.field &=
+ [ a:defaultValue = "0" ] attribute tree_invisible { "0" | "1" }?
+attlist.field &= attribute icon { text }?
+attlist.field &= attribute sum { text }?
+attlist.field &= attribute width { text }?
+data = element data { attlist.data, xpath+ }
+attlist.data &= empty
+xpath = element xpath { attlist.xpath, any }
+attlist.xpath &= attribute expr { text }
+attlist.xpath &=
+ [ a:defaultValue = "inside" ]
+ attribute position { "inside" | "replace" | "after" | "before" }?
+start = tree | data
+any =
+ (element * {
+ attribute * { text }*,
+ any
+ }
+ | text)*
diff --git a/trytond/ir/ui/tree.rng b/trytond/ir/ui/tree.rng
new file mode 100644
index 0000000000..3e240937e7
--- /dev/null
+++ b/trytond/ir/ui/tree.rng
@@ -0,0 +1,184 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ top
+ bottom
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ char
+ many2one
+ date
+ one2many
+ selection
+ float
+ numeric
+ float_time
+ interger
+ datetime
+ boolean
+ text
+ url
+ email
+ callto
+ sip
+
+
+
+
+
+
+
+
+ 0
+ 1
+ 2
+
+
+
+
+
+
+
+
+ 0
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ inside
+ replace
+ after
+ before
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/trytond/ir/ui/view.py b/trytond/ir/ui/view.py
index 9c54dbb18a..445eeaea4e 100644
--- a/trytond/ir/ui/view.py
+++ b/trytond/ir/ui/view.py
@@ -56,17 +56,20 @@ class View(OSV):
trans_views[trans['name']][trans['src']] = trans
for view in views:
xml = view.arch.strip()
- dtd_name = os.path.join(os.path.dirname(__file__),
- (view.inherit and view.inherit.type or view.type) + '.dtd')
- dtd = etree.DTD(file(dtd_name))
tree = etree.fromstring(xml)
- if not dtd.validate(tree):
- logger = Logger()
- error_log = reduce(lambda x, y: str(x) + '\n' + str(y),
- dtd.error_log.filter_from_errors())
- logger.notify_channel('ir', LOG_ERROR,
- 'Invalid xml view:\n%s' % (error_log + '\n' + xml))
- return False
+
+ # validate the tree using RelaxNG
+ rng_name = os.path.join(os.path.dirname(__file__),
+ (view.inherit and view.inherit.type or view.type) + '.rng')
+ if hasattr(etree, 'RelaxNG'):
+ validator = etree.RelaxNG(file=rng_name)
+ if not validator.validate(tree):
+ logger = Logger()
+ error_log = reduce(lambda x, y: str(x) + '\n' + str(y),
+ validator.error_log.filter_from_errors())
+ logger.notify_channel('ir', LOG_ERROR,
+ 'Invalid xml view:\n%s' % (error_log + '\n' + xml))
+ return False
root_element = tree.getroottree().getroot()
strings = self._translate_view(root_element)
view_ids = self.search(cursor, 0, [
diff --git a/trytond/osv/orm.py b/trytond/osv/orm.py
index ac21107139..c1a5cca64c 100644
--- a/trytond/osv/orm.py
+++ b/trytond/osv/orm.py
@@ -1128,7 +1128,7 @@ class ORM(object):
' FROM ' + table_query + '\"' + self._table +'\" ' \
'WHERE id IN ' \
'(' + ','.join([str(x) for x in sub_ids]) + ')'\
- ' AND ' + domain1 + ' ORDER BY ' + \
+ ' AND (' + domain1 + ') ORDER BY ' + \
','.join([self._table + '.' + x[0] + ' ' + x[1] \
for x in self._order])),
table_args + domain2)
@@ -1365,7 +1365,7 @@ class ORM(object):
domain1, domain2 = self.pool.get('ir.rule').domain_get(cursor, user,
self._name)
if domain1:
- domain1 = ' AND ' + domain1
+ domain1 = ' AND (' + domain1 + ') '
for i in range((len(ids) / ID_MAX) + \
((len(ids) % ID_MAX) and 1 or 0)):
sub_ids = ids[ID_MAX * i:ID_MAX * (i + 1)]
@@ -1491,7 +1491,7 @@ class ORM(object):
domain1, domain2 = self.pool.get('ir.rule').domain_get(cursor,
user, self._name)
if domain1:
- domain1 = ' and ' + domain1
+ domain1 = ' AND (' + domain1 + ') '
for i in range((len(ids) / ID_MAX) + \
((len(ids) % ID_MAX) and 1 or 0)):
sub_ids = ids[ID_MAX * i:ID_MAX * (i + 1)]
@@ -1964,7 +1964,7 @@ class ORM(object):
if next is not None:
for child in element2:
index = parent.index(next)
- parent.insert(index - 1, child)
+ parent.insert(index, child)
else:
parent.extend(element2.getchildren())
elif pos == 'before':
diff --git a/trytond/report/report.py b/trytond/report/report.py
index 8af3ad0c61..394e7e86ff 100644
--- a/trytond/report/report.py
+++ b/trytond/report/report.py
@@ -18,6 +18,12 @@ import time
import os
import datetime
+if not hasattr(locale, 'nl_langinfo'):
+ locale.nl_langinfo = lambda *a: '%x'
+
+if not hasattr(locale, 'D_FMT'):
+ locale.D_FMT = None
+
MODULE_LIST = []
MODULE_CLASS_LIST = {}
CLASS_POOL = {}
@@ -537,17 +543,25 @@ class Report(object):
(self._name,
localcontext.get('language', False) or 'en_US'))
if date:
- # length of date like 2001-01-01 is ten:
- if len(str(value)) == 10:
- locale_format = locale.D_FMT
- string_pattern = '%Y-%m-%d'
+ if isinstance(value, time.struct_time):
+ locale_format = locale.nl_langinfo(locale.D_FMT)\
+ .replace('%y', '%Y')
+ date = value
else:
- if len(str(value)) > 19:
+ # assume string, parse it
+ if len(str(value)) == 10:
+ # length of date like 2001-01-01 is ten
+ # assume format '%Y-%m-%d'
+ locale_format = locale.nl_langinfo(locale.D_FMT)\
+ .replace('%y', '%Y')
+ string_pattern = '%Y-%m-%d'
+ else:
+ # assume format '%Y-%m-%d %H:%M:%S'
value = str(value)[:19]
- locale_format = locale.D_T_FMT
- string_pattern = '%Y-%m-%d %H:%M:%S'
- date = time.strptime(str(value), string_pattern)
- return time.strftime(locale.nl_langinfo(locale_format).\
- replace('%y', '%Y'), date)
+ locale_format = locale.nl_langinfo(locale.D_FMT)\
+ .replace('%y', '%Y') + ' %H:%M:%S'
+ string_pattern = '%Y-%m-%d %H:%M:%S'
+ date = time.strptime(str(value), string_pattern)
+ return time.strftime(locale_format, date)
return locale.format('%.' + str(digits) + 'f', value, True)
diff --git a/trytond/tryton.dtd b/trytond/tryton.dtd
deleted file mode 100644
index 4134bdfd1e..0000000000
--- a/trytond/tryton.dtd
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/trytond/tryton.rnc b/trytond/tryton.rnc
new file mode 100644
index 0000000000..d8e3b9955b
--- /dev/null
+++ b/trytond/tryton.rnc
@@ -0,0 +1,28 @@
+namespace a = "http://relaxng.org/ns/compatibility/annotations/1.0"
+
+tryton = element tryton { attlist.tryton, data* }
+attlist.tryton &= empty
+data = element data { attlist.data, (record | menuitem)* }
+attlist.data &=
+ [ a:defaultValue = "0" ] attribute noupdate { "0" | "1" }?
+record = element record { attlist.record, field* }
+attlist.record &= attribute model { text }
+attlist.record &= attribute id { text }
+attlist.record &=
+ [ a:defaultValue = "0" ] attribute update { "0" | "1" }?
+field = element field { attlist.field, text }
+attlist.field &= attribute name { text }
+attlist.field &= attribute search { text }?
+attlist.field &= attribute model { text }?
+attlist.field &= attribute ref { text }?
+attlist.field &= attribute eval { text }?
+attlist.field &= attribute type { "xml" }?
+menuitem = element menuitem { attlist.menuitem, empty }
+attlist.menuitem &= attribute id { text }
+attlist.menuitem &= attribute name { text }?
+attlist.menuitem &= attribute icon { text }?
+attlist.menuitem &= attribute sequence { text }?
+attlist.menuitem &= attribute parent { text }?
+attlist.menuitem &= attribute action { text }?
+attlist.menuitem &= attribute groups { text }?
+start = tryton
diff --git a/trytond/web_service/db.py b/trytond/web_service/db.py
index 64fa47cf45..513e904e9a 100644
--- a/trytond/web_service/db.py
+++ b/trytond/web_service/db.py
@@ -21,6 +21,7 @@ class DB(Service):
self.export_method(self.restore)
self.export_method(self.list)
self.export_method(self.list_lang)
+ self.export_method(self.db_exist)
self.export_method(self.change_admin_password)
def create(self, password, db_name, lang):