~ubuntu-branches/ubuntu/trusty/openerp-client/trusty

« back to all changes in this revision

Viewing changes to bin/widget/model/group.py

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Baumann
  • Date: 2008-12-07 20:17:00 UTC
  • Revision ID: james.westby@ubuntu.com-20081207201700-a875pic3sd7xkoru
Tags: upstream-5.0.0~alpha
ImportĀ upstreamĀ versionĀ 5.0.0~alpha

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# -*- encoding: utf-8 -*-
 
2
##############################################################################
 
3
#
 
4
#    OpenERP, Open Source Management Solution   
 
5
#    Copyright (C) 2004-2008 Tiny SPRL (<http://tiny.be>). All Rights Reserved
 
6
#    $Id$
 
7
#
 
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.
 
12
#
 
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.
 
17
#
 
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/>.
 
20
#
 
21
##############################################################################
 
22
 
 
23
from rpc import RPCProxy
 
24
import rpc
 
25
from record import ModelRecord
 
26
import field
 
27
 
 
28
import signal_event
 
29
 
 
30
try:
 
31
    a = set()
 
32
except NameError:
 
33
    from sets import Set as set
 
34
 
 
35
class ModelList(list):
 
36
    def __init__(self, screen):
 
37
        super(ModelList, self).__init__()
 
38
        self.lock_signal = False
 
39
        self.__screen = screen
 
40
 
 
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))
 
45
 
 
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))
 
50
 
 
51
    def move(self, obj, pos):
 
52
        self.lock_signal = True
 
53
        if self.__len__() > pos:
 
54
            idx = self.index(obj)
 
55
            self.remove(obj)
 
56
            if pos > idx:
 
57
                pos -= 1
 
58
            self.insert(pos, obj)
 
59
        else:
 
60
            self.remove(obj)
 
61
            self.append(obj)
 
62
        self.lock_signal = False
 
63
 
 
64
    def remove(self, obj):
 
65
        idx = self.index(obj)
 
66
        super(ModelList, self).remove(obj)
 
67
        if not self.lock_signal:
 
68
            self.__screen.signal('record-changed', ('record-removed', idx))
 
69
    
 
70
    def clear(self):
 
71
        for obj in range(len(self)):
 
72
            self.pop()
 
73
            if not self.lock_signal:
 
74
                self.__screen.signal('record-changed', ('record-removed', len(self)))
 
75
 
 
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))
 
80
 
 
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
 
85
        self.parent = parent
 
86
        self._context = context
 
87
        self._context.update(rpc.session.context)
 
88
        self.resource = resource
 
89
        self.rpc = RPCProxy(resource)
 
90
        self.fields = fields
 
91
        self.mfields = {}
 
92
        self.mfields_load(fields.keys(), self)
 
93
 
 
94
        self.models = ModelList(self)
 
95
        self.current_idx = None
 
96
 
 
97
        self.load(ids)
 
98
        self.model_removed = []
 
99
        self.on_write = ''
 
100
        self.is_wizard = is_wizard
 
101
 
 
102
    def mfields_load(self, fkeys, models):
 
103
        for fname in fkeys:
 
104
            fvalue = models.fields[fname]
 
105
            modelfield = field.ModelField(fvalue['type'])
 
106
            fvalue['name'] = fname
 
107
            models.mfields[fname] = modelfield(models, fvalue)
 
108
 
 
109
    def model_move(self, model, position=0):
 
110
        self.models.move(model, position)
 
111
 
 
112
    def set_sequence(self, field='sequence'):
 
113
        index = 0
 
114
        for model in self.models:
 
115
            if model[field]:
 
116
                if index >= model[field].get(model):
 
117
                    index += 1
 
118
                    model[field].set(model, index, modified=True)
 
119
                else:
 
120
                    index = model[field].get(model)
 
121
                if model.id:
 
122
                    model.save()
 
123
 
 
124
    def save(self):
 
125
        for model in self.models:
 
126
            saved = model.save()
 
127
            self.writen(saved)
 
128
 
 
129
    def writen(self, edited_id):
 
130
        if not self.on_write:
 
131
            return
 
132
        new_ids = getattr(self.rpc, self.on_write)(edited_id, self.context)
 
133
        model_idx = self.models.index(self[edited_id])
 
134
        result = False
 
135
        for id in new_ids:
 
136
            cont = False
 
137
            for m in self.models:
 
138
                if m.id == id:
 
139
                    cont = True
 
140
                    m.reload()
 
141
            if cont:
 
142
                continue
 
143
            newmod = ModelRecord(self.resource, id, parent=self.parent, group=self)
 
144
            newmod.reload()
 
145
            if not result:
 
146
                result = newmod
 
147
            new_index = min(model_idx, len(self.models)-1)
 
148
            self.model_add(newmod, new_index)
 
149
        return result
 
150
    
 
151
    def pre_load(self, ids, display=True):
 
152
        if not ids:
 
153
            return True
 
154
        if len(ids)>10:
 
155
            self.models.lock_signal = True
 
156
        for id in ids:
 
157
            newmod = ModelRecord(self.resource, id, parent=self.parent, group=self)
 
158
            self.model_add(newmod)
 
159
            if display:
 
160
                self.signal('model-changed', newmod)
 
161
        if len(ids)>10:
 
162
            self.models.lock_signal = False
 
163
            self.signal('record-cleared')
 
164
        return True
 
165
 
 
166
    def load_for(self, values):
 
167
        if len(values)>10:
 
168
            self.models.lock_signal = True
 
169
        for value in values:
 
170
            newmod = ModelRecord(self.resource, value['id'], parent=self.parent, group=self)
 
171
            newmod.set(value)
 
172
            self.models.append(newmod)
 
