QSortFilterProxyModel + QAbstractItemModel modelIndex.internalPointer()导致崩溃

时间:2014-10-27 19:35:13

标签: python pyqt qabstractitemmodel

我在PyQt 4.8(Python 2.7)中实现了自己的QAbstractItemModel:

class FriendListModel(QtCore.QAbstractItemModel):
def __init__(self, groups, client):
    QtCore.QAbstractItemModel.__init__(self)
    self.root = groups
    self.client = client

    self.header = ['Player', 'Land', 'Rating', '#']

def columnCount(self, parent):
    return len(self.header);

def headerData(self, col, orientation, role):
    if orientation == QtCore.Qt.Horizontal and role == QtCore.Qt.DisplayRole:
        return self.header[col]
    return None

def rowCount(self, parentIndex):
    pointer = parentIndex.internalPointer()
    # if root level
    if pointer is None:
        return len(self.root)
    # if on FriendGroup level
    if hasattr(pointer, 'users'):
        return len(pointer.users)
    return 0

def index(self, row, column, parentIndex):
    pointer = parentIndex.internalPointer()
    # if root element, use root list
    if pointer is None:
        return self.createIndex(row, column, self.root[row])
    # if on FriendGroup level
    if hasattr(pointer, 'users'):
        return self.createIndex(row, column, pointer.users[row])
    return self.createIndex(row, column, None)

def data(self, index, role):
    if not index.isValid():
        return None
    pointer = index.internalPointer()
    if role == QtCore.Qt.DecorationRole and isinstance(pointer, User) and index.column() == 0:
        if pointer.avatarNotLoaded:
            pointer.loadPixmap()
            if not pointer.avatarNotLoaded:
                print 'loaded'
                self.emit(QtCore.SIGNAL('modelChanged'), index, index)
        return pointer.pix

    if role == QtCore.Qt.UserRole:
        if isinstance(pointer, FriendGroup):
            return None
        if index.column() == 0:
            return pointer.username

    if role == QtCore.Qt.DisplayRole or role == QtCore.Qt.UserRole:
        if isinstance(pointer, FriendGroup):
            if index.column() == 0:
                return pointer.name
            return None
        else:
            if index.column() == 1:
                return pointer.country
            if index.column() == 2:
                return pointer.rating
            if index.column() == 3:
                return '#'
            return pointer.name

    return None

def parent(self, index):
    if not index.isValid():
        return QtCore.QModelIndex()
    pointer = index.internalPointer()
    if hasattr(pointer, 'users'):
        return QtCore.QModelIndex()
    else:
        row = 0 if pointer.group == 'online' else 1
        return self.createIndex(row, 0, pointer.group)

在运行时,我向模型添加元素:

    def addFriend(self, groupIndex, username):
    '''
    groupIndex: 0 = online, 1 = offline
    '''
    self.updateTopLabel()
    n = len(self.model.root[groupIndex].users)
    self.model.beginInsertRows(self.model.index(groupIndex, 0, QtCore.QModelIndex()), n, n)
    self.model.root[groupIndex].addUser(username)
    self.model.endInsertRows()

所有似乎都是正确的(来自ui),但如果我尝试从ModelIndex调用internalPointer,应用程序崩溃了。 (APPCRASH,python.exe不再工作,没有stackstrace,...)

@QtCore.pyqtSlot(QtCore.QPoint)
def on_friendlist_customContextMenuRequested(self, pos):

    modelIndex = self.friendlist.indexAt(pos)
    if modelIndex == None or not modelIndex.isValid():
        return
    pointer = modelIndex.internalPointer()
    ...

我不知道我做错了什么。 有什么提示怎么调试呢?

我搜索了类似的问题,但没有任何结果。

修改

如果删除QSortFilterProxyModel,则一切正常。

        #proxy = QtGui.QSortFilterProxyModel()
        #proxy.setSourceModel(self.model)
        #proxy.setSortRole(QtCore.Qt.UserRole)
        #self.friendlist.setModel(proxy)
        self.friendlist.setModel(self.model)

我发现了自己的错误。我使用了QSortFilterProxyModel并忘了映射回来。

@QtCore.pyqtSlot(QtCore.QPoint)
def on_friendlist_customContextMenuRequested(self, pos):

    modelIndex = self.friendlist.indexAt(pos)
    if modelIndex == None or not modelIndex.isValid():
        return
    pointer = self.proxy.mapToSource(modelIndex).internalPointer()
    if pointer == None:
        return
    playername = pointer.name
    print playername

https://github.com/IDragonfire/lobby/commit/6c49571f5619e85bb9cea76d84296f158ef81a9b

代码: https://github.com/IDragonfire/lobby/blob/d44ad39e7ce077918a18fe4aee4299b76a2b17b6/src/friendlist/friendlistdialog.py#L106

0 个答案:

没有答案