~zaber/openobject-client/main

« back to all changes in this revision

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

  • Committer: pinky
  • Date: 2006-12-07 13:41:40 UTC
  • Revision ID: pinky-56e9b555eeb500d42202250a3456cfa2a6dc78c7
New trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
##############################################################################
 
2
#
 
3
# Copyright (c) 2006 TINY SPRL. (http://tiny.be) All Rights Reserved.
 
4
#
 
5
# $Id$
 
6
#
 
7
# WARNING: This program as such is intended to be used by professional
 
8
# programmers who take the whole responsability of assessing all potential
 
9
# consequences resulting from its eventual inadequacies and bugs
 
10
# End users who are looking for a ready-to-use solution with commercial
 
11
# garantees and support are strongly adviced to contract a Free Software
 
12
# Service Company
 
13
#
 
14
# This program is Free Software; you can redistribute it and/or
 
15
# modify it under the terms of the GNU General Public License
 
16
# as published by the Free Software Foundation; either version 2
 
17
# of the License, or (at your option) any later version.
 
18
#
 
19
# This program is distributed in the hope that it will be useful,
 
20
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
21
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
22
# GNU General Public License for more details.
 
23
#
 
24
# You should have received a copy of the GNU General Public License
 
25
# along with this program; if not, write to the Free Software
 
26
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
27
#
 
28
##############################################################################
 
29
 
 
30
#
 
31
# get: return the values to write to the server
 
32
# get_client: return the value for the client widget (form_gtk)
 
33
# set: save the value from the server
 
34
# set_client: save the value from the widget
 
35
#
 
36
from rpc import RPCProxy
 
37
import rpc
 
38
try:
 
39
        from sets import Set as set
 
40
except ImportError:
 
41
        pass
 
42
 
 
43
class ModelField(object):
 
44
        def __new__(cls, type):
 
45
                klass = TYPES.get(type, CharField)
 
46
                return klass
 
47
 
 
48
 
 
49
class CharField(object):
 
50
        def __init__(self, parent, attrs):
 
51
                self.parent = parent
 
52
                self.attrs = attrs
 
53
                self.real_attrs = attrs.copy()
 
54
                self.internal = False
 
55
                self.modified = False
 
56
 
 
57
        def sig_changed(self):
 
58
                if self.attrs.get('on_change',False):
 
59
                        self.parent.on_change(self.attrs['on_change'])
 
60
                if self.attrs.get('change_default', False):
 
61
                        self.parent.cond_default(self.attrs['name'], self.get())
 
62
 
 
63
        def domain_get(self):
 
64
                dom = self.attrs.get('domain', '[]')
 
65
                return self.parent.expr_eval(dom)
 
66
 
 
67
        def context_get(self):
 
68
                context = {}
 
69
                context.update(self.parent.context_get())
 
70
                field_context_str = self.attrs.get('context', '{}') or '{}'
 
71
                field_context = self.parent.expr_eval('dict(%s)' % field_context_str)
 
72
                context.update(field_context)
 
73
                return context
 
74
 
 
75
        def validate(self):
 
76
                ok = True
 
77
                if self.attrs.get('required', False):
 
78
                        if not self.internal:
 
79
                                ok=False
 
80
                return ok
 
81
 
 
82
        def state_set(self, state):
 
83
                if 'states' in self.attrs:
 
84
                        for key,val in self.real_attrs.items():
 
85
                                self.attrs[key] = self.real_attrs[key]
 
86
                        if state in self.attrs['states']:
 
87
                                for key,val in self.attrs['states'][state]:
 
88
                                        if key=='value':
 
89
                                                self.set(value, test_state=False)
 
90
                                                self.modified = True
 
91
                                        else:
 
92
                                                self.attrs[key] = val
 
93
 
 
94
        def set(self, value, test_state=True, modified=False):
 
95
                self.internal = value
 
96
                return True
 
