diff --git a/src/tools/qmlpuppet/qmlprivategate/qmlprivategate.cpp b/src/tools/qmlpuppet/qmlprivategate/qmlprivategate.cpp index b4cdba9f769..7978ba18355 100644 --- a/src/tools/qmlpuppet/qmlprivategate/qmlprivategate.cpp +++ b/src/tools/qmlpuppet/qmlprivategate/qmlprivategate.cpp @@ -347,7 +347,8 @@ void DesignerCustomObjectDataFork::populateResetHashes() if (binding) { m_resetBindingHash.insert(propertyName, binding); } else if (property.isWritable()) { - m_resetValueHash.insert(propertyName, property.read()); + if (!QmlPrivateGate::useCrashQTBUG136735Workaround(property, Q_FUNC_INFO)) + m_resetValueHash.insert(propertyName, property.read()); } } } @@ -994,6 +995,53 @@ void registerFixResourcePathsForObjectCallBack() s_qrcEngineHandler = new QrcEngineHandler(); } + +bool useCrashQTBUG136735Workaround(const QQmlProperty &property, const char *callerInfo) +{ +#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 4) + Q_UNUSED(property) + Q_UNUSED(callerInfo) + return false; // fixed in Qt +#else + if (!property.isValid()) + return false; + auto coreMetaType = property.propertyMetaType(); + + // property.propertyTypeCategory() == QQmlProperty::PropertyTypeCategory::List + // for unknown reason the simple check is sometimes not working in the editor QMLPuppet + const bool listLike = coreMetaType.id() == QMetaType::QStringList + || coreMetaType.id() == QMetaType::QVariantList + || QtPrivate::hasRegisteredConverterFunctionToIterableMetaSequence( + coreMetaType); + + if (!listLike) + return false; + + const QMetaObject *metaObject = property.object()->metaObject(); + QString ownerClassName; + + do { + bool isDirectProperty = property.property().enclosingMetaObject() == metaObject; + if (isDirectProperty) { + ownerClassName = QString::fromLatin1(metaObject->className()); + break; + } + } while ((metaObject = metaObject->superClass())); + + // is generated QML type + static const QRegularExpression + re(QStringLiteral(R"(_QML(?:TYPE)?_\d+$)"), QRegularExpression::CaseInsensitiveOption); + if (!re.match(ownerClassName).hasMatch()) + return false; + + QString debugString("skipped read() on %1::%2 (direct owned list property, QTBUG-136735)"); + qWarning().noquote() << callerInfo + << qPrintable(debugString.arg(ownerClassName, property.name())) + << QString("propertyCategory(%3)").arg(property.propertyTypeCategory()); + return true; +#endif +} + } // namespace QmlPrivateGate } // namespace Internal } // namespace QmlDesigner diff --git a/src/tools/qmlpuppet/qmlprivategate/qmlprivategate.h b/src/tools/qmlpuppet/qmlprivategate/qmlprivategate.h index fcc366ea1b1..eb18764f866 100644 --- a/src/tools/qmlpuppet/qmlprivategate/qmlprivategate.h +++ b/src/tools/qmlpuppet/qmlprivategate/qmlprivategate.h @@ -24,6 +24,8 @@ typedef QWeakPointer ObjectNodeInstanceWeakPointer; namespace QmlPrivateGate { +bool useCrashQTBUG136735Workaround(const QQmlProperty &property, const char *callerInfo); + class ComponentCompleteDisabler { public: diff --git a/src/tools/qmlpuppet/qmlpuppet/instances/objectnodeinstance.cpp b/src/tools/qmlpuppet/qmlpuppet/instances/objectnodeinstance.cpp index bf2066ae506..a454d7ddc05 100644 --- a/src/tools/qmlpuppet/qmlpuppet/instances/objectnodeinstance.cpp +++ b/src/tools/qmlpuppet/qmlpuppet/instances/objectnodeinstance.cpp @@ -613,14 +613,16 @@ static bool isPropertyBlackListed(const PropertyName &propertyName) QVariant ObjectNodeInstance::property(const PropertyName &name) const { if (ignoredProperties().contains(name)) - return QVariant(); + return {}; // TODO: handle model nodes if (isPropertyBlackListed(name)) - return QVariant(); + return {}; QQmlProperty property(object(), QString::fromUtf8(name), context()); + if (QmlPrivateGate::useCrashQTBUG136735Workaround(property, Q_FUNC_INFO)) + return {}; if (property.property().isEnumType()) { QVariant value = property.read(); QMetaEnum me = property.property().enumerator(); @@ -630,7 +632,7 @@ QVariant ObjectNodeInstance::property(const PropertyName &name) const if (property.propertyType() == QMetaType::QUrl) { QUrl url = property.read().toUrl(); if (url.isEmpty()) - return QVariant(); + return {}; if (url.scheme() == "file") { QFileInfo fi{nodeInstanceServer()->fileUrl().toLocalFile()};