173
            newmod.signal_connect(self, 'record-changed', self._record_changed)
 
174
        if len(values)>10:
 
175
            self.models.lock_signal = False
 
176
            self.signal('record-cleared')
 
177
 
 
178
    def load(self, ids, display=True):
 
179
        if not ids:
 
180
            return True
 
181
        if not self.fields:
 
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)
 
186
        if not values:
 
187
            return False
 
188
        newmod = False
 
189
        self.load_for(values)
 
190
        if newmod and display:
 
191
            self.signal('model-changed', newmod)
 
192
        self.current_idx = 0
 
193
        return True
 
194
    
 
195
    def clear(self):
 
196
        self.models.clear()
 
197
        self.model_removed = []
 
198
    
 
199
    def getContext(self):
 
200
        ctx = {}
 
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
 
205
        #else:
 
206
        #   ctx['active_id'] = False
 
207
        return ctx
 
208
    context = property(getContext)
 
209
 
 
210
    def model_add(self, model, position=-1):
 
211
        #
 
212
        # To be checked
 
213
        #
 
214
        if not model.mgroup is self:
 
215
            fields = {}
 
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)
 
220
            model.mgroup = self
 
221
 
 
222
        if position==-1:
 
223
            self.models.append(model)
 
224
        else:
 
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)
 
229
        return model
 
230
 
 
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)
 
235
        if default:
 
236
            ctx=context.copy()
 
237
            ctx.update(self.context)
 
238
            newmod.default_get(domain, ctx)
 
239
        self.signal('model-changed', newmod)
 
240
        return newmod
 
241
    
 
242
    def model_remove(self, model):
 
243
        idx = self.models.index(model)
 
244
        self.models.remove(model)
 
245
        if model.parent:
 
246
            model.parent.modified = True
 
247
        if self.models:
 
248
            self.current_idx = min(idx, len(self.models)-1)
 
249
        else:
 
250
            self.current_idx = None
 
251
 
 
252
    def _record_changed(self, model, signal_data):
 
253
        self.signal('model-changed', model)
 
254
 
 
255
    def prev(self):
 
256
        if self.models and self.current_idx is not None:
 
257
            self.current_idx = (self.current_idx - 1) % len(self.models)
 
258
        elif self.models:
 
259
            self.current_idx = 0
 
260
        else:
 
261
            return None
 
262
        return self.models[self.current_idx]
 
263
    
 
264
    def next(self):
 
265
        if self.models and self.current_idx is not None:
 
266
            self.current_idx = (self.current_idx + 1) % len(self.models)
 
267
        elif self.models:
 
268
            self.current_idx = 0
 
269
        else:
 
270
            return None
 
271
        return self.models[self.current_idx]
 
272
 
 
273
    def remove(self, model):
 
274
        try:
 
275
            idx = self.models.index(model)
 
276
            if self.models[idx].id:
 
277
                self.model_removed.append(self.models[idx].id)
 
278
            if model.parent:
 
279
                model.parent.modified = True
 
280
            self.models.remove(self.models[idx])
 
281
        except:
 
282
            pass
 
283
 
 
284
    def add_fields_custom(self, fields, models):
 
285
        to_add = []
 
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
 
290
                to_add.append(f)
 
291
            else:
 
292
                models.fields[f].update(fields[f])
 
293
        self.mfields_load(to_add, models)
 
294
        for fname in to_add:
 
295
            for m in models.models:
 
296
                m.value[fname] = self.mfields[fname].create(m)
 
297
        return to_add
 
298
 
 
299
    def add_fields(self, fields, models, context=None):
 
300
        import time
 
301
        ct = time.time()
 
302
        if context is None:
 
303
            context = {}
 
304
        to_add = self.add_fields_custom(fields, models)
 
305
        models = models.models
 
306
        if not len(models):
 
307
            return True
 
308
 
 
309
        old = []
 
310
        new = []
 
311
        for model in models:
 
312
            if model.id:
 
313
                old.append(model.id)
 
314
            else:
 
315
                new.append(model)
 
316
        ctx = context.copy()
 
317
        if len(old) and len(to_add):
 
318
            ctx.update(rpc.session.context)
 
319
            ctx.update(self.context)
 
320
 
 
321
            to_add_normal = []
 
322
            to_add_binary = []
 
323
            for f in to_add:
 
324
                if fields[f]['type'] in ('image','binary'):
 
325
                    to_add_binary.append(f)
 
326
                else:
 
327
                    to_add_normal.append(f)
 
328
            if to_add_normal:
 
329
                values = self.rpc.read(old, to_add_normal, ctx)
 
330
                if values:
 
331
                    for v in values:
 
332
                        id = v['id']
 
333
                        if 'id' not in to_add:
 
334
                            del v['id']
 
335
                        self[id].set(v, signal=False)
 
336
            if to_add_binary:
 
337
                data = {}
 
338
                for b in to_add_binary:
 
339
                    data[b] = None
 
340
                for m in self.models:
 
341
                    m.set(data)
 
342
 
 
343
#            values = self.rpc.read(old, to_add, ctx)
 
344
#            if values:
 
345
#                for v in values:
 
346
#                    id = v['id']
 
347
#                    if 'id' not in to_add:
 
348
#                        del v['id']
 
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)
 
353
            for t in to_add:
 
354
                if t not in values:
 
355
                    values[t] = False
 
356
            for mod in new:
 
357
                mod.set_default(values)
 
358
 
 
359
    def __iter__(self):
 
360
        return iter(self.models)
 
361
 
 
362
    def get_by_id(self, id):
 
363
        for model in self.models:
 
364
            if model.id == id:
 
365
                return model
 
366
 
 
367
    __getitem__ = get_by_id
 
368
 
 
369
 
 
370
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
 
371