97
 
 
98
        def get(self):
 
99
                return self.internal or False
 
100
 
 
101
        def set_client(self, value, test_state=True):
 
102
                internal = self.internal
 
103
                self.set(value, test_state)
 
104
                if (internal or False) != (self.internal or False):
 
105
                        self.modified = True
 
106
                        self.sig_changed()
 
107
 
 
108
        def get_client(self):
 
109
                return self.internal or False
 
110
 
 
111
        def set_default(self, value):
 
112
                return self.set(value)
 
113
 
 
114
        def get_default(self):
 
115
                return self.get()
 
116
 
 
117
class SelectionField(CharField):
 
118
        def set(self, value, test_state=True, modified=False):
 
119
                if value in [sel[0] for sel in self.attrs['selection']]:
 
120
                        super(SelectionField, self).set(value, test_state, modified)
 
121
 
 
122
class FloatField(CharField):
 
123
        def validate(self):
 
124
                return True
 
125
 
 
126
        def set_client(self, value, test_state=True):
 
127
                internal = self.internal
 
128
                self.set(value, test_state)
 
129
                if abs(float(internal or 0.0) - float(self.internal or 0.0)) >= (10.0**(-self.attrs.get('digits', (12,4))[1])):
 
130
                        self.modified = True
 
131
                        self.sig_changed()
 
132
 
 
133
 
 
134
class IntegerField(CharField):
 
135
        def validate(self):
 
136
                return True
 
137
 
 
138
 
 
139
# internal = (id, name)
 
140
class M2OField(CharField):
 
141
        def get(self):
 
142
                if self.internal:
 
143
                        return self.internal[0] or False
 
144
                return False
 
145
 
 
146
        def get_client(self):
 
147
                if self.internal:
 
148
                        return self.internal[1]
 
149
                return False
 
150
 
 
151
        def set(self, value, test_state=False, modified=False):
 
152
                if value and isinstance(value, (int, str, unicode, long)):
 
153
                        rpc2 = RPCProxy(self.attrs['relation'])
 
154
                        result = rpc2.name_get([value], rpc.session.context)
 
155
                        self.internal = result[0]
 
156
                else:
 
157
                        self.internal = value
 
158
 
 
159
        def set_client(self, value, test_state=False):
 
160
                internal = self.internal
 
161
                self.set(value, test_state)
 
162
                if internal != self.internal:
 
163
                        self.modified = True
 
164
                        self.sig_changed()
 
165
 
 
166
# internal = [id]
 
167
class M2MField(CharField):
 
168
        def __init__(self, parent, attrs):
 
169
                super(M2MField, self).__init__(parent, attrs)
 
170
                self.internal = []
 
171
 
 
172
        def get(self):
 
173
                return [(6, 0, self.internal or [])]
 
174
 
 
175
        def get_client(self):
 
176
                return self.internal or []
 
177
 
 
178
        def set(self, value, test_state=False, modified=False):
 
179
                self.internal = value or []
 
180
 
 
181
        def set_client(self, value, test_state=False):
 
182
                internal = self.internal
 
183
                self.set(value, test_state, modified=False)
 
184
                if set(internal) != set(value):
 
185
                        self.modified = True
 
186
                        self.sig_changed()
 
187
 
 
188
        def get_default(self):
 
189
                return self.get_client()
 
190
 
 
191
# internal = ModelRecordGroup of the related objects
 
192
class O2MField(CharField):
 
193
        def __init__(self, parent, attrs):
 
194
                super(O2MField, self).__init__(parent, attrs)
 
195
                from widget.model.group import ModelRecordGroup
 
196
                self.internal = ModelRecordGroup(resource=self.attrs['relation'], fields={}, parent=self.parent)
 
197
 
 
198
        def _get_modified(self):
 
199
                for model in self.internal.models:
 
200
                        if model.is_modified():
 
201
                                return True
 
202
                if self.internal.model_removed:
 
