Solved How can I properly implement QSortFilterProxyModel.parent() to handle a virtual column?
-
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…
-
Thanks @SGaist! I just got a solution on StackOverflow, so I’m marking this as solved, but it’s always great to see how the pros do it, so I’m definitely reading about
KExtraColumnsProxyModel
too 😊 -
Huh, just realised that I’m constantly getting
Can't select indexes from different model or with different parents
messages and it’s not letting me select any file, so I’m definitely doing something wrong 😅 -
Hi and welcome to devnet,
You can take some inspiration from KDE's KExtraColumnsProxyModel.
-
Thanks @SGaist! I just got a solution on StackOverflow, so I’m marking this as solved, but it’s always great to see how the pros do it, so I’m definitely reading about
KExtraColumnsProxyModel
too 😊