How can I properly implement QSortFilterProxyModel.parent() to handle a virtual column?
Solved
Qt for Python
-
I have the following working code, which opens a
QFileDialog
with an extra column that shows the file name again (pointless, I know, but it’s a result of simplifying my issue):from PySide2 import QtCore, QtWidgets class MyProxyModel(QtCore.QSortFilterProxyModel): def __init__(self, parent=None): super(MyProxyModel, self).__init__(parent) self._parents = {} def mapToSource(self, index): if index.column() == 4: return QtCore.QModelIndex() return super(MyProxyModel, self).mapToSource(index) def columnCount(self, index): return 5 def data(self, index, role=QtCore.Qt.DisplayRole): if role == QtCore.Qt.DisplayRole and index.column() == 4: return self.index(index.row(), 0, self._parents[index]).data(role) return super(MyProxyModel, self).data(index, role) def headerData(self, section, orientation, role=QtCore.Qt.DisplayRole): if section == 4 and orientation == QtCore.Qt.Horizontal and role == QtCore.Qt.DisplayRole: return 'My Column' return super(MyProxyModel, self).headerData(section, orientation, role) def index(self, row, column, parent=QtCore.QModelIndex()): if column == 4: index = self.createIndex(row, column) self._parents[index] = parent return index return super(MyProxyModel, self).index(row, column, parent) def parent(self, index): if index.column() == 4: return QtCore.QModelIndex() return super(MyProxyModel, self).parent(index) QtWidgets.QApplication([]) dialog = QtWidgets.QFileDialog() dialog.setOption(dialog.DontUseNativeDialog, True) dialog.setProxyModel(MyProxyModel(dialog)) dialog.exec_()
As you can see,
parent()
is returning an invalid index for items of column 4, and instead I’m retrieving the actual parent insidedata()
, which isn’t ideal. But if I try the following, it exits with an access violation:(...) def data(self, index, role=QtCore.Qt.DisplayRole): if role == QtCore.Qt.DisplayRole and index.column() == 4: # Either return causes access violation. return self.index(index.row(), 0, self.parent(index)).data(role) return self.index(index.row(), 0, index.parent()).data(role) return index.sibling(index.row(), 0).data(role) return super(MyProxyModel, self).data(index, role) (...) def parent(self, index): if index.column() == 4: return self._parents[index] return super(MyProxyModel, self).parent(index) (...)
I also tried leveraging
QModelIndex
’s internal pointer, with the same result (access violation):# No __init__() defined; data() exactly like above. (...) def index(self, row, column, parent=QtCore.QModelIndex()): if column == 4: return self.createIndex(row, column, parent) return super(MyProxyModel, self).index(row, column, parent) def parent(self, index): if index.column() == 4: return index.internalPointer() return super(MyProxyModel, self).parent(index) (...)
Pretty sure I’m missing something, but I can’t figure out what it is…
-
Hi and welcome to devnet,
You can take some inspiration from KDE's KExtraColumnsProxyModel.