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 Koo.Rpc import RpcProxy
00030 from Koo import Rpc
00031 from Koo.Common.Settings import *
00032 from Record import Record
00033 import Field 
00034 
00035 
00036 from PyQt4.QtCore import *
00037 from PyQt4.QtGui import *
00038 
00039 try:
00040         set()
00041 except NameError:
00042         from sets import Set as set
00043 
00044 
00045 
00046 
00047 
00048 
00049 
00050 
00051 
00052 
00053 
00054 
00055 
00056 
00057 
00058 
00059 
00060 
00061 
00062 
00063 
00064 
00065 
00066 
00067 
00068 class RecordGroup(QObject):
00069 
00070         SortVisibleItems = 1
00071         SortAllItems = 2
00072 
00073         SortingPossible = 0
00074         SortingNotPossible = 1
00075         SortingOnlyGroups = 2
00076         SortingNotPossibleModified = 3
00077 
00078         
00079         
00080         
00081         
00082         
00083         
00084         def __init__(self, resource, fields = None, ids=None, parent=None, context=None):
00085                 QObject.__init__(self)
00086                 if ids is None:
00087                         ids = []
00088                 if context is None:
00089                         context = {}
00090                 self.parent = parent
00091                 self._context = context
00092                 self._context.update(Rpc.session.context)
00093                 self.resource = resource
00094                 self.limit = Settings.value( 'koo.limit', 80, int )
00095                 self.maximumLimit = self.limit
00096                 self.rpc = RpcProxy(resource)
00097                 if fields == None:
00098                         self.fields = {}
00099                 else:
00100                         self.fields = fields
00101                 self.fieldObjects = {}
00102                 self.loadFieldObjects( self.fields.keys() )
00103 
00104                 self.records = []
00105 
00106                 self.enableSignals()
00107                 
00108                 
00109                 
00110                 
00111                 
00112                 
00113                 self.toBeSortedField = None
00114                 self.toBeSortedOrder = None
00115 
00116                 self.sortedField = None
00117                 self.sortedOrder = None
00118                 self.updated = False
00119                 self._domain = []
00120                 self._filter = []
00121 
00122                 if Settings.value('koo.sort_mode') == 'visible_items':
00123                         self._sortMode = self.SortVisibleItems
00124                 else:
00125                         self._sortMode = self.SortAllItems
00126                 self._sortMode = self.SortAllItems
00127 
00128                 self.load(ids)
00129                 self.removedRecords = []
00130                 self._onWriteFunction = ''
00131 
00132         
00133         
00134         
00135         
00136         
00137         
00138         
00139         
00140         def setLoadOneByOne(self, value):
00141                 if value:
00142                         self.limit = 1
00143                 else:
00144                         self.limit = self.maximumLimit
00145 
00146         def setSortMode(self, mode):
00147                 self._sortMode = mode
00148 
00149         def sortMode(self):
00150                 return self._sortMode
00151 
00152         def setOnWriteFunction(self, value):
00153                 self._onWriteFunction = value
00154 
00155         def onWriteFunction(self):
00156                 return self._onWriteFunction
00157 
00158         def __del__(self):
00159                 if self.parent:
00160                         self.disconnect(self,SIGNAL('modified'),self.tomanyfield.groupModified)
00161                         self.tomanyfield = None
00162                 self.rpc = None
00163                 self.parent = None
00164                 self.resource = None
00165                 self._context = None
00166                 self.fields = None
00167                 for r in self.records:
00168                         if not isinstance(r, Record):
00169                                 continue
00170                         self.disconnect(r,SIGNAL('recordChanged( PyQt_PyObject )'), self.recordChanged )
00171                         self.disconnect(r,SIGNAL('recordModified( PyQt_PyObject )'), self.recordModified)
00172                         r.__del__()
00173                 self.records = []
00174                 for f in self.fieldObjects:
00175                         self.fieldObjects[f].parent = None
00176                         self.fieldObjects[f].setParent( None )
00177                         
00178                         
00179                         
00180                         
00181                 self.fieldObjects = {}
00182 
00183         
00184         def fieldType( self, fieldName ):
00185                 if not fieldName in self.fields:
00186                         return None
00187                 return self.fields[fieldName]['type']
00188 
00189         
00190         def loadFieldObjects(self, fkeys):
00191                 for fname in fkeys:
00192                         fvalue = self.fields[fname]
00193                         fvalue['name'] = fname
00194                         self.fieldObjects[fname] = Field.FieldFactory.create( fvalue['type'], self, fvalue )
00195                         if fvalue['type'] in ('binary','image'):
00196                                 self.fieldObjects['%s.size' % fname] = Field.FieldFactory.create( 'binary-size', self, fvalue )
00197 
00198         
00199         
00200         
00201         
00202         def save(self):
00203                 for record in self.records:
00204                         if isinstance( record, Record ):
00205                                 saved = record.save()
00206 
00207         
00208         def modifiedRecords(self):
00209                 modified = []
00210                 for record in self.records:
00211                         if isinstance( record, Record ) and record.isModified():
00212                                 modified.append( record )
00213                 return modified
00214 
00215         
00216         
00217         
00218         
00219         
00220         
00221         
00222         
00223         
00224         def written( self, editedId ):
00225                 if not self._onWriteFunction or not editedId:
00226                         return
00227                 
00228                 
00229                 new_ids = getattr(self.rpc, self._onWriteFunction)( editedId, self.context() )
00230                 record_idx = self.records.index( self.recordById( editedId ) )
00231                 result = False
00232                 indexes = []
00233                 for id in new_ids:
00234                         cont = False
00235                         for m in self.records:
00236                                 if isinstance( m, Record ):
00237                                         if m.id == id:
00238                                                 cont = True
00239                                                 
00240                                                 
00241                                                 m.reload()
00242                         if cont:
00243                                 continue
00244                         
00245                         
00246                         record = Record(id, self, parent=self.parent)
00247                         self.connect(record,SIGNAL('recordChanged( PyQt_PyObject )'), self.recordChanged )
00248                         self.connect(record,SIGNAL('recordModified( PyQt_PyObject )'),self.recordModified)
00249                         record.reload()
00250                         if not result:
00251                                 result = record
00252                         newIndex = min(record_idx, len(self.records)-1)
00253                         self.add(record, newIndex)
00254                         indexes.append(newIndex)
00255 
00256                 if indexes:
00257                         self.emit( SIGNAL('recordsInserted(int,int)'), min(indexes), max(indexes) )
00258                 return result
00259         
00260         
00261         
00262         
00263         
00264         def loadFromValues(self, values):
00265                 start = len(self.records)
00266                 for value in values:
00267                         record = Record(value['id'], self, parent=self.parent)
00268                         record.set(value)
00269                         self.records.append(record)
00270                         self.connect(record,SIGNAL('recordChanged( PyQt_PyObject )'), self.recordChanged )
00271                         self.connect(record,SIGNAL('recordModified( PyQt_PyObject )'),self.recordModified)
00272                 end = len(self.records)-1
00273                 self.emit( SIGNAL('recordsInserted(int,int)'), start, end )
00274         
00275         
00276         
00277         
00278         
00279         def load(self, ids, addOnTop=False):
00280                 if not ids:
00281                         return 
00282                 if addOnTop:
00283                         start = 0
00284                         
00285                         
00286                         
00287                         
00288                         
00289                         
00290                         
00291                         
00292                         currentIds = self.ids()
00293                         for id in ids:
00294                                 if id not in currentIds:
00295                                         self.records.insert( 0, id )
00296                         end = len(ids)-1
00297                 else:
00298                         start = len(self.records)
00299                         
00300                         currentIds = self.ids()
00301                         for id in ids:
00302                                 if id not in currentIds:
00303                                         self.records.append( id )
00304                         end = len(self.records)-1
00305                 
00306                 
00307                 
00308                 self.updated = True
00309                 self.emit( SIGNAL('recordsInserted(int,int)'), start, end )
00310 
00311         
00312         def clear(self):
00313                 for record in self.records:
00314                         if isinstance(record, Record):
00315                                 self.disconnect( record, SIGNAL('recordChanged( PyQt_PyObject )'), self.recordChanged )
00316                                 self.disconnect( record, SIGNAL('recordModified( PyQt_PyObject )'), self.recordModified )
00317                 last = len(self.records)-1
00318                 self.records = []
00319                 self.removedRecords = []
00320                 self.emit( SIGNAL('recordsRemoved(int,int)'), 0, last )
00321         
00322         
00323         def context(self):
00324                 ctx = {}
00325                 ctx.update(self._context)
00326                 return ctx
00327 
00328         
00329         def setContext(self, context):
00330                 self._context = context.copy()
00331 
00332         
00333         def add(self, record, position=-1):
00334                 if not record.group is self:
00335                         fields = {}
00336                         for mf in record.group.fields:
00337                                 fields[record.group.fields[mf]['name']] = record.group.fields[mf]
00338                         self.addFields(fields)
00339                         record.group.addFields(self.fields)
00340                         record.group = self
00341 
00342                 if position==-1:
00343                         self.records.append(record)
00344                 else:
00345                         self.records.insert(position, record)
00346                 record.parent = self.parent
00347                 self.connect(record,SIGNAL('recordChanged( PyQt_PyObject )'),self.recordChanged)
00348                 self.connect(record,SIGNAL('recordModified( PyQt_PyObject )'),self.recordModified)
00349                 return record
00350 
00351         
00352         
00353         
00354         
00355         def create(self, default=True, position=-1, domain=None, context=None):
00356                 if domain is None:
00357                         domain = []
00358                 if context is None:
00359                         context = {}
00360                 self.ensureUpdated()
00361 
00362                 record = Record(None, self, parent=self.parent, new=True)
00363                 if default:
00364                         ctx=context.copy()
00365                         ctx.update( self.context() )
00366                         record.fillWithDefaults(domain, ctx)
00367                 self.add( record, position )
00368                 if position == -1:
00369                         start = len(self.records) - 1
00370                 else:
00371                         start = position
00372                 self.emit( SIGNAL('recordsInserted(int,int)'), start, start )
00373                 return record
00374 
00375         def disableSignals(self):
00376                 self._signalsEnabled = False
00377 
00378         def enableSignals(self):
00379                 self._signalsEnabled = True
00380         
00381         def recordChanged(self, record):
00382                 if self._signalsEnabled:
00383                         self.emit( SIGNAL('recordChanged(PyQt_PyObject)'), record )
00384 
00385         def recordModified(self, record):
00386                 if self._signalsEnabled:
00387                         self.emit( SIGNAL('modified') )
00388 
00389         
00390         
00391         
00392         def removeRecord(self, record):
00393                 idx = self.records.index(record)
00394                 if isinstance( record, Record ):
00395                         id = record.id
00396                 else:
00397                         id = record
00398                 if id:
00399                         
00400                         
00401                         
00402                         self.removedRecords.append( id )
00403                 if isinstance( record, Record ):
00404                         if record.parent:
00405                                 record.parent.modified = True
00406                 self.freeRecord( record )
00407                 self.emit( SIGNAL('modified') )
00408                 self.emit( SIGNAL('recordsRemoved(int,int)'), idx, idx )
00409 
00410         
00411         
00412         
00413         def removeRecords(self, records):
00414                 firstIdx = -1
00415                 lastIdx = -1
00416                 toRemove = []
00417                 for record in records:
00418                         if not record in records:
00419                                 continue
00420                         idx = self.records.index(record)
00421                         if firstIdx < 0 or idx < firstIdx:
00422                                 firstIdx = idx
00423                         if lastIdx < 0 or idx > lastIdx:
00424                                 lastIdx = idx
00425                         if isinstance( record, Record ):
00426                                 id = record.id
00427                         else:
00428                                 id = record
00429                         if id:
00430                                 
00431                                 
00432                                 
00433                                 self.removedRecords.append( id )
00434                         if isinstance( record, Record ):
00435                                 if record.parent:
00436                                         record.parent.modified = True
00437                         self.freeRecord( record )
00438                 self.emit( SIGNAL('modified') )
00439                 self.emit( SIGNAL('recordsRemoved(int,int)'), firstIdx, lastIdx )
00440 
00441         
00442         
00443         
00444         def remove(self, record):
00445                 if isinstance(record, list):
00446                         self.removeRecords( record )
00447                 else:
00448                         self.removeRecord( record )     
00449 
00450         def binaryFieldNames(self):
00451                 return [x[:-5] for x in self.fieldObjects.keys() if x.endswith('.size')]
00452 
00453         def allFieldNames(self):
00454                 return [x for x in self.fieldObjects.keys() if not x.endswith('.size')]
00455 
00456         
00457         
00458         
00459         
00460         
00461         def addFields(self, fields):
00462                 to_add = []
00463                 for f in fields.keys():
00464                         if not f in self.fields:
00465                                 self.fields[f] = fields[f]
00466                                 self.fields[f]['name'] = f
00467                                 to_add.append(f)
00468                         else:
00469                                 self.fields[f].update(fields[f])
00470                 self.loadFieldObjects(to_add)
00471                 return to_add
00472 
00473 
00474         
00475         def ensureAllLoaded(self):
00476                 ids = self.unloadedIds()
00477                 c = Rpc.session.context.copy()
00478                 c.update( self.context() )
00479                 c['bin_size'] = True
00480                 values = self.rpc.read( ids, self.fields.keys(), c )
00481                 if values:
00482                         for v in values:
00483                                 
00484                                 r = self.recordById( v['id'] )
00485                                 r.set(v, signal=False)
00486 
00487         
00488         
00489         def unloadedIds(self):
00490                 self.ensureUpdated()
00491                 ids = []
00492                 for x in self.records:
00493                         if isinstance(x, Record):
00494                                 if x.id and not x._loaded:
00495                                         ids.append( x.id )
00496                         elif x:
00497                                 ids.append( x )
00498                 return ids
00499 
00500         
00501         def loadedRecords(self):
00502                 records = []
00503                 for x in self.records:
00504                         if isinstance(x, Record):
00505                                 if x.id and x._loaded:
00506                                         records.append( x )
00507                 return records
00508 
00509         
00510         def ids(self):
00511                 ids = []
00512                 for x in self.records:
00513                         if isinstance(x, Record):
00514                                 ids.append( x.id )
00515                         else:
00516                                 ids.append( x )
00517                 return ids
00518 
00519         
00520         def newRecords(self):
00521                 records = []
00522                 for x in self.records:
00523                         if not isinstance(x, Record):
00524                                 continue
00525                         if x.id:
00526                                 continue
00527                         records.append( x )
00528                 return records
00529 
00530         
00531         def count(self):
00532                 self.ensureUpdated()
00533                 return len(self.records)
00534 
00535         def __iter__(self):
00536                 self.ensureUpdated()
00537                 self.ensureAllLoaded()
00538                 return iter(self.records)
00539 
00540         
00541         
00542         def modelById(self, id):
00543                 record = self.recordById( id )
00544                 if not record:
00545                         return None
00546                 return record
00547         __getitem__ = modelById
00548 
00549         
00550         def modelByIndex(self, row):
00551                 record = self.recordByIndex( row )
00552                 return record
00553 
00554         
00555         
00556         def indexOfRecord(self, record):
00557                 if record in self.records:
00558                         return self.records.index(record)
00559                 else:
00560                         return -1
00561                 
00562         
00563         
00564         def indexOfId(self, id):
00565                 i = 0
00566                 for record in self.records:
00567                         if isinstance( record, Record ):
00568                                 if record.id == id:
00569                                         return i
00570                         elif record == id:
00571                                 return i
00572                         i += 1
00573                 return -1
00574 
00575         
00576         def recordExists(self, record):
00577                 return record in self.records
00578 
00579         
00580         
00581         def recordById(self, id):
00582                 for record in self.records:
00583                         if isinstance( record, Record ):
00584                                 if record.id == id:
00585                                         return record
00586                         elif record == id:
00587                                 idx = self.records.index( id )
00588                                 record = Record(id, self, parent=self.parent)
00589                                 self.connect(record,SIGNAL('recordChanged( PyQt_PyObject )'), self.recordChanged )
00590                                 self.connect(record,SIGNAL('recordModified( PyQt_PyObject )'),self.recordModified)
00591                                 self.records[idx] = record 
00592                                 return record
00593 
00594         
00595         def recordByIndex(self, row):
00596                 record = self.records[row]
00597                 if isinstance( record, Record ):
00598                         return record
00599                 else:
00600                         record = Record(record, self, parent=self.parent)
00601                         self.connect(record,SIGNAL('recordChanged( PyQt_PyObject )'), self.recordChanged )
00602                         self.connect(record,SIGNAL('recordModified( PyQt_PyObject )'),self.recordModified)
00603                         self.records[row] = record
00604                         return record
00605         
00606         
00607         def isWizard(self):
00608                 return self.resource.startswith('wizard.')
00609 
00610         
00611         
00612         def ensureModelLoaded(self, record):
00613                 self.ensureUpdated()
00614                 
00615                 if not record.id:
00616                         record.createMissingFields()
00617                         return
00618                 if record.isFullyLoaded():
00619                         return
00620 
00621                 c = Rpc.session.context.copy()
00622                 c.update( self.context() )
00623                 ids = self.ids()
00624                 pos = ids.index(record.id) / self.limit
00625 
00626                 queryIds = ids[pos * self.limit: pos * self.limit + self.limit]
00627                 if None in queryIds:
00628                         queryIds.remove( None )
00629 
00630                 missingFields = record.missingFields()
00631 
00632                 self.disableSignals()
00633                 c['bin_size'] = True
00634                 values = self.rpc.read(queryIds, missingFields, c)
00635                 if values:
00636                         for v in values:
00637                                 id = v['id']
00638                                 if 'id' not in missingFields:
00639                                         del v['id']
00640                                 self.recordById(id).set(v, signal=False)
00641                 self.enableSignals()
00642                 
00643                 
00644                 
00645                         
00646                         
00647                                 
00648                                         
00649                         
00650                                 
00651 
00652         
00653         def setDomain(self, value):
00654                 
00655                 
00656                 
00657                 if not value:
00658                         self._domain = []
00659                 else:
00660                         self._domain = value
00661                 if Settings.value( 'koo.load_on_open', True ):
00662                         self.updated = False
00663         
00664         
00665         def domain(self):
00666                 return self._domain
00667 
00668         
00669         
00670         
00671         
00672         def setFilter(self, value):
00673                 if value == None:
00674                         self._filter = []
00675                 else:
00676                         self._filter = value
00677                 self.updated = False
00678         
00679         
00680         def filter(self):
00681                 return self._filter
00682 
00683         
00684         
00685         
00686         
00687         
00688         
00689         
00690         def setDomainForEmptyGroup(self):
00691                 self.setDomain([('id','in',[])])
00692                 self.clear()
00693 
00694         
00695         def isDomainForEmptyGroup(self):
00696                 return self.domain() == [('id','in',[])]
00697 
00698         
00699         def update(self):
00700                 
00701                 
00702                 self._context.update(Rpc.session.context)
00703                 self.rpc = RpcProxy(self.resource)
00704                 
00705                 self.updated = False
00706                 self.sort( self.toBeSortedField, self.toBeSortedOrder )
00707 
00708         
00709         def ensureUpdated(self):
00710                 if self.updated:
00711                         return
00712                 self.update()
00713 
00714         
00715         def sort(self, field, order):
00716                 self.toBeSortedField = field
00717                 self.toBeSortedOrder = order
00718                 if self._sortMode == self.SortAllItems:
00719                         self.sortAll( field, order )
00720                 else:
00721                         self.sortVisible( field, order )
00722 
00723         
00724         def sortAll(self, field, order):
00725                 if self.updated and field == self.sortedField and order == self.sortedOrder:
00726                         return
00727 
00728                 
00729                 
00730                 
00731                 if self.isModified():
00732                         self.emit( SIGNAL("sorting"), self.SortingNotPossibleModified )
00733                         return
00734 
00735                 oldSortedField = self.sortedField
00736 
00737                 
00738                 
00739                 self.sortedField = field
00740                 self.sortedOrder = order
00741                 self.updated = True
00742 
00743                 sorted = False
00744                 sortingResult = self.SortingPossible
00745 
00746                 if self._domain + self._filter == [('id','in',[])]:
00747                         
00748                         
00749                         
00750                         
00751                         
00752                         ids = []
00753                 elif not field in self.fields.keys():
00754                         
00755                         
00756                         ids = self.rpc.search( self._domain + self._filter, 0, False, False, self._context )
00757                 else:
00758                         type = self.fields[field]['type']
00759                         if type == 'one2many' or type == 'many2many':
00760                                 
00761                                 sortingResult = self.SortingNotPossible
00762                         elif type == 'many2one':
00763                                 
00764                                 orderby = '"%s"' % field
00765                                 if order == Qt.AscendingOrder:
00766                                         orderby += " ASC"
00767                                 else:
00768                                         orderby += " DESC"
00769                                 try:
00770                                         ids = Rpc.session.call('/koo', 'search', self.resource, self._domain + self._filter, 0, 0, orderby, self._context )
00771                                         sortingResult = self.SortingPossible
00772                                         sorted = True
00773                                 except:
00774                                         sortingResult = self.SortingOnlyGroups
00775 
00776                         
00777                         
00778                         
00779                         stored = self.fields[field].get('stored',True)
00780                         if not stored:
00781                                 sortingResult = self.SortingNotPossible
00782 
00783                         if not sorted and sortingResult != self.SortingNotPossible:
00784                                 
00785                                 
00786                                 
00787                                 
00788 
00789                                 
00790                                 
00791                                 orderby = '"%s"' % field 
00792                                 if order == Qt.AscendingOrder:
00793                                         orderby += " ASC"
00794                                 else:
00795                                         orderby += " DESC"
00796 
00797                                 try:
00798                                         
00799                                         ids = Rpc.session.call('/object', 'execute', self.resource, 'search', self._domain + self._filter, 0, 0, orderby, self._context )
00800                                 except:
00801                                         
00802                                         
00803                                         sortingResult = self.SortingNotPossible
00804 
00805                 if sortingResult != self.SortingNotPossible:
00806                         self.clear()
00807                         
00808                         self.load( ids )
00809                 elif oldSortedField == self.sortedField or not self.ids():
00810                         
00811                         
00812                         
00813                         
00814                         ids = self.rpc.search(self._domain + self._filter, 0, 0, False, self._context )
00815                         self.clear()
00816                         
00817                         self.load( ids )
00818 
00819                 self.emit( SIGNAL("sorting"), sortingResult )
00820 
00821         
00822         def sortVisible(self, field, order):
00823                 if self.updated and field == self.sortedField and order == self.sortedOrder:
00824                         return
00825 
00826                 if not self.updated:
00827                         ids = self.rpc.search( self._domain + self._filter, 0, self.limit, False, self._context )
00828                         self.clear()
00829                         self.load( ids )
00830                 
00831                 if not field in self.fields:
00832                         return
00833 
00834                 self.ensureAllLoaded()
00835 
00836                 if field != self.sortedField:
00837                         
00838 
00839                         
00840                         def ignoreCase(record):
00841                                 v = record.value(field)
00842                                 if isinstance(v, unicode) or isinstance(v, str):
00843                                         return v.lower()
00844                                 else:
00845                                         return v
00846 
00847                         type = self.fields[field]['type']
00848                         if type == 'one2many' or type == 'many2many':
00849                                 self.records.sort( key=lambda x: len(x.value(field).group) )
00850                         else:
00851                                 self.records.sort( key=ignoreCase )
00852                         if order == Qt.DescendingOrder:
00853                                 self.records.reverse()
00854                 else:
00855                         
00856                         if order != self.sortedOrder:
00857                                 self.records.reverse()
00858 
00859                 self.sortedField = field
00860                 self.sortedOrder = order
00861                 self.updated = True
00862 
00863                 
00864                 self.emit( SIGNAL('recordsInserted(int,int)'), 0, len(self.records)-1 )
00865 
00866                 self.emit( SIGNAL("sorting"), self.SortingPossible )
00867                 
00868         
00869         def cancel(self):
00870                 for record in self.records[:]:
00871                         if isinstance( record, Record ):
00872                                 if not record.id:
00873                                         self.freeRecord( record )
00874                                 elif record.isModified():
00875                                         record.cancel()
00876                         else:
00877                                 if not record:
00878                                         self.freeRecord( record )
00879 
00880         
00881         
00882         
00883         def freeRecord(self, record):
00884                 self.records.remove( record )
00885                 if isinstance(record, Record):
00886                         self.disconnect( record, SIGNAL('recordChanged( PyQt_PyObject )'), self.recordChanged )
00887                         self.disconnect( record, SIGNAL('recordModified( PyQt_PyObject )'), self.recordModified )
00888 
00889         
00890         def isModified(self):
00891                 for record in self.records:
00892                         if isinstance( record, Record ):
00893                                 if record.isModified():
00894                                         return True
00895                 return False
00896 
00897         
00898         def isRecordModified(self, id):
00899                 for record in self.records:
00900                         if isinstance( record, Record ):
00901                                 if record.id == id:
00902                                         return record.isModified()
00903                         elif record == id:
00904                                 return False
00905                 return False    
00906 
00907         
00908         
00909         
00910         def isFieldRequired(self, fieldName):
00911                 required = self.fields[ fieldName ].get('required', False)
00912                 if isinstance(required, bool):
00913                         return required
00914                 if isinstance(required, str) or isinstance(required, unicode):
00915                         if required.lower() == 'true':
00916                                 return True
00917                         if required.lower() == 'false':
00918                                 return False
00919                 return bool(int(required))
00920                 
00921 
00922