1
# -*- encoding: utf-8 -*-
2
##############################################################################
4
# OpenERP, Open Source Management Solution
5
# Copyright (C) 2004-2008 Tiny SPRL (<http://tiny.be>). All Rights Reserved
8
# This program is free software: you can redistribute it and/or modify
9
# it under the terms of the GNU General Public License as published by
10
# the Free Software Foundation, either version 3 of the License, or
11
# (at your option) any later version.
13
# This program is distributed in the hope that it will be useful,
14
# but WITHOUT ANY WARRANTY; without even the implied warranty of
15
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
# GNU General Public License for more details.
18
# You should have received a copy of the GNU General Public License
19
# along with this program. If not, see <http://www.gnu.org/licenses/>.
21
##############################################################################
23
from rpc import RPCProxy
25
from record import ModelRecord
33
from sets import Set as set
35
class ModelList(list):
36
def __init__(self, screen):
37
super(ModelList, self).__init__()
38
self.lock_signal = False
39
self.__screen = screen
41
def insert(self, pos, obj):
42
super(ModelList, self).insert(pos, obj)
43
if not self.lock_signal:
44
self.__screen.signal('record-changed', ('record-added', pos))
46
def append(self, obj):
47
super(ModelList, self).append(obj)
48
if not self.lock_signal:
49
self.__screen.signal('record-changed', ('record-added', -1))
51
def move(self, obj, pos):
52
self.lock_signal = True
53
if self.__len__() > pos:
62
self.lock_signal = False
64
def remove(self, obj):
66
super(ModelList, self).remove(obj)
67
if not self.lock_signal:
68
self.__screen.signal('record-changed', ('record-removed', idx))
71
for obj in range(len(self)):
73
if not self.lock_signal:
74
self.__screen.signal('record-changed', ('record-removed', len(self)))
76
def __setitem__(self, key, value):
77
super(ModelList, self).__setitem__(key, value)
78
if not self.lock_signal:
79
self.__screen.signal('record-changed', ('record-changed', key))
81
class ModelRecordGroup(signal_event.signal_event):
82
def __init__(self, resource, fields, ids=[], parent=None, context={}, is_wizard=False):
83
super(ModelRecordGroup, self).__init__()
84
self._readonly = False
86
self._context = context
87
self._context.update(rpc.session.context)
88
self.resource = resource
89
self.rpc = RPCProxy(resource)
92
self.mfields_load(fields.keys(), self)
94
self.models = ModelList(self)
95
self.current_idx = None
98
self.model_removed = []
100
self.is_wizard = is_wizard
102
def mfields_load(self, fkeys, models):
104
fvalue = models.fields[fname]
105
modelfield = field.ModelField(fvalue['type'])
106
fvalue['name'] = fname
107
models.mfields[fname] = modelfield(models, fvalue)
109
def model_move(self, model, position=0):
110
self.models.move(model, position)
112
def set_sequence(self, field='sequence'):
114
for model in self.models:
116
if index >= model[field].get(model):
118
model[field].set(model, index, modified=True)
120
index = model[field].get(model)
125
for model in self.models:
129
def writen(self, edited_id):
130
if not self.on_write:
132
new_ids = getattr(self.rpc, self.on_write)(edited_id, self.context)
133
model_idx = self.models.index(self[edited_id])
137
for m in self.models:
143
newmod = ModelRecord(self.resource, id, parent=self.parent, group=self)
147
new_index = min(model_idx, len(self.models)-1)
148
self.model_add(newmod, new_index)
151
def pre_load(self, ids, display=True):
155
self.models.lock_signal = True
157
newmod = ModelRecord(self.resource, id, parent=self.parent, group=self)
158
self.model_add(newmod)
160
self.signal('model-changed', newmod)
162
self.models.lock_signal = False
163
self.signal('record-cleared')
166
def load_for(self, values):
168
self.models.lock_signal = True
170
newmod = ModelRecord(self.resource, value['id'], parent=self.parent, group=self)
172
self.models.append(newmod)
173
newmod.signal_connect(self, 'record-changed', self._record_changed)
175
self.models.lock_signal = False
176
self.signal('record-cleared')
178
def load(self, ids, display=True):
182
return self.pre_load(ids, display)
183
c = rpc.session.context.copy()
184
c.update(self.context)
185
values = self.rpc.read(ids, self.fields.keys(), c)
189
self.load_for(values)
190
if newmod and display:
191
self.signal('model-changed', newmod)
197
self.model_removed = []
199
def getContext(self):
201
ctx.update(self._context)
202
#ctx['active_ids'] = [model.id for model in self.models if model.id]
203
#if self.current_idx is not None:
204
# ctx['active_id'] = self.models[self.current_idx].id or False
206
# ctx['active_id'] = False
208
context = property(getContext)
210
def model_add(self, model, position=-1):
214
if not model.mgroup is self:
216
for mf in model.mgroup.fields:
217
fields[model.mgroup.fields[mf]['name']] = model.mgroup.fields[mf]
218
self.add_fields(fields, self)
219
self.add_fields(self.fields, model.mgroup)
223
self.models.append(model)
225
self.models.insert(position, model)
226
self.current_idx = position
227
model.parent = self.parent
228
model.signal_connect(self, 'record-changed', self._record_changed)
231
def model_new(self, default=True, domain=[], context={}):
232
newmod = ModelRecord(self.resource, None, group=self,
233
parent=self.parent, new=True)
234
newmod.signal_connect(self, 'record-changed', self._record_changed)
237
ctx.update(self.context)
238
newmod.default_get(domain, ctx)
239
self.signal('model-changed', newmod)
242
def model_remove(self, model):
243
idx = self.models.index(model)
244
self.models.remove(model)
246
model.parent.modified = True
248
self.current_idx = min(idx, len(self.models)-1)
250
self.current_idx = None
252
def _record_changed(self, model, signal_data):
253
self.signal('model-changed', model)
256
if self.models and self.current_idx is not None:
257
self.current_idx = (self.current_idx - 1) % len(self.models)
262
return self.models[self.current_idx]
265
if self.models and self.current_idx is not None:
266
self.current_idx = (self.current_idx + 1) % len(self.models)
271
return self.models[self.current_idx]
273
def remove(self, model):
275
idx = self.models.index(model)
276
if self.models[idx].id:
277
self.model_removed.append(self.models[idx].id)
279
model.parent.modified = True
280
self.models.remove(self.models[idx])
284
def add_fields_custom(self, fields, models):
286
for f in fields.keys():
287
if not f in models.fields:
288
models.fields[f] = fields[f]
289
models.fields[f]['name'] = f
292
models.fields[f].update(fields[f])
293
self.mfields_load(to_add, models)
295
for m in models.models:
296
m.value[fname] = self.mfields[fname].create(m)
299
def add_fields(self, fields, models, context=None):
304
to_add = self.add_fields_custom(fields, models)
305
models = models.models
317
if len(old) and len(to_add):
318
ctx.update(rpc.session.context)
319
ctx.update(self.context)
324
if fields[f]['type'] in ('image','binary'):
325
to_add_binary.append(f)
327
to_add_normal.append(f)
329
values = self.rpc.read(old, to_add_normal, ctx)
333
if 'id' not in to_add:
335
self[id].set(v, signal=False)
338
for b in to_add_binary:
340
for m in self.models:
343
# values = self.rpc.read(old, to_add, ctx)
347
# if 'id' not in to_add:
349
# self[id].set(v, signal=False)
350
if len(new) and len(to_add):
351
ctx.update(self.context)
352
values = self.rpc.default_get(to_add, ctx)
357
mod.set_default(values)
360
return iter(self.models)
362
def get_by_id(self, id):
363
for model in self.models:
367
__getitem__ = get_by_id
370
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: