Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Qt for Python
  4. ItemFromIndex using both QSortFilterProxyModel and QIdentityProxyModel
Qt 6.11 is out! See what's new in the release blog

ItemFromIndex using both QSortFilterProxyModel and QIdentityProxyModel

Scheduled Pinned Locked Moved Unsolved Qt for Python
4 Posts 2 Posters 770 Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • M Offline
    M Offline
    misantroop
    wrote on last edited by
    #1

    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_())
    
    JonBJ 1 Reply Last reply
    0
    • M misantroop

      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_())
      
      JonBJ Online
      JonBJ Online
      JonB
      wrote on last edited by JonB
      #2

      @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 index for validity at this point, no point going further if that is invalid.

      Also check which model a returned index refers to?

                      index = self.model().mapToSource(select)
                      self.c_item = source_model.itemFromIndex(
                          index
      

      I'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 in source_model? Try Q_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?

      1 Reply Last reply
      1
      • M Offline
        M Offline
        misantroop
        wrote on last edited by
        #3

        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)
        
        JonBJ 1 Reply Last reply
        0
        • M misantroop

          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)
          
          JonBJ Online
          JonBJ Online
          JonB
          wrote on last edited by JonB
          #4

          @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?

          1 Reply Last reply
          2

          • Login

          • Login or register to search.
          • First post
            Last post
          0
          • Categories
          • Recent
          • Tags
          • Popular
          • Users
          • Groups
          • Search
          • Get Qt Extensions
          • Unsolved