00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 from PyQt4.QtCore import *
00030 from Koo.Rpc import RpcProxy, Rpc
00031 from Koo import Rpc
00032 import base64
00033 from Koo.Common import Numeric
00034
00035
00036 class StringField(QObject):
00037 def __init__(self, parent, attrs):
00038 QObject.__init__(self)
00039 self.parent = parent
00040 self.attrs = attrs
00041 self.name = attrs['name']
00042
00043
00044
00045
00046 def changed(self, record):
00047 record.modified = True
00048 record.modified_fields.setdefault(self.name)
00049 record.changed()
00050 if self.attrs.get('on_change',False):
00051 record.callOnChange(self.attrs['on_change'])
00052 if self.attrs.get('change_default', False):
00053 record.setConditionalDefaults(self.name, self.get(record))
00054
00055 def domain(self, record):
00056 dom = self.attrs.get('domain', '[]')
00057 return record.evaluateExpression(dom)
00058
00059 def context(self, record, checkLoad=True, eval=True):
00060 context = {}
00061 context.update( self.parent.context() )
00062 if eval:
00063 fieldContext = self.attrs.get('context') or '{}'
00064 fieldContext = record.evaluateExpression('dict(%s)' % fieldContext, checkLoad=checkLoad)
00065 context.update(fieldContext)
00066 return context
00067
00068
00069
00070
00071 def validate(self, record):
00072 ok = True
00073
00074
00075
00076
00077 if not record.isFieldReadOnly( self.name ):
00078 if record.isFieldRequired( self.name ):
00079 if not record.values[self.name]:
00080 ok=False
00081 record.setFieldValid( self.name, ok )
00082 return ok
00083
00084
00085 def set(self, record, value, test_state=True, modified=False):
00086 record.values[self.name] = value
00087 if modified:
00088 record.modified = True
00089 record.modified_fields.setdefault(self.name)
00090
00091
00092 def get(self, record, checkLoad=True, readonly=True, modified=False):
00093 return record.values.get(self.name, False)
00094
00095
00096 def set_client(self, record, value, test_state=True):
00097 internal = record.values.get(self.name, False)
00098 self.set(record, value, test_state)
00099 if (internal or False) != (record.values.get(self.name,False) or False):
00100 self.changed(record)
00101
00102
00103 def get_client(self, record):
00104 return record.values.get(self.name, False)
00105
00106 def setDefault(self, record, value):
00107 self.set(record, value)
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121 if self.attrs.get('on_change',False):
00122 record.callOnChange(self.attrs['on_change'])
00123
00124 def default(self, record):
00125 return self.get(record)
00126
00127 def create(self, record):
00128 return False
00129
00130
00131
00132 class BinaryField(StringField):
00133 def __init__(self, parent, attrs):
00134 StringField.__init__(self, parent, attrs)
00135 self.sizeName = '%s.size' % self.name
00136
00137 def set(self, record, value, test_state=True, modified=False):
00138 record.values[self.name] = None
00139 record.values[self.sizeName] = False
00140 if value:
00141 if record.isWizard():
00142 value = base64.decodestring(value)
00143 record.values[self.name] = value
00144 if value:
00145 record.values[ self.sizeName ] = Numeric.bytesToText( len(value) )
00146 else:
00147 record.values[ self.sizeName ] = ''
00148 else:
00149 record.values[ self.sizeName ] = value
00150 if modified:
00151 record.modified = True
00152 record.modified_fields.setdefault(self.name)
00153
00154 def set_client(self, record, value, test_state=True):
00155 internal = record.values.get(self.name, None)
00156 record.values[self.name] = value
00157 if value:
00158 record.values[self.sizeName] = Numeric.bytesToText( len(value or '') )
00159 else:
00160 record.values[self.sizeName] = ''
00161 if internal != record.values[self.name]:
00162 self.changed(record)
00163
00164 def get(self, record, checkLoad=True, readonly=True, modified=False):
00165 if checkLoad:
00166
00167 value = self.get_client(record)
00168 else:
00169 value = record.values[self.name]
00170 if value:
00171 value = base64.encodestring(value)
00172 else:
00173
00174 value = ''
00175 return value
00176
00177 def get_client(self, record):
00178 if record.values[self.name] is None and record.id:
00179 c = Rpc.session.context.copy()
00180 c.update(record.context())
00181 value = record.rpc.read([record.id], [self.name], c)[0][self.name]
00182 if value:
00183 record.values[self.name] = base64.decodestring(value)
00184 else:
00185 record.values[self.name] = ''
00186 return record.values[self.name]
00187
00188 class BinarySizeField(StringField):
00189 def __init__(self, parent, attrs):
00190 StringField.__init__(self, parent, attrs)
00191 self.name = '%s.size' % attrs['name']
00192
00193 def set(self, record, value, test_state=True, modified=False):
00194 record.values[self.name] = value
00195
00196
00197
00198 class SelectionField(StringField):
00199 def set(self, record, value, test_state=True, modified=False):
00200 if value in [sel[0] for sel in self.attrs['selection']]:
00201 super(SelectionField, self).set(record, value, test_state, modified)
00202
00203 class FloatField(StringField):
00204 def validate(self, record):
00205 record.setFieldValid( self.name, True )
00206 return True
00207
00208 def set_client(self, record, value, test_state=True):
00209 internal = record.values[self.name]
00210 self.set(record, value, test_state)
00211 digits = self.attrs.get('digits', (14,2))
00212
00213
00214
00215 if Numeric.floatToText( internal, digits ) != Numeric.floatToText( record.values[self.name], digits ):
00216 if not record.isFieldReadOnly( self.name ):
00217 self.changed(record)
00218
00219 class IntegerField(StringField):
00220
00221 def get(self, record, checkLoad=True, readonly=True, modified=False):
00222 return record.values.get(self.name, 0) or 0
00223
00224 def get_client(self, record):
00225 return record.values[self.name] or 0
00226
00227 def validate(self, record):
00228 record.setFieldValid( self.name, True )
00229 return True
00230
00231
00232 class ManyToOneField(StringField):
00233
00234 def get(self, record, checkLoad=True, readonly=True, modified=False):
00235 if record.values[self.name]:
00236 return record.values[self.name][0] or False
00237 return False
00238
00239 def get_client(self, record):
00240 if record.values[self.name]:
00241 return record.values[self.name][1]
00242 return False
00243
00244 def set(self, record, value, test_state=False, modified=False):
00245 if value and isinstance(value, (int, str, unicode, long)):
00246 Rpc2 = RpcProxy(self.attrs['relation'])
00247 result = Rpc2.name_get([value], Rpc.session.context)
00248
00249
00250
00251
00252 if result:
00253 record.values[self.name] = result[0]
00254 else:
00255 record.values[self.name] = value
00256 if modified:
00257 record.modified = True
00258 record.modified_fields.setdefault(self.name)
00259
00260 def set_client(self, record, value, test_state=False):
00261 internal = record.values[self.name]
00262 self.set(record, value, test_state)
00263 if internal != record.values[self.name]:
00264 self.changed(record)
00265
00266
00267
00268
00269
00270
00271
00272
00273 class ToManyField(StringField):
00274 def create(self, record):
00275 from Koo.Model.Group import RecordGroup
00276 group = RecordGroup(resource=self.attrs['relation'], fields={}, parent=record, context=self.context(record, eval=False))
00277 group.setDomainForEmptyGroup()
00278 group.tomanyfield = self
00279 self.connect( group, SIGNAL('modified'), self.groupModified )
00280 return group
00281
00282 def groupModified(self):
00283 p = self.sender().parent
00284 self.changed( self.sender().parent )
00285
00286 def get_client(self, record):
00287 return record.values[self.name]
00288
00289 def get(self, record, checkLoad=True, readonly=True, modified=False):
00290 pass
00291
00292 def set(self, record, value, test_state=False, modified=False):
00293 from Koo.Model.Group import RecordGroup
00294
00295
00296
00297
00298 group = RecordGroup(resource=self.attrs['relation'], fields={}, parent=record, context=self.context(record, eval=False))
00299 group.tomanyfield = self
00300 self.connect( group, SIGNAL('modified'), self.groupModified )
00301 group.setDomain( [('id','in',value)] )
00302 group.load(value)
00303 record.values[self.name] = group
00304 if modified:
00305 self.changed(record)
00306
00307 def set_client(self, record, value, test_state=False):
00308 self.set(record, value, test_state=test_state)
00309 self.changed(record)
00310
00311 def validate(self, record):
00312 ok = True
00313 for record in record.values[self.name].modifiedRecords():
00314 if not record.validate():
00315 ok = False
00316 if not super(ToManyField, self).validate(record):
00317 ok = False
00318 record.setFieldValid( self.name, ok )
00319 return ok
00320
00321 class OneToManyField(ToManyField):
00322 def get(self, record, checkLoad=True, readonly=True, modified=False):
00323 if not record.values[self.name]:
00324 return []
00325 result = []
00326 group = record.values[self.name]
00327
00328 for modifiedRecord in group.modifiedRecords():
00329
00330 if modifiedRecord.id:
00331 result.append((1, modifiedRecord.id, modifiedRecord.get(checkLoad=checkLoad, get_readonly=readonly)))
00332
00333
00334 for rec in group.newRecords():
00335 result.append((0, 0, rec.get(checkLoad=checkLoad, get_readonly=readonly)))
00336
00337
00338 for id in record.values[self.name].removedRecords:
00339 result.append( (2, id, False) )
00340 return result
00341
00342 def setDefault(self, record, value):
00343 from Koo.Model.Group import RecordGroup
00344 fields = {}
00345 if value and len(value):
00346 context = self.context(record)
00347 Rpc2 = RpcProxy(self.attrs['relation'])
00348 fields = Rpc2.fields_get(value[0].keys(), context)
00349
00350 record.values[self.name] = RecordGroup(resource=self.attrs['relation'], fields=fields, parent=record, context=self.context(record, eval=False))
00351 self.connect( record.values[self.name], SIGNAL('modified'), self.groupModified )
00352 record.values[self.name].tomanyfield = self
00353 mod=None
00354 for record in (value or []):
00355
00356 mod = record.values[self.name].model_new(default=False)
00357 mod.setDefault(record)
00358 record.values[self.name].model_add(mod)
00359 return True
00360
00361 def default(self, record):
00362
00363 return [ x.defaults() for x in record.values[self.name].records ]
00364
00365 class ManyToManyField(ToManyField):
00366 def get(self, record, checkLoad=True, readonly=True, modified=False):
00367 if not record.values[self.name]:
00368 return []
00369 return [(6, 0, record.values[self.name].ids())]
00370
00371 def default(self, record):
00372 if not record.values[self.name]:
00373 return []
00374 return record.values[self.name].ids()
00375
00376 class ReferenceField(StringField):
00377 def get_client(self, record):
00378 if record.values[self.name]:
00379 return record.values[self.name]
00380 return False
00381
00382 def get(self, record, checkLoad=True, readonly=True, modified=False):
00383 if record.values[self.name]:
00384 return '%s,%d' % (record.values[self.name][0], record.values[self.name][1][0])
00385 return False
00386
00387 def set_client(self, record, value):
00388 internal = record.values[self.name]
00389 record.values[self.name] = value
00390 if (internal or False) != (record.values[self.name] or False):
00391 self.changed(record)
00392
00393 def set(self, record, value, test_state=False, modified=False):
00394 if not value:
00395 record.values[self.name] = False
00396 return
00397 ref_model, id = value.split(',')
00398
00399 id = int(id)
00400 Rpc2 = RpcProxy(ref_model)
00401 result = Rpc2.name_get([id], Rpc.session.context)
00402 if result:
00403 record.values[self.name] = ref_model, result[0]
00404 else:
00405 record.values[self.name] = False
00406 if modified:
00407 record.modified = True
00408 record.modified_fields.setdefault(self.name)
00409
00410
00411
00412
00413
00414
00415
00416
00417 class FieldFactory:
00418
00419
00420
00421
00422 types = {
00423 'char' : StringField,
00424 'binary' : BinaryField,
00425 'binary-size': BinarySizeField,
00426 'image' : BinaryField,
00427 'float_time': FloatField,
00428 'integer' : IntegerField,
00429 'float' : FloatField,
00430 'many2one' : ManyToOneField,
00431 'many2many' : ManyToManyField,
00432 'one2many' : OneToManyField,
00433 'reference' : ReferenceField,
00434 'selection': SelectionField,
00435 'boolean': IntegerField,
00436 }
00437
00438
00439
00440 @staticmethod
00441 def create(type, parent, attributes):
00442 if type in FieldFactory.types:
00443 return FieldFactory.types[type]( parent, attributes )
00444 else:
00445 return FieldFactory.types['char']( parent, attributes )
00446
00447