1
##############################################################################
3
# Copyright (c) 2006 TINY SPRL. (http://tiny.be) All Rights Reserved.
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
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.
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.
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.
28
##############################################################################
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
36
from rpc import RPCProxy
39
from sets import Set as set
43
class ModelField(object):
44
def __new__(cls, type):
45
klass = TYPES.get(type, CharField)
49
class CharField(object):
50
def __init__(self, parent, attrs):
53
self.real_attrs = attrs.copy()
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())
64
dom = self.attrs.get('domain', '[]')
65
return self.parent.expr_eval(dom)
67
def context_get(self):
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)
77
if self.attrs.get('required', False):
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]:
89
self.set(value, test_state=False)
94
def set(self, value, test_state=True, modified=False):
99
return self.internal or False
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):
108
def get_client(self):
109
return self.internal or False
111
def set_default(self, value):
112
return self.set(value)
114
def get_default(self):
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)
122
class FloatField(CharField):
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])):
134
class IntegerField(CharField):
139
# internal = (id, name)
140
class M2OField(CharField):
143
return self.internal[0] or False
146
def get_client(self):
148
return self.internal[1]
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]
157
self.internal = value
159
def set_client(self, value, test_state=False):
160
internal = self.internal
161
self.set(value, test_state)
162
if internal != self.internal:
167
class M2MField(CharField):
168
def __init__(self, parent, attrs):
169
super(M2MField, self).__init__(parent, attrs)
173
return [(6, 0, self.internal or [])]
175
def get_client(self):
176
return self.internal or []
178
def set(self, value, test_state=False, modified=False):
179
self.internal = value or []
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):
188
def get_default(self):
189
return self.get_client()
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)
198
def _get_modified(self):
199
for model in self.internal.models:
200
if model.is_modified():
202
if self.internal.model_removed:
206
def _set_modified(self, value):
209
modified = property(_get_modified, _set_modified)
211
def _model_changed(self, group, model):
212
self.parent.signal('record-changed')
214
def get_client(self):
218
if not self.internal:
221
for model in self.internal.models:
223
result.append((1,model.id, model.get()))
225
result.append((0,0, model.get()))
226
for id in self.internal.model_removed:
227
result.append((2,id, False))
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)
237
def set_client(self, value, test_state=False):
238
self.set(value, test_state=test_state)
240
def set_default(self, value):
241
from widget.model.group import ModelRecordGroup
244
context = self.context_get()
245
rpc2 = RPCProxy(self.attrs['relation'])
246
fields = rpc2.fields_get(value[0].keys(), context)
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)
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')
259
def get_default(self):
260
res = map(lambda x: x.get_default(), self.internal.models or [])
263
class ReferenceField(CharField):
264
def get_client(self):
271
return '%s,%d' % (self.internal[0], self.internal[1][0])
274
def set_client(self, value):
275
internal = self.internal
276
self.internal = value
277
if (internal or False) != (self.internal or False):
280
def set(self, value, test_state=False, modified=False):
282
self.internal = False
284
model, id = value.split(',')
285
rpc2 = RPCProxy(model)
286
result = rpc2.name_get([id], rpc.session.context)
288
self.internal = model, result[0]
290
self.internal = False
294
'integer' : IntegerField,
295
'float' : FloatField,
296
'many2one' : M2OField,
297
'many2many' : M2MField,
298
'one2many' : O2MField,
299
'reference' : ReferenceField,
300
'selection': SelectionField,