203
                        return True
 
204
                return False
 
205
 
 
206
        def _set_modified(self, value):
 
207
                pass
 
208
                
 
209
        modified = property(_get_modified, _set_modified)
 
210
 
 
211
        def _model_changed(self, group, model):
 
212
                self.parent.signal('record-changed')
 
213
 
 
214
        def get_client(self):
 
215
                return self.internal
 
216
 
 
217
        def get(self):
 
218
                if not self.internal:
 
219
                        return []
 
220
                result = []
 
221
                for model in self.internal.models:
 
222
                        if model.id:
 
223
                                result.append((1,model.id, model.get()))
 
224
                        else:
 
225
                                result.append((0,0, model.get()))
 
226
                for id in self.internal.model_removed:
 
227
                        result.append((2,id, False))
 
228
                return result
 
229
 
 
230
        def set(self, value, test_state=False, modified=False):
 
231
                from widget.model.group import ModelRecordGroup
 
232
                self.internal = ModelRecordGroup(resource=self.attrs['relation'], fields={}, parent=self.parent)
 
233
                #self.internal.signal_connect(self.internal, 'model-changed', self._model_changed)
 
234
                self.internal.pre_load(value, display=False)
 
235
                #self.internal.signal_connect(self.internal, 'model-changed', self._model_changed)
 
236
 
 
237
        def set_client(self, value, test_state=False):
 
238
                self.set(value, test_state=test_state)
 
239
 
 
240
        def set_default(self, value):
 
241
                from widget.model.group import ModelRecordGroup
 
242
                fields = {}
 
243
                if len(value):
 
244
                        context = self.context_get()
 
245
                        rpc2 = RPCProxy(self.attrs['relation'])
 
246
                        fields = rpc2.fields_get(value[0].keys(), context)
 
247
 
 
248
                self.internal = ModelRecordGroup(resource=self.attrs['relation'], fields=fields, parent=self.parent)
 
249
                self.internal.signal_connect(self.internal, 'model-changed', self._model_changed)
 
250
                mod=None
 
251
                for record in value:
 
252
                        mod = self.internal.model_new(default=False)
 
253
                        mod.set_default(record)
 
254
                        self.internal.model_add(mod)
 
255
                self.internal.current_model = mod
 
256
                #mod.signal('record-changed')
 
257
                return True
 
258
 
 
259
        def get_default(self):
 
260
                res = map(lambda x: x.get_default(), self.internal.models or [])
 
261
                return res
 
262
 
 
263
class ReferenceField(CharField):
 
264
        def get_client(self):
 
265
                if self.internal:
 
266
                        return self.internal
 
267
                return False
 
268
 
 
269
        def get(self):
 
270
                if self.internal:
 
271
                        return '%s,%d' % (self.internal[0], self.internal[1][0])
 
272
                return False
 
273
 
 
274
        def set_client(self, value):
 
275
                internal = self.internal
 
276
                self.internal = value
 
277
                if (internal or False) != (self.internal or False):
 
278
                        self.sig_changed()
 
279
 
 
280
        def set(self, value, test_state=False, modified=False):
 
281
                if not value:
 
282
                        self.internal = False
 
283
                        return
 
284
                model, id = value.split(',')
 
285
                rpc2 = RPCProxy(model)
 
286
                result = rpc2.name_get([id], rpc.session.context)
 
287
                if result:
 
288
                        self.internal = model, result[0]
 
289
                else:
 
290
                        self.internal = False
 
291
 
 
292
TYPES = {
 
293
        'char' : CharField,
 
294
        'integer' : IntegerField,
 
295
        'float' : FloatField,
 
296
        'many2one' : M2OField,
 
297
        'many2many' : M2MField,
 
298
        'one2many' : O2MField,
 
299
        'reference' : ReferenceField,
 
300
        'selection': SelectionField,
 
301
}
 
302
 
 
303
# vim:noexpandtab: