// Copyright (C) 2021 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #ifndef BINDABLEQMLUTILS_H #define BINDABLEQMLUTILS_H #include #include #include #include // This is a helper function to test basics of typical bindable // and manipulable QQmlListProperty // "TestedClass" is the class type we are testing // "TestedData" is the data type that the list contains // "testedClass" is an instance of the class we are interested testing // "data1" is a value that can be set and removed from the list // "data2" is a value that can be set and removed from the list // "propertyName" is the name of the property we are interested in testing template void testManipulableQmlListBasics(TestedClass& testedClass, TestedData data1, TestedData data2, const char* propertyName) { // Get the property we are testing const QMetaObject *metaObject = testedClass.metaObject(); QMetaProperty metaProperty = metaObject->property(metaObject->indexOfProperty(propertyName)); // Generate a string to help identify failures (as this is a generic template) QString id(metaObject->className()); id.append(QStringLiteral("::")); id.append(propertyName); // Fail gracefully if preconditions to use this helper function are not met: QQmlListReference listRef(&testedClass, propertyName); QVERIFY2(metaProperty.isBindable(), qPrintable(id)); QVERIFY2(listRef.isManipulable(), qPrintable(id)); QVERIFY2(data1 != data2, qPrintable(id)); // Create a signal spy for the property changed -signal if such exists QScopedPointer changedSpy(nullptr); if (metaProperty.hasNotifySignal()) changedSpy.reset(new QSignalSpy(&testedClass, metaProperty.notifySignal())); // Modify values without binding (verify property basics still work) QVERIFY2(listRef.count() == 0, qPrintable(id)); listRef.append(data1); QVERIFY2(listRef.count() == 1, qPrintable(id)); if (changedSpy) QVERIFY2(changedSpy->size() == 1, qPrintable(id + ", actual: " + QString::number(changedSpy->size()))); QVERIFY2(listRef.at(0) == data1, qPrintable(id)); listRef.clear(); QVERIFY2(listRef.count() == 0, qPrintable(id)); if (changedSpy) QVERIFY2(changedSpy->size() == 2, qPrintable(id + ", actual: " + QString::number(changedSpy->size()))); // Bind to the property and verify that the bindings reflect the listproperty changes QProperty data1InList([&](){ QQmlListReference list(&testedClass, propertyName); for (int i = 0; i < list.count(); i++) { if (list.at(i) == data1) return true; } return false; }); QProperty data2InList([&](){ QQmlListReference list(&testedClass, propertyName); for (int i = 0; i < list.count(); i++) { if (list.at(i) == data2) return true; } return false; }); // initial state QVERIFY2(!data1InList, qPrintable(id)); QVERIFY2(!data2InList, qPrintable(id)); listRef.append(data1); if (changedSpy) QVERIFY2(changedSpy->size() == 3, qPrintable(id + ", actual: " + QString::number(changedSpy->size()))); QVERIFY2(data1InList, qPrintable(id)); QVERIFY2(!data2InList, qPrintable(id)); listRef.append(data2); if (changedSpy) QVERIFY2(changedSpy->size() == 4, qPrintable(id + ", actual: " + QString::number(changedSpy->size()))); QVERIFY2(data1InList, qPrintable(id)); QVERIFY2(data2InList, qPrintable(id)); QVERIFY2(listRef.count() == 2, qPrintable(id + ", actual: " + QString::number(changedSpy->size()))); listRef.clear(); if (changedSpy) QVERIFY2(changedSpy->size() == 5, qPrintable(id + ", actual: " + QString::number(changedSpy->size()))); QVERIFY2(!data1InList, qPrintable(id)); QVERIFY2(!data2InList, qPrintable(id)); QVERIFY2(listRef.count() == 0, qPrintable(id + ", actual: " + QString::number(changedSpy->size()))); listRef.append(data1); listRef.replace(0, data2); if (changedSpy) QVERIFY2(changedSpy->size() == 7, qPrintable(id + ", actual: " + QString::number(changedSpy->size()))); QVERIFY2(!data1InList, qPrintable(id)); QVERIFY2(data2InList, qPrintable(id)); QVERIFY2(listRef.count() == 1, qPrintable(id + ", actual: " + QString::number(changedSpy->size()))); listRef.removeLast(); if (changedSpy) QVERIFY2(changedSpy->size() == 8, qPrintable(id + ", actual: " + QString::number(changedSpy->size()))); QVERIFY2(!data1InList, qPrintable(id)); QVERIFY2(!data2InList, qPrintable(id)); QVERIFY2(listRef.count() == 0, qPrintable(id + ", actual: " + QString::number(listRef.count()))); } #endif // BINDABLEQMLUTILS_H