ItemFromIndex using both QSortFilterProxyModel and QIdentityProxyModel
-
How to get the item from the source model when using both QSortFilterProxyModel and QIdentityProxyModel? If I use either ProxyModel alone, it works perfectly but when using both, itemFromIndex returns None.
The example is in PyQt but I assume the behaviour is the same in PySide.
import sys, traceback from PyQt5.QtWidgets import * from PyQt5.QtGui import * from PyQt5.QtCore import * class TreeView(QTreeView): def __init__(self, *args, **kwds): super().__init__(*args, **kwds) @pyqtSlot() def item_selected(self): try: if select := self.selectedIndexes()[0]: sort_model = self.model().sourceModel() source_model = sort_model.sourceModel() index = self.model().mapToSource(select) self.c_item = source_model.itemFromIndex( index ) print(self.c_item.text()) except Exception as exc: traceback.print_exc() class MainWindow(QWidget): def __init__(self): super().__init__() model = QStandardItemModel() model.setHorizontalHeaderLabels(['Column 1']) item_1 = QStandardItem("Item 1") item_1.setData({"some_data": 11}) item_2 = QStandardItem("Item 2") item_2.setData({"some_data": 22}) model.appendRow(item_1) model.appendRow(item_2) # Create the identity proxy identity_proxy = QIdentityProxyModel() # Create the sort filter proxy sort_filter_proxy = QSortFilterProxyModel() sort_filter_proxy.setSourceModel(model) # Set the source model for the identity proxy identity_proxy.setSourceModel(sort_filter_proxy) view = TreeView() view.setModel(identity_proxy) view.selectionModel().selectionChanged.connect( view.item_selected ) layout = QVBoxLayout() layout.addWidget(view) self.setLayout(layout) self.show() if __name__ == '__main__': app = QApplication(sys.argv) w = MainWindow() sys.exit(app.exec_()) -
How to get the item from the source model when using both QSortFilterProxyModel and QIdentityProxyModel? If I use either ProxyModel alone, it works perfectly but when using both, itemFromIndex returns None.
The example is in PyQt but I assume the behaviour is the same in PySide.
import sys, traceback from PyQt5.QtWidgets import * from PyQt5.QtGui import * from PyQt5.QtCore import * class TreeView(QTreeView): def __init__(self, *args, **kwds): super().__init__(*args, **kwds) @pyqtSlot() def item_selected(self): try: if select := self.selectedIndexes()[0]: sort_model = self.model().sourceModel() source_model = sort_model.sourceModel() index = self.model().mapToSource(select) self.c_item = source_model.itemFromIndex( index ) print(self.c_item.text()) except Exception as exc: traceback.print_exc() class MainWindow(QWidget): def __init__(self): super().__init__() model = QStandardItemModel() model.setHorizontalHeaderLabels(['Column 1']) item_1 = QStandardItem("Item 1") item_1.setData({"some_data": 11}) item_2 = QStandardItem("Item 2") item_2.setData({"some_data": 22}) model.appendRow(item_1) model.appendRow(item_2) # Create the identity proxy identity_proxy = QIdentityProxyModel() # Create the sort filter proxy sort_filter_proxy = QSortFilterProxyModel() sort_filter_proxy.setSourceModel(model) # Set the source model for the identity proxy identity_proxy.setSourceModel(sort_filter_proxy) view = TreeView() view.setModel(identity_proxy) view.selectionModel().selectionChanged.connect( view.item_selected ) layout = QVBoxLayout() layout.addWidget(view) self.setLayout(layout) self.show() if __name__ == '__main__': app = QApplication(sys.argv) w = MainWindow() sys.exit(app.exec_())@misantroop
I suggest you break your code down and check what is going on in stages. For example,index = self.model().mapToSource(select)Please check
indexfor validity at this point, no point going further if that is invalid.Also check which model a returned
indexrefers to?index = self.model().mapToSource(select) self.c_item = source_model.itemFromIndex( indexI'm thinking/guessing the first line returns an index in
sort_model = self.model().sourceModel()? If that is so then it wouldn't be right for looking up insource_model? TryQ_ASSERT(index.model() == source_model)if you expect above code to be right? I'm sort of expecting to see two calls to map to source, one via the proxy model and one via the identity model? -
This appears to work but it's not intuitive.
identity_index = self.model().mapToSource(select) index = sort_model.mapToSource(identity_index) item = source_model.itemFromIndex(index) -
This appears to work but it's not intuitive.
identity_index = self.model().mapToSource(select) index = sort_model.mapToSource(identity_index) item = source_model.itemFromIndex(index)@misantroop
Exactly. I don't see anything "unintuitive" about this, it's exactly what I would expect? Any "source model mappings" are only going to follow one level of source model, not all the way down through various layers of source models if that is what you were expecting?