Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. `QSortFilterProxyModel` incorrect mapping indexes from source model
Forum Updated to NodeBB v4.3 + New Features

`QSortFilterProxyModel` incorrect mapping indexes from source model

Scheduled Pinned Locked Moved Unsolved General and Desktop
17 Posts 3 Posters 973 Views 1 Watching
  • 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.
  • Please_Help_me_DP Offline
    Please_Help_me_DP Offline
    Please_Help_me_D
    wrote on last edited by Please_Help_me_D
    #1

    Hi,

    I have a QTableView where I set QSortFilterProxyModel and the source model is QStandardItemModel.

    Let's suppose I have 10 rows in the table and then I do the resort of items based on some column (like sort items in alphabetical order by file names).

    Then user adds new items in the table and there we have some code for that:

        d->model->insertRow(d->model->rowCount());
        int row = d->model->rowCount() - 1;
        int proxy_row = d->proxy->mapFromSource(
          d->model->index(row, 0)).row();       //  proxy_row is incorrect!!!
    
        QStandardItem *readFileItem = new QStandardItem(name);
        readFileItem->setFlags(readFileItem->flags() & ~Qt::ItemIsEditable);
        d->model->setItem(row, d->tableHdrNames.indexOf("read file"), readFileItem);
    

    The problem here is proxy_row will be incorrect probably 0 even if new row is the last row of the table (I mean the last one that is displayed in the table GUI).

    This seems to be fixed and tested when I don't insert/append new row but simply do d->model->setItem(...) which automatically adds new row if needed:

        QStandardItem *readFileItem = new QStandardItem(name);
        readFileItem->setFlags(readFileItem->flags() & ~Qt::ItemIsEditable);
        d->model->setItem(d->model->rowCount(), d->tableHdrNames.indexOf("read file"), readFileItem);
    
        int row = d->model->rowCount() - 1;
        int proxy_row = d->proxy->mapFromSource(
          d->model->index(row, 0)).row();       //  proxy_row is correct
    

    I don't understand why this happens and it would be enough for me to use the second approach but my application is complicated enough so the PythonQt is adjusted as well so python scripts maybe run from C++ side and the second approach doesn't fix the issue in this case. I mean d->proxy->mapFromSource(...) gives incorrect row even when I use d->model->setItem(...) from Python script (even though this helps from C++ side).

    Maybe somebody have ideas what are the possible reasons of that?

    And this is how these objects are tight to each other:

      proxy = new QSortFilterProxyModel();
      model = new QStandardItemModel();
      proxy->setSourceModel(model);
      tableView->setModel(proxy);
    

    Qt 5.15.2
    Windows 11, msvc 2019

    1 Reply Last reply
    0
    • JonBJ Online
      JonBJ Online
      JonB
      wrote on last edited by
      #2

      @Please_Help_me_D said in `QSortFilterProxyModel` incorrect mapping indexes from source model:

      This seems to be fixed and tested when I don't insert/append new row

      Is this related to https://doc.qt.io/qt-6/qsortfilterproxymodel.html#dynamicSortFilter-prop

      Note that you should not update the source model through the proxy model when dynamicSortFilter is true.

      ?

      Please_Help_me_DP 1 Reply Last reply
      2
      • JonBJ JonB

        @Please_Help_me_D said in `QSortFilterProxyModel` incorrect mapping indexes from source model:

        This seems to be fixed and tested when I don't insert/append new row

        Is this related to https://doc.qt.io/qt-6/qsortfilterproxymodel.html#dynamicSortFilter-prop

        Note that you should not update the source model through the proxy model when dynamicSortFilter is true.

        ?

        Please_Help_me_DP Offline
        Please_Help_me_DP Offline
        Please_Help_me_D
        wrote on last edited by
        #3

        @JonB thank you for the hint!

        I didn't modify dynamicSortFilter for that proxy but I have to duble check this as I have a feeling this may be the reason of that.

        I will comeback with the results of testing!

        JonBJ 1 Reply Last reply
        0
        • Please_Help_me_DP Please_Help_me_D

          @JonB thank you for the hint!

          I didn't modify dynamicSortFilter for that proxy but I have to duble check this as I have a feeling this may be the reason of that.

          I will comeback with the results of testing!

          JonBJ Online
          JonBJ Online
          JonB
          wrote on last edited by JonB
          #4

          @Please_Help_me_D You are supposed to modify it off default (true) if you are doing what it says. At any rate try setting it false and see if that modifies behaviour?

          Please_Help_me_DP 1 Reply Last reply
          1
          • JonBJ JonB

            @Please_Help_me_D You are supposed to modify it off default (true) if you are doing what it says. At any rate try setting it false and see if that modifies behaviour?

            Please_Help_me_DP Offline
            Please_Help_me_DP Offline
            Please_Help_me_D
            wrote on last edited by
            #5

            @JonB I've tried setting dynamicSortFilter to True and False but unfortunately that didn't help...

            I have a feeling that source model either doesn't send some signal when new row is added or the connection type between proxy model and source model is not the default so it there is no time to proxy receives and process the signal. I will try to look into the source code of these models.

            JonBJ 1 Reply Last reply
            0
            • Please_Help_me_DP Please_Help_me_D

              @JonB I've tried setting dynamicSortFilter to True and False but unfortunately that didn't help...

              I have a feeling that source model either doesn't send some signal when new row is added or the connection type between proxy model and source model is not the default so it there is no time to proxy receives and process the signal. I will try to look into the source code of these models.

              JonBJ Online
              JonBJ Online
              JonB
              wrote on last edited by
              #6

              @Please_Help_me_D
              "Timing" cannot/should not be an issue.
              If it's your own source model make sure you do the right thing for insertRows per the docs. There is a also a model tester per https://doc.qt.io/qt-6/qabstractitemmodeltester.html. Oh if you are using base QStandardItemModel then obviously it behaves correctly.

              Otherwise please show a complete but minimal example of what goes wrong.

              Just glancing and thinking:

              d->model->insertRow(d->model->rowCount());
              
              int proxy_row = d->proxy->mapFromSource(
                  d->model->index(row, 0)).row();       //  proxy_row is incorrect!!!
              

              First line inserts a new blank row. Meaning all columns are empty/QVariant(). So if you are sorting (ascending) by anything it will likely come first, so proxy row will be 0. So that seems correct to me. I think you need to clarify exactly what you think is wrong.

              Please_Help_me_DP 1 Reply Last reply
              1
              • JonBJ JonB

                @Please_Help_me_D
                "Timing" cannot/should not be an issue.
                If it's your own source model make sure you do the right thing for insertRows per the docs. There is a also a model tester per https://doc.qt.io/qt-6/qabstractitemmodeltester.html. Oh if you are using base QStandardItemModel then obviously it behaves correctly.

                Otherwise please show a complete but minimal example of what goes wrong.

                Just glancing and thinking:

                d->model->insertRow(d->model->rowCount());
                
                int proxy_row = d->proxy->mapFromSource(
                    d->model->index(row, 0)).row();       //  proxy_row is incorrect!!!
                

                First line inserts a new blank row. Meaning all columns are empty/QVariant(). So if you are sorting (ascending) by anything it will likely come first, so proxy row will be 0. So that seems correct to me. I think you need to clarify exactly what you think is wrong.

                Please_Help_me_DP Offline
                Please_Help_me_DP Offline
                Please_Help_me_D
                wrote on last edited by
                #7

                @JonB I successfully created minimal project that shows the
                issue.

                link to the minimal example project to Download

                Steps to reproduce:

                1. build and run the app
                2. click on Add file button
                3. add several arbitrary files
                4. manually resort the table view by cicking on the File column name
                5. click Add file and add few more files
                6. look at the resulted table

                Here is the result. As you can see there is blank cells because proxy_row is incorrect.

                a2ed6a20-647e-45c8-abc3-ff5bd3e1e036-image.png

                Christian EhrlicherC 1 Reply Last reply
                0
                • Please_Help_me_DP Please_Help_me_D

                  @JonB I successfully created minimal project that shows the
                  issue.

                  link to the minimal example project to Download

                  Steps to reproduce:

                  1. build and run the app
                  2. click on Add file button
                  3. add several arbitrary files
                  4. manually resort the table view by cicking on the File column name
                  5. click Add file and add few more files
                  6. look at the resulted table

                  Here is the result. As you can see there is blank cells because proxy_row is incorrect.

                  a2ed6a20-647e-45c8-abc3-ff5bd3e1e036-image.png

                  Christian EhrlicherC Offline
                  Christian EhrlicherC Offline
                  Christian Ehrlicher
                  Lifetime Qt Champion
                  wrote on last edited by
                  #8

                  Because the sorting happens during insertion the row is wrong afterwards.

                  Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                  Visit the Qt Academy at https://academy.qt.io/catalog

                  Please_Help_me_DP 1 Reply Last reply
                  3
                  • Christian EhrlicherC Christian Ehrlicher

                    Because the sorting happens during insertion the row is wrong afterwards.

                    Please_Help_me_DP Offline
                    Please_Help_me_DP Offline
                    Please_Help_me_D
                    wrote on last edited by
                    #9

                    @Christian-Ehrlicher hi,

                    You mean the blank row is inserted and it becomes the first row in the proxy model? But in this case this first proxy row is not filled anyway in the example.

                    Can't understand the logic...

                    Christian EhrlicherC 1 Reply Last reply
                    0
                    • Please_Help_me_DP Please_Help_me_D

                      @Christian-Ehrlicher hi,

                      You mean the blank row is inserted and it becomes the first row in the proxy model? But in this case this first proxy row is not filled anyway in the example.

                      Can't understand the logic...

                      Christian EhrlicherC Offline
                      Christian EhrlicherC Offline
                      Christian Ehrlicher
                      Lifetime Qt Champion
                      wrote on last edited by
                      #10

                      When you want the correct (source) index then use QStandardItemModel::indexFromItem()

                      Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                      Visit the Qt Academy at https://academy.qt.io/catalog

                      Please_Help_me_DP 1 Reply Last reply
                      3
                      • Christian EhrlicherC Christian Ehrlicher

                        When you want the correct (source) index then use QStandardItemModel::indexFromItem()

                        Please_Help_me_DP Offline
                        Please_Help_me_DP Offline
                        Please_Help_me_D
                        wrote on last edited by Please_Help_me_D
                        #11

                        @Christian-Ehrlicher thank you, this works fine with C++ only:

                        void MainWindow::onAddBtnClicked(){
                          QStringList fileNames = QFileDialog::getOpenFileNames(
                              nullptr, QObject::tr("Select one or more files to open"), "",
                              QObject::tr("all (*)"));
                        
                          for (const auto &name : fileNames) {
                            // set item directly to the model (works fine)
                            QStandardItem *readFileItem = new QStandardItem(name);
                            readFileItem->setFlags(readFileItem->flags() & ~Qt::ItemIsEditable);
                            model->setItem(model->rowCount(), 0, readFileItem);
                        
                            QModelIndex index = model->indexFromItem(readFileItem);
                            int row = index.row();
                            int proxy_row = proxy->mapFromSource(
                                  model->index(row, 0)).row();
                        
                            // set data to the proxy (gives blank cells)
                            proxy->setData(
                                  proxy->index(proxy_row, 1),
                                  QString::number(row));
                            proxy->setData(
                                  proxy->index(proxy_row, 2),
                                  QString::number(proxy_row));
                          }
                        }
                        

                        The problem now is that approach doesn't work with PythonQt.
                        As I mentionned my application includes both C++ and python so that it is posible to run python scripts and new GUI appears with PythonQt force.

                        I tried your approach in python script and it didn't work. For example after manual column resorting I get:

                        row: 4,     proxy_row: 0
                        row: 5,     proxy_row: 0
                        row: 6,     proxy_row: 0
                        

                        And this is how it looks in Python:

                              readFileItem = QtGui.QStandardItem(name)
                              readFileItem.setFlags(readFileItem.flags() & ~Qt.Qt.ItemIsEditable)
                              self.wellModel.setItem(self.wellModel.rowCount(), self.wellTableHdrNames.index("read file"), readFileItem)
                        
                              index = self.wellModel.indexFromItem(readFileItem)
                              row = index.row()
                              proxy_row = self.wellProxy.mapFromSource(index).row();
                        
                        Christian EhrlicherC 1 Reply Last reply
                        0
                        • Please_Help_me_DP Please_Help_me_D

                          @Christian-Ehrlicher thank you, this works fine with C++ only:

                          void MainWindow::onAddBtnClicked(){
                            QStringList fileNames = QFileDialog::getOpenFileNames(
                                nullptr, QObject::tr("Select one or more files to open"), "",
                                QObject::tr("all (*)"));
                          
                            for (const auto &name : fileNames) {
                              // set item directly to the model (works fine)
                              QStandardItem *readFileItem = new QStandardItem(name);
                              readFileItem->setFlags(readFileItem->flags() & ~Qt::ItemIsEditable);
                              model->setItem(model->rowCount(), 0, readFileItem);
                          
                              QModelIndex index = model->indexFromItem(readFileItem);
                              int row = index.row();
                              int proxy_row = proxy->mapFromSource(
                                    model->index(row, 0)).row();
                          
                              // set data to the proxy (gives blank cells)
                              proxy->setData(
                                    proxy->index(proxy_row, 1),
                                    QString::number(row));
                              proxy->setData(
                                    proxy->index(proxy_row, 2),
                                    QString::number(proxy_row));
                            }
                          }
                          

                          The problem now is that approach doesn't work with PythonQt.
                          As I mentionned my application includes both C++ and python so that it is posible to run python scripts and new GUI appears with PythonQt force.

                          I tried your approach in python script and it didn't work. For example after manual column resorting I get:

                          row: 4,     proxy_row: 0
                          row: 5,     proxy_row: 0
                          row: 6,     proxy_row: 0
                          

                          And this is how it looks in Python:

                                readFileItem = QtGui.QStandardItem(name)
                                readFileItem.setFlags(readFileItem.flags() & ~Qt.Qt.ItemIsEditable)
                                self.wellModel.setItem(self.wellModel.rowCount(), self.wellTableHdrNames.index("read file"), readFileItem)
                          
                                index = self.wellModel.indexFromItem(readFileItem)
                                row = index.row()
                                proxy_row = self.wellProxy.mapFromSource(index).row();
                          
                          Christian EhrlicherC Offline
                          Christian EhrlicherC Offline
                          Christian Ehrlicher
                          Lifetime Qt Champion
                          wrote on last edited by
                          #12

                          If it works in c++ then it also works the same way in python except you don't use python correctly (which i can't justify) so you must be doing something wrong.
                          Why do you need the index at all when using a QStandardItemModel?

                          Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                          Visit the Qt Academy at https://academy.qt.io/catalog

                          Please_Help_me_DP 1 Reply Last reply
                          2
                          • Christian EhrlicherC Christian Ehrlicher

                            If it works in c++ then it also works the same way in python except you don't use python correctly (which i can't justify) so you must be doing something wrong.
                            Why do you need the index at all when using a QStandardItemModel?

                            Please_Help_me_DP Offline
                            Please_Help_me_DP Offline
                            Please_Help_me_D
                            wrote on last edited by
                            #13

                            @Christian-Ehrlicher absolutely agree it shpuld work with python too.

                            @Christian-Ehrlicher said in `QSortFilterProxyModel` incorrect mapping indexes from source model:

                            Why do you need the index at all when using a QStandardItemModel?

                            The idea is that user adds files to the table and then the information about every chosen file is filled in table with proxyModel.setData(w_proxy_row, ...):

                            self.wellProxy.setData(self.wellProxy.index(w_proxy_row, 1), well_name)
                            

                            I know I can set data directly to the source model but I'm trying to avoid that though I don't remeber exactly why and use proxy_model.

                            Christian EhrlicherC 1 Reply Last reply
                            0
                            • Please_Help_me_DP Please_Help_me_D

                              @Christian-Ehrlicher absolutely agree it shpuld work with python too.

                              @Christian-Ehrlicher said in `QSortFilterProxyModel` incorrect mapping indexes from source model:

                              Why do you need the index at all when using a QStandardItemModel?

                              The idea is that user adds files to the table and then the information about every chosen file is filled in table with proxyModel.setData(w_proxy_row, ...):

                              self.wellProxy.setData(self.wellProxy.index(w_proxy_row, 1), well_name)
                              

                              I know I can set data directly to the source model but I'm trying to avoid that though I don't remeber exactly why and use proxy_model.

                              Christian EhrlicherC Offline
                              Christian EhrlicherC Offline
                              Christian Ehrlicher
                              Lifetime Qt Champion
                              wrote on last edited by
                              #14

                              Then either use the proxy_index or - since you're using a QStandardItemModel, set it through the QStandardItemModel. Don't see a problem here.

                              Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                              Visit the Qt Academy at https://academy.qt.io/catalog

                              Please_Help_me_DP 1 Reply Last reply
                              1
                              • Christian EhrlicherC Christian Ehrlicher

                                Then either use the proxy_index or - since you're using a QStandardItemModel, set it through the QStandardItemModel. Don't see a problem here.

                                Please_Help_me_DP Offline
                                Please_Help_me_DP Offline
                                Please_Help_me_D
                                wrote on last edited by
                                #15

                                @Christian-Ehrlicher proxy_index you mean the one I get with:

                                      index = self.wellModel.indexFromItem(readFileItem)
                                      row = index.row()
                                      proxy_index = self.wellProxy.mapFromSource(index)
                                

                                ?

                                Christian EhrlicherC 1 Reply Last reply
                                0
                                • Please_Help_me_DP Please_Help_me_D

                                  @Christian-Ehrlicher proxy_index you mean the one I get with:

                                        index = self.wellModel.indexFromItem(readFileItem)
                                        row = index.row()
                                        proxy_index = self.wellProxy.mapFromSource(index)
                                  

                                  ?

                                  Christian EhrlicherC Offline
                                  Christian EhrlicherC Offline
                                  Christian Ehrlicher
                                  Lifetime Qt Champion
                                  wrote on last edited by
                                  #16

                                  Yes, that's the proxy index.

                                  Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                                  Visit the Qt Academy at https://academy.qt.io/catalog

                                  Please_Help_me_DP 1 Reply Last reply
                                  1
                                  • Christian EhrlicherC Christian Ehrlicher

                                    Yes, that's the proxy index.

                                    Please_Help_me_DP Offline
                                    Please_Help_me_DP Offline
                                    Please_Help_me_D
                                    wrote on last edited by
                                    #17

                                    @Christian-Ehrlicher alright I just decided to forbid table view sorting for the python side.

                                    It is strange that C++ side works and Python fails. But there are some chances that the reason of that is my personal additions so I will take some time to investigate it.

                                    1 Reply Last reply
                                    0

                                    • Login

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