从QAbstractListModel获取选定的项目

时间:2018-07-11 14:27:02

标签: python pyside

如何从包含自定义排序算法的自定义QAbstractListModel中检索正确选择的项目?

您可以通过简单地在UI中进行选择并查看控制台来测试该工具。您会看到它为所选项目打印了错误的信息。

我假设问题与我如何使用选择索引在模型中获取项目有关。

enter image description here

完整代码:

import os, sys
from PySide import QtGui, QtCore


class ExplorerItem(object):
    def __init__(self, name, tags):
        self.name = name
        self.tags = tags


class ElementModel(QtCore.QAbstractListModel):
    TagsRole = QtCore.Qt.UserRole + 1
    NameRole = QtCore.Qt.UserRole + 2

    def __init__(self, *args, **kwargs):
        QtCore.QAbstractListModel.__init__(self, *args, **kwargs)
        self._items = []
        self._icons = {}

    def rowCount(self, index=QtCore.QModelIndex()):
        return len(self._items)

    def addItem(self, item):
        self.beginInsertRows(QtCore.QModelIndex(), self.rowCount(), self.rowCount())
        self._items.append(item)
        self.endInsertRows()

    def getItem(self, index):
        row = index.row()
        if index.isValid() and 0 <= row < self.rowCount():
            return self._items[row]

    def data(self, index, role=QtCore.Qt.DisplayRole):
        if not index.isValid():
            return None
        if 0 <= index.row() < self.rowCount():
            item = self._items[index.row()]
            if role == ElementModel.TagsRole:
                return item.tags
            elif role == ElementModel.NameRole:
                return item.colors
            elif role == QtCore.Qt.DisplayRole:
                return item.name
            elif role == QtCore.Qt.TextAlignmentRole:
                return QtCore.Qt.AlignCenter


class ExplorerSortModel(QtGui.QSortFilterProxyModel):

    def __init__(self, *args, **kwargs):
        super(ExplorerSortModel, self).__init__(*args, **kwargs)
        self._patterns = {}
        self.setDynamicSortFilter(True)
        self.setSourceModel(ElementModel())
        self.sort(0, QtCore.Qt.AscendingOrder)


    def set_pattern(self, role, value):
        self._patterns[role] = value


    def lessThan(self, left, right):
        leftData = self.sourceModel()._items[left.row()]
        rightData = self.sourceModel()._items[right.row()]

        if leftData and rightData:
            l = getattr(leftData, 'name', '')
            r = getattr(rightData, 'name', '')
            return l > r

        return True


    def filterAcceptsRow(self, sourceRow, sourceParent):
        sm = self.sourceModel()
        ix = sm.index(sourceRow)
        if ix.isValid():
            val = True
            for role, fvalue in self._patterns.items():
                value = ix.data(role)
                val = val and self.filter(value, fvalue, role)
            return val
        return False


    @staticmethod
    def filter(value, fvalue, role):
        '''
        fvalue: search value
        value: properties value being tested
        '''
        if role == ElementModel.TagsRole:
            if fvalue == []:
                return True
            else:
                return all(any(x in y for y in value) for x in fvalue)
        elif role == ElementModel.NameRole:
            return True
        else:
            return False


class QExplorerWidget(QtGui.QWidget):

    def __init__(self, *args, **kwargs):
        super(QExplorerWidget, self).__init__(*args, **kwargs)
        self.resize(400,400)

        # control
        self.ui_explorer = QtGui.QListView()
        self.ui_explorer.setResizeMode(QtGui.QListView.Adjust)
        self.ui_explorer.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers)
        self.ui_explorer.setMovement(QtGui.QListView.Static)
        self.ui_explorer.setSpacing(10)

        self.explorer_model = ExplorerSortModel()
        self.ui_explorer.setModel(self.explorer_model)

        self.ui_explorer_selection = self.ui_explorer.selectionModel()

        lay = QtGui.QVBoxLayout()
        lay.addWidget(self.ui_explorer)
        self.setLayout(lay)

        # connections
        self.ui_explorer_selection.selectionChanged.connect(self.changed_selection)

        # test data
        self.explorer_model.sourceModel().addItem(ExplorerItem('John',['john','sports']))
        self.explorer_model.sourceModel().addItem(ExplorerItem('Apple',['apple','fruit']))
        self.explorer_model.sourceModel().addItem(ExplorerItem('Kevin',['kevin','money']))
        self.explorer_model.sourceModel().addItem(ExplorerItem('Zoo',['zoo','animals']))


    def changed_selection(self):
        indexes =  self.ui_explorer_selection.selectedIndexes()
        for index in indexes:
            item = self.explorer_model.sourceModel().getItem(index)
            print item.name, item.tags, index


if __name__ == '__main__':
    ''
    app = QtGui.QApplication(sys.argv)
    ex = QExplorerWidget()
    ex.show()
    sys.exit(app.exec_())

1 个答案:

答案 0 :(得分:1)

QModelIndex的{​​{1}}属于在视图中建立的模型,在这种情况下为selectedIndexes,因此这些索引不能直接传递给ElementModel的ExplorerSortModel方法,因为该方法期望getItem()属于QModelIndex

对于您来说,您必须使用ElementModel方法将属于QModelIndex的{​​{1}}转换为属于ExplorerSortModel的相应QModelIndex

ElementModel