File indexing completed on 2025-03-23 09:56:02
0001 /* 0002 Copyright (C) 2019 David Edmundson <davidedmundson@kde.org> 0003 0004 This library is free software; you can redistribute it and/or modify it 0005 under the terms of the GNU Lesser General Public License as published by 0006 the Free Software Foundation; either version 2.1 of the License, or (at your 0007 option) any later version. 0008 0009 This library is distributed in the hope that it will be useful, but WITHOUT 0010 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 0011 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 0012 License for more details. 0013 0014 You should have received a copy of the GNU Library General Public License 0015 along with this library; see the file COPYING.LIB. If not, write to the 0016 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 0017 02110-1301, USA. 0018 */ 0019 0020 #include <QObject> 0021 0022 #include <QSignalSpy> 0023 #include <QTest> 0024 0025 #include <QQmlApplicationEngine> 0026 #include <QQmlContext> 0027 0028 #include <QAbstractItemModel> 0029 #include <QStandardItemModel> 0030 0031 #ifdef IMPORT_ITEMMODELSPLUGIN 0032 #include <QPluginLoader> 0033 Q_IMPORT_PLUGIN(Plugin) 0034 #endif 0035 0036 class tst_KSortFilterProxyModelQml : public QObject 0037 { 0038 Q_OBJECT 0039 private Q_SLOTS: 0040 void testFilterCallback(); 0041 void testSortRole_data(); 0042 void testSortRole(); 0043 void testFilterRegExp(); 0044 void testFilterRegExpRole(); 0045 0046 private: 0047 QAbstractItemModel *createMonthTestModel(QObject *parent); 0048 }; 0049 0050 QAbstractItemModel *tst_KSortFilterProxyModelQml::createMonthTestModel(QObject *parent) 0051 { 0052 auto testModel = new QStandardItemModel(parent); 0053 for (int i = 1; i <= 12; i++) { 0054 auto entry = new QStandardItem(); 0055 entry->setData(QLocale::c().monthName(i), Qt::DisplayRole); 0056 entry->setData(i, Qt::UserRole); 0057 testModel->appendRow(entry); 0058 } 0059 testModel->setItemRoleNames({{Qt::UserRole, "user"}, {Qt::DisplayRole, "display"}}); 0060 return testModel; 0061 } 0062 0063 void tst_KSortFilterProxyModelQml::testFilterCallback() 0064 { 0065 QQmlApplicationEngine app; 0066 app.loadData( 0067 "import QtQml 2.0\n" 0068 "import org.kde.kitemmodels 1.0\n" 0069 "KSortFilterProxyModel\n" 0070 "{\n" 0071 " property int modulo: 2\n" 0072 " sourceModel: KNumberModel {\n" 0073 " minimumValue: 1\n" 0074 " maximumValue: 10\n" 0075 " }\n" 0076 " filterRowCallback: function(source_row, source_parent) {\n" 0077 " return sourceModel.data(sourceModel.index(source_row, 0, source_parent), Qt.DisplayRole) % modulo == 1;\n" 0078 " };\n" 0079 "}\n"); 0080 QCOMPARE(app.rootObjects().count(), 1); 0081 0082 auto filterModel = qobject_cast<QAbstractItemModel *>(app.rootObjects().first()); 0083 QVERIFY(filterModel); 0084 0085 QCOMPARE(filterModel->rowCount(), 5); 0086 QCOMPARE(filterModel->data(filterModel->index(0, 0)).toString(), "1"); 0087 QCOMPARE(filterModel->data(filterModel->index(1, 0)).toString(), "3"); 0088 QCOMPARE(filterModel->data(filterModel->index(2, 0)).toString(), "5"); 0089 QCOMPARE(filterModel->data(filterModel->index(3, 0)).toString(), "7"); 0090 QCOMPARE(filterModel->data(filterModel->index(4, 0)).toString(), "9"); 0091 0092 filterModel->setProperty("modulo", 3); 0093 0094 // Nothing should change until we call invalidateFilter 0095 QCOMPARE(filterModel->rowCount(), 5); 0096 QCOMPARE(filterModel->data(filterModel->index(0, 0)).toString(), "1"); 0097 QCOMPARE(filterModel->data(filterModel->index(1, 0)).toString(), "3"); 0098 QCOMPARE(filterModel->data(filterModel->index(2, 0)).toString(), "5"); 0099 QCOMPARE(filterModel->data(filterModel->index(3, 0)).toString(), "7"); 0100 QCOMPARE(filterModel->data(filterModel->index(4, 0)).toString(), "9"); 0101 0102 // Simulate call from QML by going through metaobject rather than calling it directly 0103 const bool invalidateFilterCallOk = QMetaObject::invokeMethod(filterModel, "invalidateFilter"); 0104 QVERIFY(invalidateFilterCallOk); 0105 0106 QCOMPARE(filterModel->rowCount(), 4); 0107 QCOMPARE(filterModel->data(filterModel->index(0, 0)).toString(), "1"); 0108 QCOMPARE(filterModel->data(filterModel->index(1, 0)).toString(), "4"); 0109 QCOMPARE(filterModel->data(filterModel->index(2, 0)).toString(), "7"); 0110 QCOMPARE(filterModel->data(filterModel->index(3, 0)).toString(), "10"); 0111 } 0112 0113 void tst_KSortFilterProxyModelQml::testSortRole_data() 0114 { 0115 // test model consists of all month names + month number as Display and UserRoler respectively 0116 0117 QTest::addColumn<QString>("qmlContents"); 0118 QTest::addColumn<QString>("result"); 0119 0120 QTest::newRow("sort by role name - display") << "KSortFilterProxyModel {" 0121 " sourceModel: testModel;" 0122 " sortRole: \"display\";" 0123 "}" 0124 << "April"; 0125 QTest::newRow("sort by role name - value") << "KSortFilterProxyModel {" 0126 " sourceModel: testModel;" 0127 " sortRole: \"user\";" 0128 "}" 0129 << "January"; 0130 QTest::newRow("sort by role name - reset") << "KSortFilterProxyModel {" 0131 " sourceModel: testModel;" 0132 " sortRole: \"\";" 0133 " Component.onCompleted: sortRole = \"\";" 0134 "}" 0135 << "January"; 0136 } 0137 0138 void tst_KSortFilterProxyModelQml::testSortRole() 0139 { 0140 QQmlApplicationEngine app; 0141 QFETCH(QString, qmlContents); 0142 QFETCH(QString, result); 0143 0144 qmlContents = 0145 "import org.kde.kitemmodels 1.0\n" 0146 "import QtQuick 2.0\n" 0147 + qmlContents; 0148 0149 app.rootContext()->setContextProperty("testModel", createMonthTestModel(&app)); 0150 0151 app.loadData(qmlContents.toLatin1()); 0152 0153 QCOMPARE(app.rootObjects().count(), 1); 0154 auto filterModel = qobject_cast<QAbstractItemModel *>(app.rootObjects().first()); 0155 QVERIFY(filterModel); 0156 QCOMPARE(filterModel->rowCount(), 12); 0157 QCOMPARE(filterModel->data(filterModel->index(0, 0), Qt::DisplayRole).toString(), result); 0158 } 0159 0160 void tst_KSortFilterProxyModelQml::testFilterRegExp() 0161 { 0162 // filterRegExp comes from the QSortFilterProxyModel directly, confirm it still works 0163 QQmlApplicationEngine app; 0164 0165 app.rootContext()->setContextProperty("testModel", createMonthTestModel(&app)); 0166 0167 auto qmlSrc = QByteArray( 0168 "import QtQml 2.0\n" 0169 "import org.kde.kitemmodels 1.0\n" 0170 "KSortFilterProxyModel {\n" 0171 " sourceModel: testModel\n" 0172 " filterRegularExpression: /Ma.*/\n" 0173 "}\n"); 0174 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) 0175 qmlSrc.replace("filterRegularExpression", "filterRegExp"); 0176 #endif 0177 app.loadData(qmlSrc); 0178 0179 QCOMPARE(app.rootObjects().count(), 1); 0180 auto filterModel = qobject_cast<QAbstractItemModel *>(app.rootObjects().first()); 0181 QVERIFY(filterModel); 0182 QCOMPARE(filterModel->rowCount(), 2); 0183 QCOMPARE(filterModel->data(filterModel->index(0, 0), Qt::DisplayRole).toString(), "March"); 0184 QCOMPARE(filterModel->data(filterModel->index(1, 0), Qt::DisplayRole).toString(), "May"); 0185 } 0186 0187 void tst_KSortFilterProxyModelQml::testFilterRegExpRole() 0188 { 0189 // filterRegExp comes from the QSortFilterProxyModel directly, confirm it still works 0190 QQmlApplicationEngine app; 0191 0192 app.rootContext()->setContextProperty("testModel", createMonthTestModel(&app)); 0193 0194 auto qmlSrc = QByteArray( 0195 "import QtQml 2.0\n" 0196 "import org.kde.kitemmodels 1.0\n" 0197 "KSortFilterProxyModel {\n" 0198 " sourceModel: testModel\n" 0199 " filterRole: \"user\"\n" 0200 " filterRegularExpression: /1[0-9]/\n" // month value is 10 or more 0201 "}\n"); 0202 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) 0203 qmlSrc.replace("filterRegularExpression", "filterRegExp"); 0204 #endif 0205 app.loadData(qmlSrc); 0206 0207 QCOMPARE(app.rootObjects().count(), 1); 0208 auto filterModel = qobject_cast<QAbstractItemModel *>(app.rootObjects().first()); 0209 QVERIFY(filterModel); 0210 QCOMPARE(filterModel->rowCount(), 3); 0211 QCOMPARE(filterModel->data(filterModel->index(0, 0), Qt::DisplayRole).toString(), "October"); 0212 QCOMPARE(filterModel->data(filterModel->index(1, 0), Qt::DisplayRole).toString(), "November"); 0213 QCOMPARE(filterModel->data(filterModel->index(2, 0), Qt::DisplayRole).toString(), "December"); 0214 } 0215 0216 QTEST_GUILESS_MAIN(tst_KSortFilterProxyModelQml) 0217 0218 #include "ksortfilterproxymodel_qml.moc"