From 7014efe6781c53fa702df4d6ffbff359625c072c Mon Sep 17 00:00:00 2001 From: Tarja Sundqvist Date: Tue, 7 Sep 2021 17:11:26 +0300 Subject: Bump version Change-Id: Ifde151e0fa4fecc7fdb674a331d47fed2ae37ef3 --- .qmake.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.qmake.conf b/.qmake.conf index df72b25..f1a6b2b 100644 --- a/.qmake.conf +++ b/.qmake.conf @@ -4,6 +4,6 @@ CONFIG += qt_example_installs DEFINES += QT_NO_JAVA_STYLE_ITERATORS DEFINES += QT_NO_FOREACH -MODULE_VERSION = 5.15.6 +MODULE_VERSION = 5.15.7 QTRO_SOURCE_TREE = $$PWD -- cgit v1.2.3 From f14549a54bb8daeffae48108a7e76d521523f04f Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Mon, 7 Oct 2019 10:37:37 -0500 Subject: Fix crash when remoting QML objects with sub-objects There are two edge cases to watch out for. First, the property metaType's metaObject() returns a nullptr, so the property QObject pointer's metaObject needs to be used instead. If the QObject is null, the property is skipped, as there is no way to get the metaobject without introducing a dependency on QtQuick. Change-Id: I60ae36dffb30c840858e4d67b9980299c58354b4 Reviewed-by: Michael Brasser Reviewed-by: Fabian Kosmale (cherry picked from commit 28093b4ac318209f12189efda9094797226eead1) Reviewed-by: Qt Cherry-pick Bot --- src/remoteobjects/qremoteobjectsource.cpp | 33 +++++++++++++++++++++-------- tests/auto/qml/usertypes/data/MyType.qml | 5 +++++ tests/auto/qml/usertypes/data/composite.qml | 7 ++++++ tests/auto/qml/usertypes/tst_usertypes.cpp | 12 +++++++++++ 4 files changed, 48 insertions(+), 9 deletions(-) create mode 100644 tests/auto/qml/usertypes/data/MyType.qml create mode 100644 tests/auto/qml/usertypes/data/composite.qml diff --git a/src/remoteobjects/qremoteobjectsource.cpp b/src/remoteobjects/qremoteobjectsource.cpp index 1aaa9ac..381b5e4 100644 --- a/src/remoteobjects/qremoteobjectsource.cpp +++ b/src/remoteobjects/qremoteobjectsource.cpp @@ -113,7 +113,10 @@ QRemoteObjectSourceBase::QRemoteObjectSourceBase(QObject *obj, Private *d, const if (QMetaType::typeFlags(property.userType()).testFlag(QMetaType::PointerToQObject)) { auto propertyMeta = QMetaType::metaObjectForType(property.userType()); QObject *child = property.read(m_object).value(); - if (propertyMeta->inherits(&QAbstractItemModel::staticMetaObject)) { + const QMetaObject *meta = child ? child->metaObject() : propertyMeta; + if (!meta) + continue; + if (meta->inherits(&QAbstractItemModel::staticMetaObject)) { const auto modelInfo = api->m_models.at(modelIndex++); QAbstractItemModel *model = qobject_cast(child); QAbstractItemAdapterSourceAPI *modelApi = @@ -455,13 +458,20 @@ DynamicApiMap::DynamicApiMap(QObject *object, const QMetaObject *metaObject, con const int propCount = metaObject->propertyCount(); const int propOffset = metaObject->propertyOffset(); m_properties.reserve(propCount-propOffset); - int i = 0; - for (i = propOffset; i < propCount; ++i) { + QSet invalidSignals; + for (int i = propOffset; i < propCount; ++i) { const QMetaProperty property = metaObject->property(i); if (QMetaType::typeFlags(property.userType()).testFlag(QMetaType::PointerToQObject)) { auto propertyMeta = QMetaType::metaObjectForType(property.userType()); QObject *child = property.read(object).value(); - if (propertyMeta->inherits(&QAbstractItemModel::staticMetaObject)) { + const QMetaObject *meta = child ? child->metaObject() : propertyMeta; + if (!meta) { + const int notifyIndex = metaObject->property(i).notifySignalIndex(); + if (notifyIndex != -1) + invalidSignals << notifyIndex; + continue; + } + if (meta->inherits(&QAbstractItemModel::staticMetaObject)) { const QByteArray name = QByteArray::fromRawData(property.name(), qstrlen(property.name())); const QByteArray infoName = name.toUpper() + QByteArrayLiteral("_ROLES"); @@ -475,12 +485,15 @@ DynamicApiMap::DynamicApiMap(QObject *object, const QMetaObject *metaObject, con QString::fromLatin1(property.name()), roleInfo}); } else { - const QMetaObject *meta = child ? child->metaObject() : propertyMeta; QString typeName = QtRemoteObjects::getTypeNameAndMetaobjectFromClassInfo(meta); if (typeName.isNull()) { - typeName = QString::fromLatin1(propertyMeta->className()); + typeName = QString::fromLatin1(meta->className()); + if (typeName.contains(QLatin1String("QQuick"))) + typeName.remove(QLatin1String("QQuick")); + else if (int index = typeName.indexOf(QLatin1String("_QMLTYPE_"))) + typeName.truncate(index); // TODO better way to ensure we have consistent typenames between source/replicas? - if (typeName.endsWith(QLatin1String("Source"))) + else if (typeName.endsWith(QLatin1String("Source"))) typeName.chop(6); } @@ -499,11 +512,13 @@ DynamicApiMap::DynamicApiMap(QObject *object, const QMetaObject *metaObject, con } const int methodCount = metaObject->methodCount(); const int methodOffset = metaObject->methodOffset(); - for (i = methodOffset; i < methodCount; ++i) { + for (int i = methodOffset; i < methodCount; ++i) { const QMetaMethod mm = metaObject->method(i); const QMetaMethod::MethodType m = mm.methodType(); if (m == QMetaMethod::Signal) { - if (m_signals.indexOf(i) >= 0) //Already added as a property notifier + if (m_signals.indexOf(i) >= 0) // Already added as a property notifier + continue; + if (invalidSignals.contains(i)) // QObject with no metatype continue; m_signals << i; } else if (m == QMetaMethod::Slot || m == QMetaMethod::Method) diff --git a/tests/auto/qml/usertypes/data/MyType.qml b/tests/auto/qml/usertypes/data/MyType.qml new file mode 100644 index 0000000..7061c2c --- /dev/null +++ b/tests/auto/qml/usertypes/data/MyType.qml @@ -0,0 +1,5 @@ +import QtQuick 2.0 + +QtObject { + property int value: 39 +} diff --git a/tests/auto/qml/usertypes/data/composite.qml b/tests/auto/qml/usertypes/data/composite.qml new file mode 100644 index 0000000..b8defd3 --- /dev/null +++ b/tests/auto/qml/usertypes/data/composite.qml @@ -0,0 +1,7 @@ +import QtQuick 2.0 + +QtObject { + property QtObject myTypeOk: MyType {} // this works + property MyType myType: MyType {} // this crashes + property MyType myType2 // this crashes (ensure solution works with null object) +} diff --git a/tests/auto/qml/usertypes/tst_usertypes.cpp b/tests/auto/qml/usertypes/tst_usertypes.cpp index 355d545..4c25153 100644 --- a/tests/auto/qml/usertypes/tst_usertypes.cpp +++ b/tests/auto/qml/usertypes/tst_usertypes.cpp @@ -65,6 +65,7 @@ private Q_SLOTS: void watcherInQml(); void hostInQml(); void twoReplicas(); + void remoteCompositeType(); }; tst_usertypes::tst_usertypes() @@ -293,6 +294,17 @@ void tst_usertypes::twoReplicas() QTRY_COMPARE_WITH_TIMEOUT(obj->property("result2").value(), 7, 500); } +void tst_usertypes::remoteCompositeType() +{ + QQmlEngine e; + QQmlComponent c(&e, SRCDIR "data/composite.qml"); + QScopedPointer obj(c.create()); + QVERIFY(obj); + + QRemoteObjectRegistryHost host(QUrl("local:remoteCompositeType")); + host.enableRemoting(obj.data(), "composite"); +} + QTEST_MAIN(tst_usertypes) #include "tst_usertypes.moc" -- cgit v1.2.3