Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-115717

QSortFilterProxyModel::invalidateFilter() sometimes does not trigger a reevaluation of the model

    XMLWordPrintable

Details

    Description

      If invalidate() is called earlier, then invalidateFilter() might not trigger reevaluation.

      In the code below, the standard QSortFilterProxyModel behaves correctly and emits the signal, but a custom proxy model does not.

      Code

      #include <QCoreApplication>
      #include <QSortFilterProxyModel>
      #include <QStringListModel>
      #include <QTimer>
      #include <QDebug>
      
      class CustomProxyModel : public QSortFilterProxyModel
      {
          Q_OBJECT
      
      public:
          CustomProxyModel(QObject* parent = nullptr) : QSortFilterProxyModel(parent) {}
      
          void setFilter(const QString& s)
          {
              if (m_matchString == s)
                  return;
      
              //rowCount(); // Workaround: Calling rowCount() here makes things work
              m_matchString = s;
              invalidateFilter();
          }
      
          bool filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const override
          {
              const auto index = sourceModel()->index(sourceRow, 0, sourceParent);
              if (!index.isValid())
                  return false;
      
              bool accepted = index.data().value<QString>() == m_matchString;
              qDebug() << '\t' << index.data() << "Accepted?" << accepted;
              return accepted;
          }
      
      private:
          QString m_matchString;
      };
      
      int main(int argc, char* argv[])
      {
          QCoreApplication app(argc, argv);
          QStringListModel model({"1", "2", "3", "4", "5"});
      
          // ==============================================
      
          qDebug() << "=== Testing CustomProxyModel ===";
          qDebug() << "Initializing...";
          CustomProxyModel proxyModel;
          proxyModel.setFilter("X"); // Reject all source data at the start
          proxyModel.sort(0, Qt::AscendingOrder); // Trigger an evaluation
          proxyModel.setSourceModel(&model);
      
          qDebug() << "Invalidating...";
          proxyModel.invalidate();
      
          qDebug() << "Connnecting signal...";
          QObject::connect(&proxyModel, &QSortFilterProxyModel::rowsInserted, &app, [&] {
              qDebug() << "SIGNAL EMITTED! CustomProxyModel's new rowCount():" << proxyModel.rowCount();
          });
      
          qDebug() << "Changing filter...";
          proxyModel.setFilter("3");
          // We expect to see a signal emitted here to learn that the proxy model now has 1 row
      
          // ==============================================
          qDebug() << "";
      
          qDebug() << "=== Testing QSortFilterProxyModel ===";
          qDebug() << "Initializing...";
          QSortFilterProxyModel qsfpm;
          qsfpm.setFilterRegularExpression("X"); // Reject all source data at the start
          qsfpm.setSourceModel(&model);
      
          qDebug() << "Invalidating...";
          qsfpm.invalidate();
      
          qDebug() << "Connnecting signal...";
          QObject::connect(&qsfpm, &QSortFilterProxyModel::rowsInserted, &app, [&] {
              qDebug() << "SIGNAL EMITTED! QSortFilterProxyModel's new rowCount():" << qsfpm.rowCount();
          });
      
          qDebug() << "Changing filter...";
          qsfpm.setFilterRegularExpression("3");
      
          // ==============================================
      }
      
      #include "main.moc"
      

      Output

      === Testing CustomProxyModel ===
      Initializing...
           QVariant(QString, "1") Accepted? false
           QVariant(QString, "2") Accepted? false
           QVariant(QString, "3") Accepted? false
           QVariant(QString, "4") Accepted? false
           QVariant(QString, "5") Accepted? false
      Invalidating...
      Connnecting signal...
      Changing filter...
      
      === Testing QSortFilterProxyModel ===
      Initializing...
      Invalidating...
      Connnecting signal...
      Changing filter...
      SIGNAL EMITTED! QSortFilterProxyModel's new rowCount(): 1
      

      Attachments

        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

        Activity

          People

            dfaure_kdab David Faure
            nigel.lu Nigel Lu (Inactive)
            Votes:
            8 Vote for this issue
            Watchers:
            9 Start watching this issue

            Dates

              Created:
              Updated:

              Gerrit Reviews

                There are no open Gerrit changes