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