diff --git a/bin/addons/base/base_data.xml b/bin/addons/base/base_data.xml
index a2cc3cb6911..8132106130f 100644
--- a/bin/addons/base/base_data.xml
+++ b/bin/addons/base/base_data.xml
@@ -38,17 +38,17 @@
- en_US
- English
+ en_US
+ English
- Andorra, Principality of
- ad
+ Andorra, Principality of
+ ad
- United Arab Emirates
- ae
+ United Arab Emirates
+ ae
Afghanistan, Islamic State of
diff --git a/bin/addons/base/ir/ir_actions.py b/bin/addons/base/ir/ir_actions.py
index d3e3db1a542..93812f0eae5 100644
--- a/bin/addons/base/ir/ir_actions.py
+++ b/bin/addons/base/ir/ir_actions.py
@@ -171,6 +171,7 @@ class act_window(osv.osv):
'context': fields.char('Context Value', size=250),
'res_model': fields.char('Model', size=64),
'src_model': fields.char('Source model', size=64),
+ 'target': fields.selection([('current','Current Window'),('new','New Window')], 'Target Window'),
'view_type': fields.selection((('tree','Tree'),('form','Form')),string='Type of view'),
'view_mode': fields.char('Mode of view', size=250),
'usage': fields.char('Action Usage', size=32),
@@ -186,6 +187,7 @@ class act_window(osv.osv):
'view_mode': lambda *a: 'tree,form',
'context': lambda *a: '{}',
'limit': lambda *a: 80,
+ 'target': lambda *a: 'current',
'auto_refresh': lambda *a: 0,
}
act_window()
@@ -321,3 +323,16 @@ class actions_server(osv.osv):
return False
actions_server()
+class act_window_close(osv.osv):
+ _name = 'ir.actions.act_window_close'
+ _table = 'ir_actions'
+ _sequence = 'ir_actions_id_seq'
+ _columns = {
+ 'name': fields.char('Action Name', size=64, translate=True),
+ 'type': fields.char('Action Type', size=32, required=True),
+ }
+ _defaults = {
+ 'type': lambda *a: 'ir.actions.act_window_close',
+ }
+act_window_close()
+
diff --git a/bin/addons/base/ir/ir_model.py b/bin/addons/base/ir/ir_model.py
index 1e47bc2aa28..bd99acebb80 100644
--- a/bin/addons/base/ir/ir_model.py
+++ b/bin/addons/base/ir/ir_model.py
@@ -40,7 +40,8 @@ def _get_fields_type(self, cr, uid, context=None):
class ir_model(osv.osv):
_name = 'ir.model'
- _rec_name = 'model'
+ _description = "Objects"
+ _rec_name = 'name'
_columns = {
'name': fields.char('Model name', size=64, translate=True),
'model': fields.char('Object name', size=64, required=True, search=1),
@@ -80,9 +81,10 @@ ir_model()
class ir_model_fields(osv.osv):
_name = 'ir.model.fields'
+ _description = "Fields"
_columns = {
'name': fields.char('Name', required=True, size=64, select=1),
- 'model': fields.char('Model Name', size=64, required=True),
+ 'model': fields.char('Object Name', size=64, required=True),
'relation': fields.char('Model Relation', size=64),
'model_id': fields.many2one('ir.model', 'Model id', required=True, select=True, ondelete='cascade'),
'field_description': fields.char('Field Label', required=True, size=256),
diff --git a/bin/addons/base/ir/workflow/workflow_view.xml b/bin/addons/base/ir/workflow/workflow_view.xml
index 601b6a06865..5703643bd48 100644
--- a/bin/addons/base/ir/workflow/workflow_view.xml
+++ b/bin/addons/base/ir/workflow/workflow_view.xml
@@ -61,7 +61,8 @@
-
+
+
@@ -103,6 +104,7 @@
+
diff --git a/bin/osv/fields.py b/bin/osv/fields.py
index 619746e0235..b01ec611648 100644
--- a/bin/osv/fields.py
+++ b/bin/osv/fields.py
@@ -96,7 +96,11 @@ class _column(object):
def set(self, cr, obj, id, name, value, user=None, context=None):
cr.execute('update '+obj._table+' set '+name+'='+self._symbol_set[0]+' where id=%d', (self._symbol_set[1](value),id) )
+ def set_memory(self, cr, obj, id, name, value, user=None, context=None):
+ raise Exception, 'Not implemented set_memory method !'
+ def get_memory(self, cr, obj, ids, name, context=None, values=None):
+ raise Exception, 'Not implemented get_memory method !'
def get(self, cr, obj, ids, name, context=None, values=None):
raise Exception, 'undefined get method !'
@@ -104,6 +108,8 @@ class _column(object):
ids = obj.search(cr, uid, args+self._domain+[(name,'ilike',value)], offset, limit)
res = obj.read(cr, uid, ids, [name])
return [x[name] for x in res]
+ def search_memory(self, cr, obj, args, name, value, offset=0, limit=None, uid=None):
+ raise Exception, 'Not implemented search_memory method !'
# ---------------------------------------------------------
# Simple fields
@@ -165,31 +171,6 @@ class float(_column):
_column.__init__(self, string=string, **args)
self.digits = digits
-# We'll need to use decimal one day or another
-#try:
-# import decimal
-#except ImportError:
-# from tools import decimal
-#
-#class float(_column):
-# _type = 'float'
-# _symbol_c = '%f'
-# def __init__(self, string='unknown', digits=None, **args):
-# _column.__init__(self, string=string, **args)
-# self._symbol_set = (self._symbol_c, self._symbol_set_decimal)
-# self.digits = digits
-# if not digits:
-# scale = 4
-# else:
-# scale = digits[1]
-# self._scale = decimal.Decimal(str(10**-scale))
-# self._context = decimal.Context(prec=scale, rounding=decimal.ROUND_HALF_UP)
-#
-# def _symbol_set_decimal(self, symb):
-# if isinstance(symb, __builtin__.float):
-# return decimal.Decimal('%f' % symb)
-# return decimal.Decimal(symb)
-
class date(_column):
_type = 'date'
@@ -212,17 +193,6 @@ class selection(_column):
_column.__init__(self, string=string, **args)
self.selection = selection
- def set(self, cr, obj, id, name, value, user=None, context=None):
- if not context:
- context={}
-#CHECKME: a priori, ceci n'est jamais appelé puisque le test ci-dessous est mauvais
-# la raison est que selection n'est pas en classic_write = false
-# a noter qu'on pourrait fournir un _symbol_set specifique, et ca suffirait
- if value in self.selection:
- raise Exception, 'BAD VALUE'
- _column.set(self, cr, obj, id, name, value, user=None, context=context)
-
-
# ---------------------------------------------------------
# Relationals fields
# ---------------------------------------------------------
@@ -262,16 +232,6 @@ class one2one(_column):
def search(self, cr, obj, args, name, value, offset=0, limit=None, uid=None):
return obj.pool.get(self._obj).search(cr, uid, args+self._domain+[('name','like',value)], offset, limit)
-class many2one_memory(_column):
- _classic_read = True
- _classic_write = True
- _type = 'many2one'
- def __init__(self, obj, string='unknown', **args):
- _column.__init__(self, string=string, **args)
- self._obj = obj
-
-
-
class many2one(_column):
_classic_read = False
_classic_write = True
@@ -285,6 +245,12 @@ class many2one(_column):
# TODO: speed improvement
#
# name is the name of the relation field
+ def get_memory(self, cr, obj, ids, name, user=None, context=None, values=None):
+ result = {}
+ for id in ids:
+ result[id] = obj.datas[id][name]
+ return result
+
def get(self, cr, obj, ids, name, user=None, context=None, values=None):
if not context:
context={}
@@ -342,19 +308,20 @@ class many2one(_column):
def search(self, cr, obj, args, name, value, offset=0, limit=None, uid=None):
return obj.pool.get(self._obj).search(cr, uid, args+self._domain+[('name','like',value)], offset, limit)
-class one2many_memory(_column):
+class one2many(_column):
_classic_read = False
_classic_write = False
_type = 'one2many'
+
def __init__(self, obj, fields_id, string='unknown', limit=None, **args):
_column.__init__(self, string=string, **args)
self._obj = obj
self._fields_id = fields_id
self._limit = limit
+ #one2many can't be used as condition for defaults
assert(self.change_default != True)
- def get(self, cr, obj, ids, name, user=None, offset=0, context=None, values=None):
- print 'Get O2M'
+ def get_memory(self, cr, obj, ids, name, user=None, offset=0, context=None, values=None):
if not context:
context = {}
if not values:
@@ -369,7 +336,7 @@ class one2many_memory(_column):
print 'Ok', res
return res
- def set(self, cr, obj, id, field, values, user=None, context=None):
+ def set_memory(self, cr, obj, id, field, values, user=None, context=None):
if not context:
context={}
if not values:
@@ -395,63 +362,9 @@ class one2many_memory(_column):
for id2 in (act[2] or []):
obj.datas[id2][self._fields_id] = id
- def search(self, cr, obj, args, name, value, offset=0, limit=None, uid=None, operator='like'):
+ def search_memory(self, cr, obj, args, name, value, offset=0, limit=None, uid=None, operator='like'):
raise 'Not Implemented'
-class many2many_memory(_column):
- _classic_read = False
- _classic_write = False
- _type = 'many2many'
-
- def __init__(self, obj, string='unknown', limit=None, **args):
- _column.__init__(self, string=string, **args)
- self._obj = obj
- self._limit = limit
-
- def get(self, cr, obj, ids, name, user=None, offset=0, context=None, values=None):
- result = {}
- for id in ids:
- result[id] = obj.datas[id][name]
- return result
-
- def set(self, cr, obj, id, name, values, user=None, context=None):
- if not values:
- return
- for act in values:
- if act[0]==0:
- raise 'Not Implemented'
- elif act[0]==1:
- raise 'Not Implemented'
- elif act[0]==2:
- raise 'Not Implemented'
- elif act[0]==3:
- raise 'Not Implemented'
- elif act[0]==4:
- raise 'Not Implemented'
- elif act[0]==5:
- raise 'Not Implemented'
- elif act[0]==6:
- obj.datas[id][name] = act[2]
-
- #
- # TODO: use a name_search
- #
- def search(self, cr, obj, args, name, value, offset=0, limit=None, uid=None, operator='like'):
- raise 'Not Implemented'
-
-
-class one2many(_column):
- _classic_read = False
- _classic_write = False
- _type = 'one2many'
-
- def __init__(self, obj, fields_id, string='unknown', limit=None, **args):
- _column.__init__(self, string=string, **args)
- self._obj = obj
- self._fields_id = fields_id
- self._limit = limit
- #one2many can't be used as condition for defaults
- assert(self.change_default != True)
def get(self, cr, obj, ids, name, user=None, offset=0, context=None, values=None):
if not context:
@@ -584,6 +497,32 @@ class many2many(_column):
def search(self, cr, obj, args, name, value, offset=0, limit=None, uid=None, operator='like'):
return obj.pool.get(self._obj).search(cr, uid, args+self._domain+[('name',operator,value)], offset, limit)
+ def get_memory(self, cr, obj, ids, name, user=None, offset=0, context=None, values=None):
+ result = {}
+ for id in ids:
+ result[id] = obj.datas[id].get(name, [])
+ return result
+
+ def set_memory(self, cr, obj, id, name, values, user=None, context=None):
+ if not values:
+ return
+ for act in values:
+ if act[0]==0:
+ raise 'Not Implemented'
+ elif act[0]==1:
+ raise 'Not Implemented'
+ elif act[0]==2:
+ raise 'Not Implemented'
+ elif act[0]==3:
+ raise 'Not Implemented'
+ elif act[0]==4:
+ raise 'Not Implemented'
+ elif act[0]==5:
+ raise 'Not Implemented'
+ elif act[0]==6:
+ obj.datas[id][name] = act[2]
+
+
# ---------------------------------------------------------
# Function fields
# ---------------------------------------------------------
diff --git a/bin/osv/orm.py b/bin/osv/orm.py
index 33d49217078..04ff4a64d66 100644
--- a/bin/osv/orm.py
+++ b/bin/osv/orm.py
@@ -47,6 +47,7 @@
#
#
+import time
from xml import dom, xpath
from xml.parsers import expat
import string
@@ -862,9 +863,14 @@ class orm_template(object):
doc_src = dom.minidom.parseString(src)
doc_dest = dom.minidom.parseString(inherit)
- for node2 in doc_dest.childNodes:
+ toparse = doc_dest.childNodes
+ while len(toparse):
+ node2 = toparse.pop(0)
if not node2.nodeType==node2.ELEMENT_NODE:
continue
+ if node2.localName=='data':
+ toparse += node2.childNodes
+ continue
node = _find(doc_src, node2)
if node:
pos = 'inside'
@@ -1029,12 +1035,35 @@ class orm_template(object):
class orm_memory(orm_template):
_protected = ['read','write','create','default_get','perm_read','unlink','fields_get','fields_view_get','search','name_get','distinct_field_get','name_search','copy','import_data','search_count']
_inherit_fields = {}
+ _max_count = 200
+ _max_hours = 1
+ _check_time = 20
def __init__(self, cr):
super(orm_memory, self).__init__(cr)
self.datas = {}
self.next_id = 0
+ self.check_id = 0
+ cr.execute('delete from wkf_instance where res_type=%s', (self._name,))
+
+ def clear(self):
+ self.check_id+=1
+ if self.check_id % self._check_time:
+ return True
+ tounlink = []
+ max = time.time() - self._max_hours * 60 * 60
+ for id in self.datas:
+ if self.datas[id]['internal.date_access'] < max:
+ tounlink.append(id)
+ self.unlink(tounlink)
+ if len(self.datas)>self._max_count:
+ sorted = map(lambda x: (x[1]['internal.date_access'], x[0]), self.datas.items())
+ sorted.sort()
+ ids = map(lambda x: x[1], sorted[:len(self.datas)-self._max_count])
+ self.unlink(ids)
+ return True
def read(self, cr, user, ids, fields=None, context=None, load='_classic_read'):
+ print 'Read Memory'
self.pool.get('ir.model.access').check(cr, user, self._name, 'read')
if not fields:
fields = self._columns.keys()
@@ -1044,9 +1073,10 @@ class orm_memory(orm_template):
for f in fields:
r[f] = self.datas[id].get(f, False)
result.append(r)
+ self.datas[id]['internal.date_access'] = time.time()
fields_post = filter(lambda x: x in self._columns and not getattr(self._columns[x], load), fields)
for f in fields_post:
- res2 = self._columns[f].get(cr, self, ids, f, user, context=context, values=False)
+ res2 = self._columns[f].get_memory(cr, self, ids, f, user, context=context, values=False)
for record in result:
record[f] = res2[record['id']]
return result
@@ -1062,14 +1092,15 @@ class orm_memory(orm_template):
upd_todo.append(field)
for id_new in ids:
self.datas[id_new].update(vals2)
+ self.datas[id_new]['internal.date_access'] = time.time()
for field in upd_todo:
- self._columns[field].set(cr, self, id_new, field, vals[field], user, context)
+ self._columns[field].set_memory(cr, self, id_new, field, vals[field], user, context)
self._validate(cr, user, [id_new])
wf_service = netsvc.LocalService("workflow")
wf_service.trg_write(user, self._name, id_new, cr)
+ self.clear()
return id_new
-
def create(self, cr, user, vals, context=None):
self.pool.get('ir.model.access').check(cr, user, self._name, 'create')
self.next_id += 1
@@ -1088,11 +1119,13 @@ class orm_memory(orm_template):
else:
upd_todo.append(field)
self.datas[id_new] = vals2
+ self.datas[id_new]['internal.date_access'] = time.time()
for field in upd_todo:
- self._columns[field].set(cr, self, id_new, field, vals[field], user, context)
+ self._columns[field].set_memory(cr, self, id_new, field, vals[field], user, context)
self._validate(cr, user, [id_new])
wf_service = netsvc.LocalService("workflow")
wf_service.trg_create(user, self._name, id_new, cr)
+ self.clear()
return id_new
def default_get(self, cr, uid, fields_list, context=None):
@@ -1149,18 +1182,19 @@ class orm_memory(orm_template):
return self.datas.keys()
def unlink(self, cr, uid, ids, context=None):
- self.pool.get('ir.model.access').check(cr, uid, self._name, 'unlink')
for id in ids:
if id in self.datas:
del self.datas[id]
+ if len(ids):
+ cr.execute('delete from wkf_instance where res_type=%s and res_id in ('+','.join(map(str,ids))+')', (self._name, ))
return True
def perm_read(self, cr, user, ids, context=None, details=True):
result = []
for id in ids:
result.append({
- 'create_uid': (1, 'Root'),
- 'create_date': '2008-06-12 10:42:09.880151',
+ 'create_uid': (user, 'Root'),
+ 'create_date': time.strftime('%Y-%m-%d %H:%M:%S'),
'write_uid': False,
'write_date': False,
'id': id
@@ -1698,7 +1732,6 @@ class orm(orm_template):
r[key] = self.pool.get('res.users').name_get(cr, user, [r[key]])[0]
if isinstance(ids, (int, long)):
return res[ids]
- print res
return res
def unlink(self, cr, uid, ids, context=None):
diff --git a/bin/osv/osv.py b/bin/osv/osv.py
index 2a4d5a5f139..e74b056ceba 100644
--- a/bin/osv/osv.py
+++ b/bin/osv/osv.py
@@ -202,20 +202,10 @@ class osv_memory(orm.orm_memory):
# put objects in the pool var
#
def createInstance(cls, pool, module, cr):
+ name = hasattr(cls,'_name') and cls._name or cls._inherit
parent_name = hasattr(cls, '_inherit') and cls._inherit
if parent_name:
- parent_class = pool.get(parent_name).__class__
- assert parent_class, "parent class %s does not exist !" % parent_name
- nattr = {}
- for s in ('_columns', '_defaults', '_inherits', '_constraints', '_sql_constraints'):
- new = copy.copy(getattr(pool.get(parent_name), s))
- if hasattr(new, 'update'):
- new.update(cls.__dict__.get(s, {}))
- else:
- new.extend(cls.__dict__.get(s, []))
- nattr[s] = new
- name = hasattr(cls,'_name') and cls._name or cls._inherit
- cls = type(name, (cls, parent_class), nattr)
+ print 'Inherit not supported in osv_memory object !'
obj = object.__new__(cls)
obj.__init__(pool, cr)
return obj
diff --git a/bin/tools/convert.py b/bin/tools/convert.py
index 6d72d379950..af78eeefa3d 100644
--- a/bin/tools/convert.py
+++ b/bin/tools/convert.py
@@ -314,20 +314,21 @@ form: module.record_id""" % (xml_id,)
and rec.getAttribute('auto_refresh').encode('utf-8')
res = {
- 'name': name,
- 'type': type,
- 'view_id': view_id,
- 'domain': domain,
- 'context': context,
- 'res_model': res_model,
- 'src_model': src_model,
- 'view_type': view_type,
- 'view_mode': view_mode,
- 'usage': usage,
- 'limit': limit,
- 'auto_refresh': auto_refresh,
- }
-
+ 'name': name,
+ 'type': type,
+ 'view_id': view_id,
+ 'domain': domain,
+ 'context': context,
+ 'res_model': res_model,
+ 'src_model': src_model,
+ 'view_type': view_type,
+ 'view_mode': view_mode,
+ 'usage': usage,
+ 'limit': limit,
+ 'auto_refresh': auto_refresh,
+ }
+ if rec.hasAttribute('target'):
+ res['target'] = rex.getAttribute('target')
id = self.pool.get('ir.model.data')._update(cr, self.uid, 'ir.actions.act_window', self.module, res, xml_id, mode=self.mode)
self.idref[xml_id] = int(id)