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. Subclass QSortFilterProxyModel to filter multiple values on same column - Is it possible?
Forum Updated to NodeBB v4.3 + New Features

Subclass QSortFilterProxyModel to filter multiple values on same column - Is it possible?

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

    Hey,

    I would like to know if I can filter several different ID's in one column with a QSortFilterProxyModel?

    I imagined the whole thing so that I build a function that is called e.g. setIdFilters(const QList<int> ids) and filterAcceptRows filters out the corresponding ones.

    Unfortunately I didn't find anything, only that I can filter several columns at the same time or only one value from a column.

    I'm mainly interested in is this technically feasible or will it not work?

    Thanks for tipps

    JonBJ 1 Reply Last reply
    0
    • JonBJ JonB

      @Gabber
      In a word, if you override filterAcceptsRow() you can write whatever logic you want there to determine whether to return true or false, given that it passes int source_row as parameter for you to look at.

      The default implementation returns true if the value held by the relevant item matches the filter string, wildcard string or regular expression.

      So the other "filter" methods are just "defaults" you can specify if you don't want to override this method. If you do, it's up to your code what you do or look at. Your use case of "look up id column value in row in a list of wanted ids" is perfectly doable.

      Note btw that filterAcceptRow() returning true filters in the corresponding row, rather than filtering it out.

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

      @JonB
      Can you maybe help me again for a moment?

      class GermanNameFilterModel : public QSortFilterProxyModel
      {
          Q_OBJECT
      public:
          explicit GermanNameFilterModel(QObject *parent = nullptr);
          ~GermanNameFilterModel();
          void setIdFilterList(const QList<int> idFilterList);
          bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override;
      
      private:
          const int mIdColumn = 0;
          QList<int> mIdFilterList;
      };
      
      GermanNameFilterModel::GermanNameFilterModel(QObject *parent)
          : QSortFilterProxyModel{parent}{}
      
      GermanNameFilterModel::~GermanNameFilterModel(){}
      
      void GermanNameFilterModel::setIdFilterList(const QList<int> idFilterList)
      {
          if(mIdFilterList != idFilterList)
          {
              mIdFilterList = idFilterList;
              emit invalidateFilter();
          }
      }
      
      bool GermanNameFilterModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
      {
          if(mIdFilterList.size() == 1) {
              QModelIndex index = sourceModel()->index(source_row, mIdColumn, source_parent);
              int id = sourceModel()->data(index).toInt();
              if(mIdFilterList.at(0) == id)
                  return true;
              return false;
          } else {
              QModelIndex index = sourceModel()->index(source_row, mIdColumn, source_parent);
              int id = sourceModel()->data(index).toInt();
              for(int i=0; i<mIdFilterList.size(); i++){
                  if(mIdFilterList.at(i) == id)
                      return true;
              }
              return false;
          }
      }
      

      This code works as long as mIdFilterList.size() == 1. If mIdFilterList.size() is greater than 1, then my program freezes and is completely black.

      So I started the debugger and saw what happens when the list is greater than 1. After the return true it calls invalidateFilter() from the function setIdFilterList().

      Unfortunately I don't have the knowledge now. Assuming my list (mIdFilterList) contains two elements then filterAcceptsRow should return true at least twice or? According to the debugger it does that but in between it always calls invalidateFilter().

      Can you please give me some help?

      Thanks!

      JonBJ 1 Reply Last reply
      0
      • ? A Former User

        Hey,

        I would like to know if I can filter several different ID's in one column with a QSortFilterProxyModel?

        I imagined the whole thing so that I build a function that is called e.g. setIdFilters(const QList<int> ids) and filterAcceptRows filters out the corresponding ones.

        Unfortunately I didn't find anything, only that I can filter several columns at the same time or only one value from a column.

        I'm mainly interested in is this technically feasible or will it not work?

        Thanks for tipps

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

        @Gabber
        In a word, if you override filterAcceptsRow() you can write whatever logic you want there to determine whether to return true or false, given that it passes int source_row as parameter for you to look at.

        The default implementation returns true if the value held by the relevant item matches the filter string, wildcard string or regular expression.

        So the other "filter" methods are just "defaults" you can specify if you don't want to override this method. If you do, it's up to your code what you do or look at. Your use case of "look up id column value in row in a list of wanted ids" is perfectly doable.

        Note btw that filterAcceptRow() returning true filters in the corresponding row, rather than filtering it out.

        ? 2 Replies Last reply
        0
        • JonBJ JonB

          @Gabber
          In a word, if you override filterAcceptsRow() you can write whatever logic you want there to determine whether to return true or false, given that it passes int source_row as parameter for you to look at.

          The default implementation returns true if the value held by the relevant item matches the filter string, wildcard string or regular expression.

          So the other "filter" methods are just "defaults" you can specify if you don't want to override this method. If you do, it's up to your code what you do or look at. Your use case of "look up id column value in row in a list of wanted ids" is perfectly doable.

          Note btw that filterAcceptRow() returning true filters in the corresponding row, rather than filtering it out.

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

          @JonB
          Thank you for your reply. In that case I will try to implement it.

          1 Reply Last reply
          0
          • JonBJ JonB

            @Gabber
            In a word, if you override filterAcceptsRow() you can write whatever logic you want there to determine whether to return true or false, given that it passes int source_row as parameter for you to look at.

            The default implementation returns true if the value held by the relevant item matches the filter string, wildcard string or regular expression.

            So the other "filter" methods are just "defaults" you can specify if you don't want to override this method. If you do, it's up to your code what you do or look at. Your use case of "look up id column value in row in a list of wanted ids" is perfectly doable.

            Note btw that filterAcceptRow() returning true filters in the corresponding row, rather than filtering it out.

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

            @JonB
            Can you maybe help me again for a moment?

            class GermanNameFilterModel : public QSortFilterProxyModel
            {
                Q_OBJECT
            public:
                explicit GermanNameFilterModel(QObject *parent = nullptr);
                ~GermanNameFilterModel();
                void setIdFilterList(const QList<int> idFilterList);
                bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override;
            
            private:
                const int mIdColumn = 0;
                QList<int> mIdFilterList;
            };
            
            GermanNameFilterModel::GermanNameFilterModel(QObject *parent)
                : QSortFilterProxyModel{parent}{}
            
            GermanNameFilterModel::~GermanNameFilterModel(){}
            
            void GermanNameFilterModel::setIdFilterList(const QList<int> idFilterList)
            {
                if(mIdFilterList != idFilterList)
                {
                    mIdFilterList = idFilterList;
                    emit invalidateFilter();
                }
            }
            
            bool GermanNameFilterModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
            {
                if(mIdFilterList.size() == 1) {
                    QModelIndex index = sourceModel()->index(source_row, mIdColumn, source_parent);
                    int id = sourceModel()->data(index).toInt();
                    if(mIdFilterList.at(0) == id)
                        return true;
                    return false;
                } else {
                    QModelIndex index = sourceModel()->index(source_row, mIdColumn, source_parent);
                    int id = sourceModel()->data(index).toInt();
                    for(int i=0; i<mIdFilterList.size(); i++){
                        if(mIdFilterList.at(i) == id)
                            return true;
                    }
                    return false;
                }
            }
            

            This code works as long as mIdFilterList.size() == 1. If mIdFilterList.size() is greater than 1, then my program freezes and is completely black.

            So I started the debugger and saw what happens when the list is greater than 1. After the return true it calls invalidateFilter() from the function setIdFilterList().

            Unfortunately I don't have the knowledge now. Assuming my list (mIdFilterList) contains two elements then filterAcceptsRow should return true at least twice or? According to the debugger it does that but in between it always calls invalidateFilter().

            Can you please give me some help?

            Thanks!

            JonBJ 1 Reply Last reply
            0
            • ? A Former User

              @JonB
              Can you maybe help me again for a moment?

              class GermanNameFilterModel : public QSortFilterProxyModel
              {
                  Q_OBJECT
              public:
                  explicit GermanNameFilterModel(QObject *parent = nullptr);
                  ~GermanNameFilterModel();
                  void setIdFilterList(const QList<int> idFilterList);
                  bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override;
              
              private:
                  const int mIdColumn = 0;
                  QList<int> mIdFilterList;
              };
              
              GermanNameFilterModel::GermanNameFilterModel(QObject *parent)
                  : QSortFilterProxyModel{parent}{}
              
              GermanNameFilterModel::~GermanNameFilterModel(){}
              
              void GermanNameFilterModel::setIdFilterList(const QList<int> idFilterList)
              {
                  if(mIdFilterList != idFilterList)
                  {
                      mIdFilterList = idFilterList;
                      emit invalidateFilter();
                  }
              }
              
              bool GermanNameFilterModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
              {
                  if(mIdFilterList.size() == 1) {
                      QModelIndex index = sourceModel()->index(source_row, mIdColumn, source_parent);
                      int id = sourceModel()->data(index).toInt();
                      if(mIdFilterList.at(0) == id)
                          return true;
                      return false;
                  } else {
                      QModelIndex index = sourceModel()->index(source_row, mIdColumn, source_parent);
                      int id = sourceModel()->data(index).toInt();
                      for(int i=0; i<mIdFilterList.size(); i++){
                          if(mIdFilterList.at(i) == id)
                              return true;
                      }
                      return false;
                  }
              }
              

              This code works as long as mIdFilterList.size() == 1. If mIdFilterList.size() is greater than 1, then my program freezes and is completely black.

              So I started the debugger and saw what happens when the list is greater than 1. After the return true it calls invalidateFilter() from the function setIdFilterList().

              Unfortunately I don't have the knowledge now. Assuming my list (mIdFilterList) contains two elements then filterAcceptsRow should return true at least twice or? According to the debugger it does that but in between it always calls invalidateFilter().

              Can you please give me some help?

              Thanks!

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

              @Gabber said in Subclass QSortFilterProxyModel to filter multiple values on same column - Is it possible?:

              If mIdFilterList.size() is greater than 1, then my program freezes and is completely black.

              I can no reason why this should be the case, your code looks good. BTW for a QList<int> you should just be able to use:

              return mIdFilterList.contains(id);
              

              to avoid your loop in the second case, and works for first case too.

              After the return true it calls invalidateFilter() from the function setIdFilterList().

              And when is your setIdFilterList() called, because your code does not show that? The QSFPM calling filterAcceptsRow() to determine what rows to include should not have any reason to be updating any filter list? If setIdFilterList()/emit invalidateFilter(); is called during filtering I can believe that might re-start filtration evaluation, and thus lead to "freezing"?

              ? 1 Reply Last reply
              0
              • JonBJ JonB

                @Gabber said in Subclass QSortFilterProxyModel to filter multiple values on same column - Is it possible?:

                If mIdFilterList.size() is greater than 1, then my program freezes and is completely black.

                I can no reason why this should be the case, your code looks good. BTW for a QList<int> you should just be able to use:

                return mIdFilterList.contains(id);
                

                to avoid your loop in the second case, and works for first case too.

                After the return true it calls invalidateFilter() from the function setIdFilterList().

                And when is your setIdFilterList() called, because your code does not show that? The QSFPM calling filterAcceptsRow() to determine what rows to include should not have any reason to be updating any filter list? If setIdFilterList()/emit invalidateFilter(); is called during filtering I can believe that might re-start filtration evaluation, and thus lead to "freezing"?

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

                @JonB

                @JonB said in Subclass QSortFilterProxyModel to filter multiple values on same column - Is it possible?:

                return mIdFilterList.contains(id);

                Thanks, for that tip!

                @JonB said in Subclass QSortFilterProxyModel to filter multiple values on same column - Is it possible?:

                And when is your setIdFilterList() called, because your code does not show that?

                That was the mistake. I had called setIdFilterList, but then did not continue working with the QSFPM but with the source model.

                The code works fine!

                Slowly I come also already completely confused with the whole German names code Laugh.

                Thanks again for your tip!

                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