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 - 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)