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. What's the best way to find a ID from one QSortFilterProxyModel in another QSortFilerProxyModel?
Qt 6.11 is out! See what's new in the release blog

What's the best way to find a ID from one QSortFilterProxyModel in another QSortFilerProxyModel?

Scheduled Pinned Locked Moved Solved General and Desktop
22 Posts 5 Posters 6.2k 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.
  • ? Offline
    ? Offline
    A Former User
    wrote on last edited by
    #1

    Hey,

    I would like to know what is the best method to find an ID in a QSortFilerProxyModel? Here is a short example of what I currently have.

    My first QSortFilterProxyModel is called "mFungusProxyModel" the second QSortFilterProxyModel is called "mSynonymProxyModel". Now I select an index from the mFungusProxyModel in a QListView. Via

    const int id = mFungusProxyModel->data(index.siblingAtColumn(0)).toInt();
    

    I get the ID. Now I want to search this ID in the "mSynonymProxyModel" and get the records, so I can show it in another QListView.

    Is there a simple method/way or do I have to create a regular expression that filters this ID?

    eyllanescE 1 Reply Last reply
    0
    • Christian EhrlicherC Offline
      Christian EhrlicherC Offline
      Christian Ehrlicher
      Lifetime Qt Champion
      wrote on last edited by
      #2

      Iterate through your other model and search for the id. Don't know what a regexp should help here though.

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

      1 Reply Last reply
      1
      • ? Offline
        ? Offline
        A Former User
        wrote on last edited by A Former User
        #3

        Sorry, I forgot to mention that the mSynonymProxyModel is a 1:N relationship to the mFungusProxyModel. Thereby the possibility exists that the ID occurs several times in the mSynonymProxyModel.

        How do I proceed then? I would need something like a "where" clause like "where id = 1" if possible in my ProxyModel and not in the sourceModel.

        JonBJ 1 Reply Last reply
        0
        • ? A Former User

          Sorry, I forgot to mention that the mSynonymProxyModel is a 1:N relationship to the mFungusProxyModel. Thereby the possibility exists that the ID occurs several times in the mSynonymProxyModel.

          How do I proceed then? I would need something like a "where" clause like "where id = 1" if possible in my ProxyModel and not in the sourceModel.

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

          @Gabber
          If you just need to look up an ID/IDs you could just iterate the table, through the proxy or underlying.

          If you are wanting to filter in the proxy for one or more IDs, subclass and override bool QSortFilterProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const. Now you can do straight integer comparisons. No need for regular expression. The reg exp is just one way to define a filter in the proxy; it's optional, does nothing if left empty.

          ? 1 Reply Last reply
          1
          • ? A Former User

            Hey,

            I would like to know what is the best method to find an ID in a QSortFilerProxyModel? Here is a short example of what I currently have.

            My first QSortFilterProxyModel is called "mFungusProxyModel" the second QSortFilterProxyModel is called "mSynonymProxyModel". Now I select an index from the mFungusProxyModel in a QListView. Via

            const int id = mFungusProxyModel->data(index.siblingAtColumn(0)).toInt();
            

            I get the ID. Now I want to search this ID in the "mSynonymProxyModel" and get the records, so I can show it in another QListView.

            Is there a simple method/way or do I have to create a regular expression that filters this ID?

            eyllanescE Offline
            eyllanescE Offline
            eyllanesc
            wrote on last edited by
            #5

            @Gabber If you want to search for an item given the value of a role then a possible option is match method: https://doc.qt.io/qt-5/qabstractitemmodel.html#match

            If you want me to help you develop some work then you can write to my email: e.yllanescucho@gmal.com.

            1 Reply Last reply
            1
            • JonBJ JonB

              @Gabber
              If you just need to look up an ID/IDs you could just iterate the table, through the proxy or underlying.

              If you are wanting to filter in the proxy for one or more IDs, subclass and override bool QSortFilterProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const. Now you can do straight integer comparisons. No need for regular expression. The reg exp is just one way to define a filter in the proxy; it's optional, does nothing if left empty.

              ? Offline
              ? Offline
              A Former User
              wrote on last edited by
              #6

              @JonB
              I have no idea how to do this. Maybe you can give me some help. For example, I do not know how to get the ID of both models? Comparing the "numbers" later and returning true or false is also no problem.
              I can't do anything with "source_row" and "source_parent" either. What do I have to pass in my mainwindow when I select for example a mushroom in my ListView? Can you give me an example how to do that? The examples on the internet mostly compare "strings" via a pattern.

              Let's say I have something like this:

              bool CustomSortFilterProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
              {
                  //What to do here??
                  //How do I get the two ID's?
              }
              

              It would be nice if someone would show me and explain it.
              Thanks for your time.

              JonBJ 1 Reply Last reply
              0
              • ? A Former User

                @JonB
                I have no idea how to do this. Maybe you can give me some help. For example, I do not know how to get the ID of both models? Comparing the "numbers" later and returning true or false is also no problem.
                I can't do anything with "source_row" and "source_parent" either. What do I have to pass in my mainwindow when I select for example a mushroom in my ListView? Can you give me an example how to do that? The examples on the internet mostly compare "strings" via a pattern.

                Let's say I have something like this:

                bool CustomSortFilterProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
                {
                    //What to do here??
                    //How do I get the two ID's?
                }
                

                It would be nice if someone would show me and explain it.
                Thanks for your time.

                JonBJ Offline
                JonBJ Offline
                JonB
                wrote on last edited by JonB
                #7

                @Gabber
                You never really replied to @eyllanesc's suggestion. If all you want is to get the list of indexes in a model for a value you could use that.

                For mine we are assuming you actually want to filter a model for a particular value in a particular field. You just need to write the desired filterAcceptsRow() implementation in a subclass, and have the outside world tell it which value you want to filter on. So you will want something like the following (you can tidy it):

                class SortFilterByIdProxyModel : QSortFilterProxyModel
                {
                private:
                    const int idColumnNumber = 0;
                    int idFilterValue = -1;
                
                public:
                    void setIdFilterValue(int id)
                    {
                        if (idFilterValue != id)
                        {
                            idFilterValue = id;
                            emit invalidateFilter();
                        }
                    }
                
                    bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override
                    {
                        Q_UNUSED(source_parent);    // only tree models use parents, not flat models
                        int id = sourceModel()->index(source_row, idColumnNumber).data().toInt();    // get the ID column's value in the source model's source row
                        return (id == idFilterValue);    // row accepted iff its id is the desired idFilterValue
                    }
                }
                
                // Outside world
                sortFilterByIdProxyModel->setIdFilterValue(valueDesiredFromOtherModel);
                
                SGaistS JonBJ 2 Replies Last reply
                0
                • JonBJ JonB

                  @Gabber
                  You never really replied to @eyllanesc's suggestion. If all you want is to get the list of indexes in a model for a value you could use that.

                  For mine we are assuming you actually want to filter a model for a particular value in a particular field. You just need to write the desired filterAcceptsRow() implementation in a subclass, and have the outside world tell it which value you want to filter on. So you will want something like the following (you can tidy it):

                  class SortFilterByIdProxyModel : QSortFilterProxyModel
                  {
                  private:
                      const int idColumnNumber = 0;
                      int idFilterValue = -1;
                  
                  public:
                      void setIdFilterValue(int id)
                      {
                          if (idFilterValue != id)
                          {
                              idFilterValue = id;
                              emit invalidateFilter();
                          }
                      }
                  
                      bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override
                      {
                          Q_UNUSED(source_parent);    // only tree models use parents, not flat models
                          int id = sourceModel()->index(source_row, idColumnNumber).data().toInt();    // get the ID column's value in the source model's source row
                          return (id == idFilterValue);    // row accepted iff its id is the desired idFilterValue
                      }
                  }
                  
                  // Outside world
                  sortFilterByIdProxyModel->setIdFilterValue(valueDesiredFromOtherModel);
                  
                  SGaistS Offline
                  SGaistS Offline
                  SGaist
                  Lifetime Qt Champion
                  wrote on last edited by
                  #8

                  @JonB there's a missing call to invalidateFilter in setIdFilterValue.

                  Interested in AI ? www.idiap.ch
                  Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                  JonBJ ? 2 Replies Last reply
                  0
                  • SGaistS SGaist

                    @JonB there's a missing call to invalidateFilter in setIdFilterValue.

                    JonBJ Offline
                    JonBJ Offline
                    JonB
                    wrote on last edited by
                    #9

                    @SGaist That was supposed to be the exercise for the user :) I have put it in.

                    1 Reply Last reply
                    0
                    • SGaistS SGaist

                      @JonB there's a missing call to invalidateFilter in setIdFilterValue.

                      ? Offline
                      ? Offline
                      A Former User
                      wrote on last edited by
                      #10

                      @SGaist
                      @JonB

                      Thank you for the help and support. It works now after the "invalidateFilter" has been added.But so that I also learn something I would like to try the version of @eyllanesc. For this I used the QAbstractItemModel::match function. The code looks like this:

                      const int id = mFungusProxyModel->data(index.siblingAtColumn(0)).toInt();
                      QModelIndexList list = mSynonymProxyModel->match(QModelIndex(),Qt::DisplayRole,id);
                      
                          QStandardItemModel *myModel = new QStandardItemModel;
                          foreach(QModelIndex myIndex, list){
                              myModel->setData(myIndex, index.data());
                          }
                      
                      ui->synonymList->setModel(myModel);
                      

                      Since I haven't found anything on how to get from a QModelIndexList back to a Model and display the whole thing in my QListView, I thought I'd create a QStandardItemModel, iterate over the List and add the data to the Model. Unfortunately, I only have an empty QListView. But now I don't know if it's because of my QModelIndexList, because I use an empty QModelIndex() as start index or what the problem could be. For tips I would be very grateful again.

                      This is my first QT project so I still have a lot to ask and learn.

                      JonBJ 1 Reply Last reply
                      0
                      • ? A Former User

                        @SGaist
                        @JonB

                        Thank you for the help and support. It works now after the "invalidateFilter" has been added.But so that I also learn something I would like to try the version of @eyllanesc. For this I used the QAbstractItemModel::match function. The code looks like this:

                        const int id = mFungusProxyModel->data(index.siblingAtColumn(0)).toInt();
                        QModelIndexList list = mSynonymProxyModel->match(QModelIndex(),Qt::DisplayRole,id);
                        
                            QStandardItemModel *myModel = new QStandardItemModel;
                            foreach(QModelIndex myIndex, list){
                                myModel->setData(myIndex, index.data());
                            }
                        
                        ui->synonymList->setModel(myModel);
                        

                        Since I haven't found anything on how to get from a QModelIndexList back to a Model and display the whole thing in my QListView, I thought I'd create a QStandardItemModel, iterate over the List and add the data to the Model. Unfortunately, I only have an empty QListView. But now I don't know if it's because of my QModelIndexList, because I use an empty QModelIndex() as start index or what the problem could be. For tips I would be very grateful again.

                        This is my first QT project so I still have a lot to ask and learn.

                        JonBJ Offline
                        JonBJ Offline
                        JonB
                        wrote on last edited by JonB
                        #11

                        @Gabber said in What's the best way to find a ID from one QSortFilterProxyModel in another QSortFilerProxyModel?:

                        myModel->setData(myIndex, index.data());

                        Check setData()'s return value, it should be false. You can't do this! myIndex is an index into mSynonymProxyModel, you can't use that to index into myModel!

                        Either you have to use the result of the match() as indexes into mSynonymProxyModel, or you would have to copy the data into your new QStandardItemModel.

                        ? 1 Reply Last reply
                        0
                        • JonBJ JonB

                          @Gabber said in What's the best way to find a ID from one QSortFilterProxyModel in another QSortFilerProxyModel?:

                          myModel->setData(myIndex, index.data());

                          Check setData()'s return value, it should be false. You can't do this! myIndex is an index into mSynonymProxyModel, you can't use that to index into myModel!

                          Either you have to use the result of the match() as indexes into mSynonymProxyModel, or you would have to copy the data into your new QStandardItemModel.

                          ? Offline
                          ? Offline
                          A Former User
                          wrote on last edited by
                          #12

                          @JonB

                          Okay, I am now ready to get to my names. I'm just not sure how to tell the ProxyModel (in my case mSynonymProxyModel) to show me only the records from the QModelIndexList. Can you please explain this to me?

                          My code looks like this:

                              const int id = mFungusProxyModel->data(index.siblingAtColumn(0)).toInt();
                              QModelIndex mIndex = mSynonymProxyModel->index(0,2);
                              QModelIndexList list = mSynonymProxyModel->match(mIndex,Qt::DisplayRole,id, -1);
                          
                              foreach(QModelIndex myIndex, list){
                                  auto test = myIndex.siblingAtColumn(1).data();
                                  mSynonymProxyModel-> // What to do here, to set only the data from list
                              }
                          
                          1 Reply Last reply
                          0
                          • SGaistS Offline
                            SGaistS Offline
                            SGaist
                            Lifetime Qt Champion
                            wrote on last edited by
                            #13

                            Call setData with the index you got and whatever data you want to put there.

                            Interested in AI ? www.idiap.ch
                            Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                            1 Reply Last reply
                            0
                            • ? Offline
                              ? Offline
                              A Former User
                              wrote on last edited by
                              #14

                              @SGaist

                              I already tried that, but when I then add the mSynonymProxyModel to the QListView again, all the data from my ProxyModel is displayed and not just the one from the QModelIndexList. Do I need to do anything else? My code looks like this:

                                  foreach(QModelIndex myIndex, list){
                                      auto test = myIndex.siblingAtColumn(1).data(); //only for debuging
                                      mSynonymProxyModel->setData(myIndex, myIndex.data());
                                  }
                              
                              ui->synonymList->setModel(mSynonymProxyModel);
                              
                              1 Reply Last reply
                              0
                              • SGaistS Offline
                                SGaistS Offline
                                SGaist
                                Lifetime Qt Champion
                                wrote on last edited by
                                #15

                                Sorry, I misunderstood your intentions.

                                As @JonB already wrote, you would need to build a new model with the match result data.

                                Wasn't the proxy supposed to be the model to feed the synonym view ?

                                Interested in AI ? www.idiap.ch
                                Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                                1 Reply Last reply
                                0
                                • JonBJ JonB

                                  @Gabber
                                  You never really replied to @eyllanesc's suggestion. If all you want is to get the list of indexes in a model for a value you could use that.

                                  For mine we are assuming you actually want to filter a model for a particular value in a particular field. You just need to write the desired filterAcceptsRow() implementation in a subclass, and have the outside world tell it which value you want to filter on. So you will want something like the following (you can tidy it):

                                  class SortFilterByIdProxyModel : QSortFilterProxyModel
                                  {
                                  private:
                                      const int idColumnNumber = 0;
                                      int idFilterValue = -1;
                                  
                                  public:
                                      void setIdFilterValue(int id)
                                      {
                                          if (idFilterValue != id)
                                          {
                                              idFilterValue = id;
                                              emit invalidateFilter();
                                          }
                                      }
                                  
                                      bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override
                                      {
                                          Q_UNUSED(source_parent);    // only tree models use parents, not flat models
                                          int id = sourceModel()->index(source_row, idColumnNumber).data().toInt();    // get the ID column's value in the source model's source row
                                          return (id == idFilterValue);    // row accepted iff its id is the desired idFilterValue
                                      }
                                  }
                                  
                                  // Outside world
                                  sortFilterByIdProxyModel->setIdFilterValue(valueDesiredFromOtherModel);
                                  
                                  JonBJ Offline
                                  JonBJ Offline
                                  JonB
                                  wrote on last edited by JonB
                                  #16

                                  @JonB said in What's the best way to find a ID from one QSortFilterProxyModel in another QSortFilerProxyModel?:

                                  @Gabber
                                  You never really replied to @eyllanesc's suggestion. If all you want is to get the list of indexes in a model for a value you could use that.
                                  For mine we are assuming you actually want to filter a model for a particular value in a particular field

                                  It seems to me using match() is not what you are looking to do here. Given that you do want to filter, and you had that way working earlier, I don't think you're pursuing anything useful.

                                  1 Reply Last reply
                                  0
                                  • ? Offline
                                    ? Offline
                                    A Former User
                                    wrote on last edited by
                                    #17
                                    This post is deleted!
                                    1 Reply Last reply
                                    0
                                    • ? Offline
                                      ? Offline
                                      A Former User
                                      wrote on last edited by
                                      #18

                                      @JonB
                                      Your code works very well, thank you! I have one more question though: Is there a nicer way to filter by a specific ID or output all records? My code for this looks like this. Of course I always have to setFilterId(-1) which I don't like so much.

                                      void FungusSortFilterProxyModel::setIdFilter(const int &id)
                                      {
                                          if(mIdFilterValue != id)
                                          {
                                              mIdFilterValue = id;
                                              emit invalidateFilter();
                                          }
                                      }
                                      
                                      bool FungusSortFilterProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
                                      {
                                          if(mIdFilterValue == -1){
                                              return true;
                                          } else {
                                              Q_UNUSED(source_parent);
                                              const int id = sourceModel()->index(source_row, mIdColumNumber).data().toInt();
                                              return (id == mIdFilterValue);
                                          }
                                      }
                                      
                                      JonBJ 1 Reply Last reply
                                      0
                                      • ? A Former User

                                        @JonB
                                        Your code works very well, thank you! I have one more question though: Is there a nicer way to filter by a specific ID or output all records? My code for this looks like this. Of course I always have to setFilterId(-1) which I don't like so much.

                                        void FungusSortFilterProxyModel::setIdFilter(const int &id)
                                        {
                                            if(mIdFilterValue != id)
                                            {
                                                mIdFilterValue = id;
                                                emit invalidateFilter();
                                            }
                                        }
                                        
                                        bool FungusSortFilterProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
                                        {
                                            if(mIdFilterValue == -1){
                                                return true;
                                            } else {
                                                Q_UNUSED(source_parent);
                                                const int id = sourceModel()->index(source_row, mIdColumNumber).data().toInt();
                                                return (id == mIdFilterValue);
                                            }
                                        }
                                        
                                        JonBJ Offline
                                        JonBJ Offline
                                        JonB
                                        wrote on last edited by
                                        #19

                                        @Gabber said in What's the best way to find a ID from one QSortFilterProxyModel in another QSortFilerProxyModel?:

                                        Is there a nicer way to filter by a specific ID or output all records?
                                        Of course I always have to setFilterId(-1) which I don't like so much.

                                        I don't know what you are looking for/what is wrong with what you have/what you would rather have?! What is the objection? If there is a valid mIdFilterValue you compare it against each row, but if it is invalid you don't bother and just return true. Seems fine to me?

                                        1 Reply Last reply
                                        0
                                        • ? Offline
                                          ? Offline
                                          A Former User
                                          wrote on last edited by
                                          #20

                                          @JonB

                                          I just wanted to know if there is a programming possibility to implement filterAcceptsRow in such a way that all records are always output and only when I call setIdFilter(id), it is filtered by this ID. After that all records should be used again automatically. If this is too complex or not possible then I have to work with setIdFilter(-1).

                                          JonBJ 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