QmlPuppet: add workaround for reading list<> property crash

it skips the problematic QQmlProperty::read() calls

Change-Id: Ic28e0de2143c4543c0815eda27d3886af1524f80
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
(cherry picked from commit 9162f29e9e)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Tim Jenssen
2025-05-12 21:26:15 +02:00
committed by Thomas Hartmann
parent ed626849e8
commit 1f27d15c89
3 changed files with 56 additions and 4 deletions

View File

@@ -347,6 +347,7 @@ void DesignerCustomObjectDataFork::populateResetHashes()
if (binding) { if (binding) {
m_resetBindingHash.insert(propertyName, binding); m_resetBindingHash.insert(propertyName, binding);
} else if (property.isWritable()) { } else if (property.isWritable()) {
if (!QmlPrivateGate::useCrashQTBUG136735Workaround(property, Q_FUNC_INFO))
m_resetValueHash.insert(propertyName, property.read()); m_resetValueHash.insert(propertyName, property.read());
} }
} }
@@ -994,6 +995,53 @@ void registerFixResourcePathsForObjectCallBack()
s_qrcEngineHandler = new QrcEngineHandler(); 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<T> property, QTBUG-136735)");
qWarning().noquote() << callerInfo
<< qPrintable(debugString.arg(ownerClassName, property.name()))
<< QString("propertyCategory(%3)").arg(property.propertyTypeCategory());
return true;
#endif
}
} // namespace QmlPrivateGate } // namespace QmlPrivateGate
} // namespace Internal } // namespace Internal
} // namespace QmlDesigner } // namespace QmlDesigner

View File

@@ -24,6 +24,8 @@ typedef QWeakPointer<ObjectNodeInstance> ObjectNodeInstanceWeakPointer;
namespace QmlPrivateGate { namespace QmlPrivateGate {
bool useCrashQTBUG136735Workaround(const QQmlProperty &property, const char *callerInfo);
class ComponentCompleteDisabler class ComponentCompleteDisabler
{ {
public: public:

View File

@@ -613,14 +613,16 @@ static bool isPropertyBlackListed(const PropertyName &propertyName)
QVariant ObjectNodeInstance::property(const PropertyName &name) const QVariant ObjectNodeInstance::property(const PropertyName &name) const
{ {
if (ignoredProperties().contains(name)) if (ignoredProperties().contains(name))
return QVariant(); return {};
// TODO: handle model nodes // TODO: handle model nodes
if (isPropertyBlackListed(name)) if (isPropertyBlackListed(name))
return QVariant(); return {};
QQmlProperty property(object(), QString::fromUtf8(name), context()); QQmlProperty property(object(), QString::fromUtf8(name), context());
if (QmlPrivateGate::useCrashQTBUG136735Workaround(property, Q_FUNC_INFO))
return {};
if (property.property().isEnumType()) { if (property.property().isEnumType()) {
QVariant value = property.read(); QVariant value = property.read();
QMetaEnum me = property.property().enumerator(); QMetaEnum me = property.property().enumerator();
@@ -630,7 +632,7 @@ QVariant ObjectNodeInstance::property(const PropertyName &name) const
if (property.propertyType() == QMetaType::QUrl) { if (property.propertyType() == QMetaType::QUrl) {
QUrl url = property.read().toUrl(); QUrl url = property.read().toUrl();
if (url.isEmpty()) if (url.isEmpty())
return QVariant(); return {};
if (url.scheme() == "file") { if (url.scheme() == "file") {
QFileInfo fi{nodeInstanceServer()->fileUrl().toLocalFile()}; QFileInfo fi{nodeInstanceServer()->fileUrl().toLocalFile()};