def _updateField(self, row, col, val):
        self._loading -= 1
        if row >= len(self._cache): return

        self._cache[row]['cache'][col]['loading'] = False

        # if isinstance(val, QtGui.QPixmap):
        #     print val, val.width(), val.height()

        if val != None and self._types[col] == "image" and not isinstance(val, QtGui.QPixmap):
            if self._typeArgs[col] and len(self._typeArgs[col]) > 0:
                d = self._peer.getImage(row, self._typeArgs[col], documentID=val)
            else:
                d = self._peer.getImage(row, val)
            d.addCallback(partial(self._updateField, row, col))

        val = FXUI.renderType(val, self._types[col], self._typeArgs[col]) 

        self._cache[row]['loading'] = False
        self._cache[row]['cache'][col]['cached'] = True
        self._cache[row]['cache'][col]['value']  = val

        if self._minRow == -1 or row < self._minRow: self._minRow = row
        if self._maxRow == -1 or row > self._maxRow: self._maxRow = row

        if self._updateChangedDeferred is not None:
            try:
                self._updateChangedDeferred.cancel()
            except: pass

        from twisted.internet import reactor
        self._updateChangedDeferred = reactor.callLater(1.0, self._updateChanged)
        # self.dataChanged.emit(self.index(row, col), self.index(row, col))
        # if self._loading == 0: self.layoutChanged.emit()
        return val
    def data(self, index, role): 
        if not index.isValid(): 
            return None
        elif role != QtCore.Qt.EditRole and role != QtCore.Qt.DisplayRole and role != QtCore.Qt.SizeHintRole:  
            return None

        row = index.row()
        if self.rowCount(self._parent) <= row: return None

        col = index.column()
        if len(self._columns) <= col: return None
 

        if role == QtCore.Qt.SizeHintRole:
            if self._columns[col] in self._sizeHints and isinstance(self._sizeHints[self._columns[col]], dict):
                hint = self._sizeHints[self._columns[col]]
                w = self._minColumnWidth
                h = self._minRowHeight
                if 'width' in hint and hint['width'] is not None: w = int(hint['width'])
                if 'height' in hint and hint['height'] is not None: h = int(hint['height'])
                # print w, h, col
                return QtCore.QSize(w, h)
            else:
                size = QtCore.QSize(self._minColumnWidth, self._minRowHeight)

            # if isinstance(val, QtGui.QPixmap):
            #     size.setWidth(max(val.width()+1, size.width()))
            #     size.setHeight(max(val.height(), size.height()))
            return size

        key = self.getKey(row)

        path = self._columns[col]
        type = self._types[col]
        typeArg = self._typeArgs[col]

        pathes = []
        types = []
        typeArgs = []
        
        if path != None and '|' in path:
            pathes = path.split('|')

            if type != None and '|' in type:
                types = type.split('|')
            else:
                for p in pathes: types.append(type)

            if typeArg != None and '|' in typeArg:
                typeArgs = typeArg.split('|')
            else:
                for p in pathes: typeArgs.append(typeArg)

            type = types[-1]
            for i in range(len(types), len(pathes)):
                types.append(type)

            typeArg = typeArgs[-1]
            for i in range(len(typeArgs), len(pathes)):
                typeArgs.append(typeArg)
        else:
            pathes = [path] 
            types = [type]
            typeArgs = [typeArg]

        i = 0
        for i in range(len(pathes)):
            path = pathes[i]
            type = types[i]
            typeArg = typeArgs[i]

            if path == '*':
                if (self._isList and key < len(self._data)) or key in self._data:
                    val = self._data[key]
                else:
                    val = u""
            elif path == '__key__':
                val = key
            else:
                val = PathHelper.getValue(self._data[key], path)
                # print "get", key, self._data[key], self._columns[col], val

            if type == "imagelist":
                if not isinstance(val, list):
                    continue

                images = []

                for dct in val:
                    if isinstance(dct, (unicode, str)):
                        images.append(dct)
                    elif isinstance(dct, dict):
                        if typeArg in dct:
                            images.append(dct[typeArg])
                    elif isinstance(dct, list):
                        if typeArg != None and int(typeArg) < len(dct):
                            images.append(dct[int(typeArg)])

                if str(images) in self._imageCache:
                    return self._imageCache[str(images)]

                dList = []

                for img in images:
                    dList.append(self._peer.getImage(img))

                d = defer.DeferredList(dList)
                d.addCallback(partial(self._updateField, row, col, str(images)))
                return  [QtGui.QPixmap()]

            if type == "image":
                if val in self._imageCache:
                    val = self._imageCache[val]
                else:
                    if not self._peer.hasImage(val):
                        val = None
                        continue

                    d = self._peer.getImage(val)
                    d.addCallback(partial(self._updateField, row, col, val))
                    val = QtGui.QPixmap()
            else:
                val = FXUI.renderType(val, type, typeArg, role == QtCore.Qt.EditRole) 

            if val != None:
                return val
        return val