#include #include #include #include class TestComboWithLargeModel : public QObject { Q_OBJECT private Q_SLOTS: void create(); }; enum { ExpiredRole = Qt::UserRole + 1, TrainingRole }; class FilterProxy : public QSortFilterProxyModel { public: void setIncludeExpired(bool b) { m_includeExpired = b; invalidateRowsFilter(); } void setIncludeTrainings(bool b) { m_includeTrainings = b; invalidateRowsFilter(); } int persistentIndexes() const { return persistentIndexList().count(); } protected: bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override { const auto sourceIndex = sourceModel()->index(source_row, 0, source_parent); return (m_includeExpired || !sourceIndex.data(ExpiredRole).toBool()) && (m_includeTrainings || !sourceIndex.data(TrainingRole).toBool()); } private: bool m_includeExpired = false; bool m_includeTrainings = false; }; void TestComboWithLargeModel::create() { // Show a window, just so that QWindowsUiaAccessibility::handleWmGetObject is called QWidget w; w.show(); qApp->processEvents(); w.hide(); // Base model const int rows = 1000; int nonTrainings = 0; QStandardItemModel largeModel(rows, 1); for (int row = 0; row < rows; ++row) { const auto index = largeModel.index(row, 0); largeModel.setData(index, QStringLiteral("Project %1").arg(row)); largeModel.setData(index, row < rows-40, ExpiredRole); // the last 40 are active (non-expired) const bool isTraining = (row % 10) == 0 && row < rows - 40; largeModel.setData(index, isTraining, TrainingRole); if (!isTraining) ++nonTrainings; } // Proxy FilterProxy proxy; proxy.setSourceModel(&largeModel); QBENCHMARK { QElapsedTimer dt; dt.start(); qDebug() << "Creating combo"; QComboBox combo; combo.setEditable(true); combo.setModel(&proxy); combo.setCurrentText(""); // QWindowsUiaMainProvider::notifyValueChange iterates over all cells trying to find that value, creating a persistent index for each qDebug() << "initial count" << combo.count() << "active (non-expired) projects, with" << proxy.persistentIndexes() << "persistent indexes"; QCOMPARE(combo.count(), 40); qDebug() << "Calling setIncludeExpired"; proxy.setIncludeExpired(true); // this pushes the current index down for each rowInserted call, calling QWindowsUiaMainProvider::notifyValueChange every time qDebug() << "after setIncludeExpired:" << combo.count() << "rows," << proxy.persistentIndexes() << "persistent indexes"; qDebug() << "Calling setIncludeTrainings"; QCOMPARE(combo.count(), nonTrainings); proxy.setIncludeTrainings(true); qDebug() << "after setIncludeTrainings:" << combo.count() << "rows," << proxy.persistentIndexes() << "persistent indexes"; QCOMPARE(combo.count(), rows); qDebug() << dt.elapsed() << "ms"; } } QTEST_MAIN(TestComboWithLargeModel) #include "tst_comboWithLargeModel.moc"