diff options
author | Qt Forward Merge Bot <qt_forward_merge_bot@qt-project.org> | 2019-10-10 01:00:21 +0200 |
---|---|---|
committer | Qt Forward Merge Bot <qt_forward_merge_bot@qt-project.org> | 2019-10-10 01:00:21 +0200 |
commit | 1bddf29287b4c42c321688376147d14bfecb46a1 (patch) | |
tree | 2939d848a3a5496963aa2749b9deead6df9c49f4 /src | |
parent | a02b5d48cf63228ed8faf6abf4724df2c4500269 (diff) | |
parent | 3fde977a817498817e98ce350d493658b0ed4458 (diff) |
Merge remote-tracking branch 'origin/5.14' into 5.15
Change-Id: I2835748c27616103f275849141fbe5a93e3dfd8c
Diffstat (limited to 'src')
21 files changed, 360 insertions, 196 deletions
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp b/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp index be83f63bfc..029004ffd1 100644 --- a/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp +++ b/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp @@ -490,7 +490,7 @@ void QQmlEngineDebugServiceImpl::processMessage(const QByteArray &message) QQmlDebugPacket ds(message); QByteArray type; - int queryId; + qint32 queryId; ds >> type >> queryId; QQmlDebugPacket rs; @@ -503,13 +503,13 @@ void QQmlEngineDebugServiceImpl::processMessage(const QByteArray &message) QJSEngine *engine = m_engines.at(ii); QString engineName = engine->objectName(); - int engineId = QQmlDebugService::idForObject(engine); + qint32 engineId = QQmlDebugService::idForObject(engine); rs << engineName << engineId; } } else if (type == "LIST_OBJECTS") { - int engineId = -1; + qint32 engineId = -1; ds >> engineId; QQmlEngine *engine = @@ -532,7 +532,7 @@ void QQmlEngineDebugServiceImpl::processMessage(const QByteArray &message) } } else if (type == "FETCH_OBJECT") { - int objectId; + qint32 objectId; bool recurse; bool dumpProperties = true; @@ -550,8 +550,8 @@ void QQmlEngineDebugServiceImpl::processMessage(const QByteArray &message) } else if (type == "FETCH_OBJECTS_FOR_LOCATION") { QString file; - int lineNumber; - int columnNumber; + qint32 lineNumber; + qint32 columnNumber; bool recurse; bool dumpProperties = true; @@ -569,7 +569,7 @@ void QQmlEngineDebugServiceImpl::processMessage(const QByteArray &message) } } else if (type == "WATCH_OBJECT") { - int objectId; + qint32 objectId; ds >> objectId; bool ok = m_watch->addWatch(queryId, objectId); @@ -577,7 +577,7 @@ void QQmlEngineDebugServiceImpl::processMessage(const QByteArray &message) rs << QByteArray("WATCH_OBJECT_R") << queryId << ok; } else if (type == "WATCH_PROPERTY") { - int objectId; + qint32 objectId; QByteArray property; ds >> objectId >> property; @@ -586,7 +586,7 @@ void QQmlEngineDebugServiceImpl::processMessage(const QByteArray &message) rs << QByteArray("WATCH_PROPERTY_R") << queryId << ok; } else if (type == "WATCH_EXPR_OBJECT") { - int debugId; + qint32 debugId; QString expr; ds >> debugId >> expr; @@ -600,11 +600,11 @@ void QQmlEngineDebugServiceImpl::processMessage(const QByteArray &message) rs << QByteArray("NO_WATCH_R") << queryId << ok; } else if (type == "EVAL_EXPRESSION") { - int objectId; + qint32 objectId; QString expr; ds >> objectId >> expr; - int engineId = -1; + qint32 engineId = -1; if (!ds.atEnd()) ds >> engineId; @@ -632,12 +632,12 @@ void QQmlEngineDebugServiceImpl::processMessage(const QByteArray &message) rs << QByteArray("EVAL_EXPRESSION_R") << queryId << result; } else if (type == "SET_BINDING") { - int objectId; + qint32 objectId; QString propertyName; QVariant expr; bool isLiteralValue; QString filename; - int line; + qint32 line; ds >> objectId >> propertyName >> expr >> isLiteralValue >> filename >> line; bool ok = setBinding(objectId, propertyName, expr, isLiteralValue, @@ -646,7 +646,7 @@ void QQmlEngineDebugServiceImpl::processMessage(const QByteArray &message) rs << QByteArray("SET_BINDING_R") << queryId << ok; } else if (type == "RESET_BINDING") { - int objectId; + qint32 objectId; QString propertyName; ds >> objectId >> propertyName; bool ok = resetBinding(objectId, propertyName); @@ -654,7 +654,7 @@ void QQmlEngineDebugServiceImpl::processMessage(const QByteArray &message) rs << QByteArray("RESET_BINDING_R") << queryId << ok; } else if (type == "SET_METHOD_BODY") { - int objectId; + qint32 objectId; QString methodName; QString methodBody; ds >> objectId >> methodName >> methodBody; @@ -817,7 +817,8 @@ bool QQmlEngineDebugServiceImpl::setMethodBody(int objectId, const QString &meth return true; } -void QQmlEngineDebugServiceImpl::propertyChanged(int id, int objectId, const QMetaProperty &property, const QVariant &value) +void QQmlEngineDebugServiceImpl::propertyChanged( + qint32 id, qint32 objectId, const QMetaProperty &property, const QVariant &value) { QQmlDebugPacket rs; rs << QByteArray("UPDATE_WATCH") << id << objectId << QByteArray(property.name()) << valueContents(value); @@ -848,14 +849,14 @@ void QQmlEngineDebugServiceImpl::objectCreated(QJSEngine *engine, QObject *objec if (!m_engines.contains(engine)) return; - int engineId = QQmlDebugService::idForObject(engine); - int objectId = QQmlDebugService::idForObject(object); - int parentId = QQmlDebugService::idForObject(object->parent()); + qint32 engineId = QQmlDebugService::idForObject(engine); + qint32 objectId = QQmlDebugService::idForObject(object); + qint32 parentId = QQmlDebugService::idForObject(object->parent()); QQmlDebugPacket rs; //unique queryId -1 - rs << QByteArray("OBJECT_CREATED") << -1 << engineId << objectId << parentId; + rs << QByteArray("OBJECT_CREATED") << qint32(-1) << engineId << objectId << parentId; emit messageToClient(name(), rs.data()); } diff --git a/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.h b/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.h index c0c24058eb..741768cd00 100644 --- a/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.h +++ b/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.h @@ -111,7 +111,8 @@ private: friend class QQmlDebuggerServiceFactory; void processMessage(const QByteArray &msg); - void propertyChanged(int id, int objectId, const QMetaProperty &property, const QVariant &value); + void propertyChanged(qint32 id, qint32 objectId, const QMetaProperty &property, + const QVariant &value); void prepareDeferredObjects(QObject *); void buildObjectList(QDataStream &, QQmlContext *, diff --git a/src/qml/qml/qqmltype.cpp b/src/qml/qml/qqmltype.cpp index 2db3ad6b2a..874bcd4bca 100644 --- a/src/qml/qml/qqmltype.cpp +++ b/src/qml/qml/qqmltype.cpp @@ -91,6 +91,8 @@ QQmlTypePrivate::QQmlTypePrivate(QQmlType::RegistrationType type) QQmlTypePrivate::~QQmlTypePrivate() { qDeleteAll(scopedEnums); + for (const auto &metaObject : metaObjects) + free(metaObject.metaObject); switch (regType) { case QQmlType::CppType: delete extraData.cd->customParser; diff --git a/src/qml/types/qqmlbind.cpp b/src/qml/types/qqmlbind.cpp index 36de16a818..921d60caa1 100644 --- a/src/qml/types/qqmlbind.cpp +++ b/src/qml/types/qqmlbind.cpp @@ -54,11 +54,14 @@ #include <QtCore/qfile.h> #include <QtCore/qdebug.h> #include <QtCore/qtimer.h> +#include <QtCore/qloggingcategory.h> #include <private/qobject_p.h> QT_BEGIN_NAMESPACE +Q_DECLARE_LOGGING_CATEGORY(lcBindingRemoval) + class QQmlBindPrivate : public QObjectPrivate { public: @@ -72,6 +75,7 @@ public: , restoreBinding(true) , restoreValue(false) , restoreModeExplicit(false) + , writingProperty(false) {} ~QQmlBindPrivate() { } @@ -90,6 +94,7 @@ public: bool restoreBinding:1; bool restoreValue:1; bool restoreModeExplicit:1; + bool writingProperty: 1; void validate(QObject *binding) const; void clearPrev(); @@ -193,6 +198,13 @@ QQmlBind::~QQmlBind() When the binding becomes inactive again, any direct bindings that were previously set on the property will be restored. + + \note By default, a previously set literal value is not restored when the Binding becomes + inactive. Rather, the last value set by the now inactive Binding is retained. You can customize + the restoration behavior for literal values as well as bindings using the \l restoreMode + property. The default will change in Qt 6.0. + + \sa restoreMode */ bool QQmlBind::when() const { @@ -235,7 +247,7 @@ void QQmlBind::setObject(QObject *obj) } d->obj = obj; if (d->componentComplete) { - d->prop = QQmlProperty(d->obj, d->propName, qmlContext(this)); + setTarget(QQmlProperty(d->obj, d->propName, qmlContext(this))); d->validate(this); } eval(); @@ -281,7 +293,7 @@ void QQmlBind::setProperty(const QString &p) } d->propName = p; if (d->componentComplete) { - d->prop = QQmlProperty(d->obj, d->propName, qmlContext(this)); + setTarget(QQmlProperty(d->obj, d->propName, qmlContext(this))); d->validate(this); } eval(); @@ -360,7 +372,7 @@ void QQmlBind::setDelayed(bool delayed) \endlist \warning The default value is Binding.RestoreBinding. This will change in - Qt 5.15 to Binding.RestoreBindingOrValue. + Qt 6.0 to Binding.RestoreBindingOrValue. If you rely on any specific behavior regarding the restoration of plain values when bindings get disabled you should migrate to explicitly set the @@ -394,6 +406,19 @@ void QQmlBind::setRestoreMode(RestorationMode newMode) void QQmlBind::setTarget(const QQmlProperty &p) { Q_D(QQmlBind); + + if (Q_UNLIKELY(lcBindingRemoval().isInfoEnabled())) { + if (QObject *oldObject = d->prop.object()) { + QMetaProperty prop = oldObject->metaObject()->property(d->prop.index()); + if (prop.hasNotifySignal()) { + QByteArray signal('2' + prop.notifySignal().methodSignature()); + QObject::disconnect(oldObject, signal.constData(), + this, SLOT(targetValueChanged())); + } + } + p.connectNotifySignal(this, SLOT(targetValueChanged())); + } + d->prop = p; } @@ -408,7 +433,7 @@ void QQmlBind::componentComplete() Q_D(QQmlBind); d->componentComplete = true; if (!d->prop.isValid()) { - d->prop = QQmlProperty(d->obj, d->propName, qmlContext(this)); + setTarget(QQmlProperty(d->obj, d->propName, qmlContext(this))); d->validate(this); } eval(); @@ -461,8 +486,8 @@ void QQmlBind::eval() qmlWarning(this) << "Not restoring previous value because restoreMode has not been set." << "This behavior is deprecated." - << "In Qt < 5.15 the default is Binding.RestoreBinding." - << "In Qt >= 5.15 the default is Binding.RestoreBindingOrValue."; + << "In Qt < 6.0 the default is Binding.RestoreBinding." + << "In Qt >= 6.0 the default is Binding.RestoreBindingOrValue."; } } else if (d->prevIsVariant) { if (d->restoreValue) { @@ -472,8 +497,8 @@ void QQmlBind::eval() qmlWarning(this) << "Not restoring previous value because restoreMode has not been set." << "This behavior is deprecated." - << "In Qt < 5.15 the default is Binding.RestoreBinding." - << "In Qt >= 5.15 the default is Binding.RestoreBindingOrValue."; + << "In Qt < 6.0 the default is Binding.RestoreBinding." + << "In Qt >= 6.0 the default is Binding.RestoreBindingOrValue."; } } return; @@ -502,7 +527,34 @@ void QQmlBind::eval() QQmlPropertyPrivate::removeBinding(d->prop); } + d->writingProperty = true; d->prop.write(d->value.value.toVariant()); + d->writingProperty = false; +} + +void QQmlBind::targetValueChanged() +{ + Q_D(QQmlBind); + if (d->writingProperty) + return; + + if (d->when.isValid() && !d->when) + return; + + QUrl url; + quint16 line = 0; + + const QQmlData *ddata = QQmlData::get(this, false); + if (ddata && ddata->outerContext) { + url = ddata->outerContext->url(); + line = ddata->lineNumber; + } + + qCInfo(lcBindingRemoval, + "The target property of the Binding element created at %s:%d was changed from " + "elsewhere. This does not overwrite the binding. The target property will still be " + "updated when the value of the Binding element changes.", + qPrintable(url.toString()), line); } QT_END_NAMESPACE diff --git a/src/qml/types/qqmlbind_p.h b/src/qml/types/qqmlbind_p.h index a100b1552c..c709224c23 100644 --- a/src/qml/types/qqmlbind_p.h +++ b/src/qml/types/qqmlbind_p.h @@ -116,6 +116,9 @@ protected: private: void prepareEval(); void eval(); + +private Q_SLOTS: + void targetValueChanged(); }; QT_END_NAMESPACE diff --git a/src/qmldebug/qqmlenginedebugclient.cpp b/src/qmldebug/qqmlenginedebugclient.cpp index 50f8deb087..0ca3f573d9 100644 --- a/src/qmldebug/qqmlenginedebugclient.cpp +++ b/src/qmldebug/qqmlenginedebugclient.cpp @@ -33,14 +33,14 @@ QT_BEGIN_NAMESPACE struct QQmlObjectData { QUrl url; - int lineNumber = -1; - int columnNumber = -1; + qint32 lineNumber = -1; + qint32 columnNumber = -1; QString idString; QString objectName; QString objectType; - int objectId = -1; - int contextId = -1; - int parentId = -1; + qint32 objectId = -1; + qint32 contextId = -1; + qint32 parentId = -1; }; QPacket &operator>>(QPacket &ds, QQmlObjectData &data) @@ -63,10 +63,10 @@ struct QQmlObjectProperty { QPacket &operator>>(QPacket &ds, QQmlObjectProperty &data) { - int type; + qint32 type; ds >> type >> data.name >> data.value >> data.valueTypeName >> data.binding >> data.hasNotifySignal; - data.type = (QQmlObjectProperty::Type)type; + data.type = QQmlObjectProperty::Type(type); return ds; } @@ -81,10 +81,10 @@ QQmlEngineDebugClientPrivate::QQmlEngineDebugClientPrivate(QQmlDebugConnection * } -quint32 QQmlEngineDebugClient::addWatch( +qint32 QQmlEngineDebugClient::addWatch( const QQmlEngineDebugPropertyReference &property, bool *success) { - quint32 id = -1; + qint32 id = -1; *success = false; if (state() == QQmlDebugClient::Enabled) { id = getId(); @@ -97,19 +97,19 @@ quint32 QQmlEngineDebugClient::addWatch( return id; } -quint32 QQmlEngineDebugClient::addWatch( +qint32 QQmlEngineDebugClient::addWatch( const QQmlEngineDebugContextReference &, const QString &, bool *success) { *success = false; qWarning("QQmlEngineDebugClient::addWatch(): Not implemented"); - return 0; + return -1; } -quint32 QQmlEngineDebugClient::addWatch( +qint32 QQmlEngineDebugClient::addWatch( const QQmlEngineDebugObjectReference &object, const QString &expr, bool *success) { - quint32 id = -1; + qint32 id = -1; *success = false; if (state() == QQmlDebugClient::Enabled) { id = getId(); @@ -121,10 +121,10 @@ quint32 QQmlEngineDebugClient::addWatch( return id; } -quint32 QQmlEngineDebugClient::addWatch( +qint32 QQmlEngineDebugClient::addWatch( const QQmlEngineDebugObjectReference &object, bool *success) { - quint32 id = -1; + qint32 id = -1; *success = false; if (state() == QQmlDebugClient::Enabled) { id = getId(); @@ -136,15 +136,15 @@ quint32 QQmlEngineDebugClient::addWatch( return id; } -quint32 QQmlEngineDebugClient::addWatch( +qint32 QQmlEngineDebugClient::addWatch( const QQmlEngineDebugFileReference &, bool *success) { *success = false; qWarning("QQmlEngineDebugClient::addWatch(): Not implemented"); - return 0; + return -1; } -void QQmlEngineDebugClient::removeWatch(quint32 id, bool *success) +void QQmlEngineDebugClient::removeWatch(qint32 id, bool *success) { *success = false; if (state() == QQmlDebugClient::Enabled) { @@ -155,11 +155,11 @@ void QQmlEngineDebugClient::removeWatch(quint32 id, bool *success) } } -quint32 QQmlEngineDebugClient::queryAvailableEngines(bool *success) +qint32 QQmlEngineDebugClient::queryAvailableEngines(bool *success) { Q_D(QQmlEngineDebugClient); d->engines.clear(); - quint32 id = -1; + qint32 id = -1; *success = false; if (state() == QQmlDebugClient::Enabled) { id = getId(); @@ -171,12 +171,12 @@ quint32 QQmlEngineDebugClient::queryAvailableEngines(bool *success) return id; } -quint32 QQmlEngineDebugClient::queryRootContexts( +qint32 QQmlEngineDebugClient::queryRootContexts( const QQmlEngineDebugEngineReference &engine, bool *success) { Q_D(QQmlEngineDebugClient); d->rootContext = QQmlEngineDebugContextReference(); - quint32 id = -1; + qint32 id = -1; *success = false; if (state() == QQmlDebugClient::Enabled && engine.debugId != -1) { id = getId(); @@ -188,12 +188,12 @@ quint32 QQmlEngineDebugClient::queryRootContexts( return id; } -quint32 QQmlEngineDebugClient::queryObject( +qint32 QQmlEngineDebugClient::queryObject( const QQmlEngineDebugObjectReference &object, bool *success) { Q_D(QQmlEngineDebugClient); d->object = QQmlEngineDebugObjectReference(); - quint32 id = -1; + qint32 id = -1; *success = false; if (state() == QQmlDebugClient::Enabled && object.debugId != -1) { id = getId(); @@ -205,12 +205,12 @@ quint32 QQmlEngineDebugClient::queryObject( return id; } -quint32 QQmlEngineDebugClient::queryObjectsForLocation( - const QString &file, int lineNumber, int columnNumber, bool *success) +qint32 QQmlEngineDebugClient::queryObjectsForLocation( + const QString &file, qint32 lineNumber, qint32 columnNumber, bool *success) { Q_D(QQmlEngineDebugClient); d->objects.clear(); - quint32 id = -1; + qint32 id = -1; *success = false; if (state() == QQmlDebugClient::Enabled) { id = getId(); @@ -223,12 +223,12 @@ quint32 QQmlEngineDebugClient::queryObjectsForLocation( return id; } -quint32 QQmlEngineDebugClient::queryObjectRecursive( +qint32 QQmlEngineDebugClient::queryObjectRecursive( const QQmlEngineDebugObjectReference &object, bool *success) { Q_D(QQmlEngineDebugClient); d->object = QQmlEngineDebugObjectReference(); - quint32 id = -1; + qint32 id = -1; *success = false; if (state() == QQmlDebugClient::Enabled && object.debugId != -1) { id = getId(); @@ -240,12 +240,12 @@ quint32 QQmlEngineDebugClient::queryObjectRecursive( return id; } -quint32 QQmlEngineDebugClient::queryObjectsForLocationRecursive(const QString &file, - int lineNumber, int columnNumber, bool *success) +qint32 QQmlEngineDebugClient::queryObjectsForLocationRecursive(const QString &file, + qint32 lineNumber, qint32 columnNumber, bool *success) { Q_D(QQmlEngineDebugClient); d->objects.clear(); - quint32 id = -1; + qint32 id = -1; *success = false; if (state() == QQmlDebugClient::Enabled) { id = getId(); @@ -258,12 +258,12 @@ quint32 QQmlEngineDebugClient::queryObjectsForLocationRecursive(const QString &f return id; } -quint32 QQmlEngineDebugClient::queryExpressionResult( - int objectDebugId, const QString &expr, bool *success) +qint32 QQmlEngineDebugClient::queryExpressionResult( + qint32 objectDebugId, const QString &expr, bool *success) { Q_D(QQmlEngineDebugClient); d->exprResult = QVariant(); - quint32 id = -1; + qint32 id = -1; *success = false; if (state() == QQmlDebugClient::Enabled) { id = getId(); @@ -276,12 +276,12 @@ quint32 QQmlEngineDebugClient::queryExpressionResult( return id; } -quint32 QQmlEngineDebugClient::queryExpressionResultBC( - int objectDebugId, const QString &expr, bool *success) +qint32 QQmlEngineDebugClient::queryExpressionResultBC( + qint32 objectDebugId, const QString &expr, bool *success) { Q_D(QQmlEngineDebugClient); d->exprResult = QVariant(); - quint32 id = -1; + qint32 id = -1; *success = false; if (state() == QQmlDebugClient::Enabled) { id = getId(); @@ -293,15 +293,15 @@ quint32 QQmlEngineDebugClient::queryExpressionResultBC( return id; } -quint32 QQmlEngineDebugClient::setBindingForObject( - int objectDebugId, +qint32 QQmlEngineDebugClient::setBindingForObject( + qint32 objectDebugId, const QString &propertyName, const QVariant &bindingExpression, bool isLiteralValue, - const QString &source, int line, + const QString &source, qint32 line, bool *success) { - quint32 id = -1; + qint32 id = -1; *success = false; if (state() == QQmlDebugClient::Enabled && objectDebugId != -1) { id = getId(); @@ -314,12 +314,12 @@ quint32 QQmlEngineDebugClient::setBindingForObject( return id; } -quint32 QQmlEngineDebugClient::resetBindingForObject( - int objectDebugId, +qint32 QQmlEngineDebugClient::resetBindingForObject( + qint32 objectDebugId, const QString &propertyName, bool *success) { - quint32 id = -1; + qint32 id = -1; *success = false; if (state() == QQmlDebugClient::Enabled && objectDebugId != -1) { id = getId(); @@ -331,11 +331,11 @@ quint32 QQmlEngineDebugClient::resetBindingForObject( return id; } -quint32 QQmlEngineDebugClient::setMethodBody( - int objectDebugId, const QString &methodName, +qint32 QQmlEngineDebugClient::setMethodBody( + qint32 objectDebugId, const QString &methodName, const QString &methodBody, bool *success) { - quint32 id = -1; + qint32 id = -1; *success = false; if (state() == QQmlDebugClient::Enabled && objectDebugId != -1) { id = getId(); @@ -366,19 +366,19 @@ void QQmlEngineDebugClient::decode(QPacket &ds, if (simple) return; - int childCount; + qint32 childCount; bool recur; ds >> childCount >> recur; - for (int ii = 0; ii < childCount; ++ii) { + for (qint32 ii = 0; ii < childCount; ++ii) { o.children.append(QQmlEngineDebugObjectReference()); decode(ds, o.children.last(), !recur); } - int propCount; + qint32 propCount; ds >> propCount; - for (int ii = 0; ii < propCount; ++ii) { + for (qint32 ii = 0; ii < propCount; ++ii) { QQmlObjectProperty data; ds >> data; QQmlEngineDebugPropertyReference prop; @@ -414,9 +414,9 @@ void QQmlEngineDebugClient::decode(QPacket &ds, QList<QQmlEngineDebugObjectReference> &o, bool simple) { - int count; + qint32 count; ds >> count; - for (int i = 0; i < count; i++) { + for (qint32 i = 0; i < count; i++) { QQmlEngineDebugObjectReference obj; decode(ds, obj, simple); o << obj; @@ -464,18 +464,18 @@ void QQmlEngineDebugClient::decode(QPacket &ds, { ds >> c.name >> c.debugId; - int contextCount; + qint32 contextCount; ds >> contextCount; - for (int ii = 0; ii < contextCount; ++ii) { + for (qint32 ii = 0; ii < contextCount; ++ii) { c.contexts.append(QQmlEngineDebugContextReference()); decode(ds, c.contexts.last()); } - int objectCount; + qint32 objectCount; ds >> objectCount; - for (int ii = 0; ii < objectCount; ++ii) { + for (qint32 ii = 0; ii < objectCount; ++ii) { QQmlEngineDebugObjectReference obj; decode(ds, obj, true); @@ -490,18 +490,18 @@ void QQmlEngineDebugClient::messageReceived(const QByteArray &data) d->valid = false; QPacket ds(connection()->currentDataStreamVersion(), data); - int queryId; + qint32 queryId; QByteArray type; ds >> type >> queryId; //qDebug() << "QQmlEngineDebugPrivate::message()" << type; if (type == "LIST_ENGINES_R") { - int count; + qint32 count; ds >> count; d->engines.clear(); - for (int ii = 0; ii < count; ++ii) { + for (qint32 ii = 0; ii < count; ++ii) { QQmlEngineDebugEngineReference eng; ds >> eng.name; ds >> eng.debugId; @@ -532,7 +532,7 @@ void QQmlEngineDebugClient::messageReceived(const QByteArray &data) ds >> d->valid; } else if (type == "UPDATE_WATCH") { - int debugId; + qint32 debugId; QByteArray name; QVariant value; ds >> debugId >> name >> value; @@ -540,7 +540,9 @@ void QQmlEngineDebugClient::messageReceived(const QByteArray &data) return; } else if (type == "OBJECT_CREATED") { - int engineId, objectId, parentId; + qint32 engineId; + qint32 objectId; + qint32 parentId; ds >> engineId >> objectId >> parentId; emit newObject(objectId); return; @@ -557,7 +559,7 @@ void QQmlEngineDebugClient::messageReceived(const QByteArray &data) } -quint32 QQmlEngineDebugClient::getId() +qint32 QQmlEngineDebugClient::getId() { Q_D(QQmlEngineDebugClient); return d->nextId++; diff --git a/src/qmldebug/qqmlenginedebugclient_p.h b/src/qmldebug/qqmlenginedebugclient_p.h index 4a9cc3a020..0a01f2eac5 100644 --- a/src/qmldebug/qqmlenginedebugclient_p.h +++ b/src/qmldebug/qqmlenginedebugclient_p.h @@ -50,7 +50,7 @@ QT_BEGIN_NAMESPACE struct QQmlEngineDebugPropertyReference { - int objectDebugId = -1; + qint32 objectDebugId = -1; QString name; QVariant value; QString valueTypeName; @@ -61,25 +61,25 @@ struct QQmlEngineDebugPropertyReference struct QQmlEngineDebugFileReference { QUrl url; - int lineNumber = -1; - int columnNumber = -1; + qint32 lineNumber = -1; + qint32 columnNumber = -1; }; struct QQmlEngineDebugObjectReference { - int debugId = -1; + qint32 debugId = -1; QString className; QString idString; QString name; QQmlEngineDebugFileReference source; - int contextDebugId = -1; + qint32 contextDebugId = -1; QList<QQmlEngineDebugPropertyReference> properties; QList<QQmlEngineDebugObjectReference> children; }; struct QQmlEngineDebugContextReference { - int debugId = -1; + qint32 debugId = -1; QString name; QList<QQmlEngineDebugObjectReference> objects; QList<QQmlEngineDebugContextReference> contexts; @@ -87,7 +87,7 @@ struct QQmlEngineDebugContextReference struct QQmlEngineDebugEngineReference { - int debugId = -1; + qint32 debugId = -1; QString name; }; @@ -100,46 +100,46 @@ class QQmlEngineDebugClient : public QQmlDebugClient public: explicit QQmlEngineDebugClient(QQmlDebugConnection *conn); - quint32 addWatch(const QQmlEngineDebugPropertyReference &, - bool *success); - quint32 addWatch(const QQmlEngineDebugContextReference &, const QString &, - bool *success); - quint32 addWatch(const QQmlEngineDebugObjectReference &, const QString &, - bool *success); - quint32 addWatch(const QQmlEngineDebugObjectReference &, - bool *success); - quint32 addWatch(const QQmlEngineDebugFileReference &, + qint32 addWatch(const QQmlEngineDebugPropertyReference &, + bool *success); + qint32 addWatch(const QQmlEngineDebugContextReference &, const QString &, + bool *success); + qint32 addWatch(const QQmlEngineDebugObjectReference &, const QString &, + bool *success); + qint32 addWatch(const QQmlEngineDebugObjectReference &, + bool *success); + qint32 addWatch(const QQmlEngineDebugFileReference &, bool *success); - void removeWatch(quint32 watch, bool *success); - - quint32 queryAvailableEngines(bool *success); - quint32 queryRootContexts(const QQmlEngineDebugEngineReference &, - bool *success); - quint32 queryObject(const QQmlEngineDebugObjectReference &, - bool *success); - quint32 queryObjectsForLocation(const QString &file, - int lineNumber, int columnNumber, bool *success); - quint32 queryObjectRecursive(const QQmlEngineDebugObjectReference &, + void removeWatch(qint32 watch, bool *success); + + qint32 queryAvailableEngines(bool *success); + qint32 queryRootContexts(const QQmlEngineDebugEngineReference &, + bool *success); + qint32 queryObject(const QQmlEngineDebugObjectReference &, + bool *success); + qint32 queryObjectsForLocation(const QString &file, + qint32 lineNumber, qint32 columnNumber, bool *success); + qint32 queryObjectRecursive(const QQmlEngineDebugObjectReference &, + bool *success); + qint32 queryObjectsForLocationRecursive(const QString &file, + qint32 lineNumber, qint32 columnNumber, bool *success); + qint32 queryExpressionResult(qint32 objectDebugId, + const QString &expr, + bool *success); + qint32 queryExpressionResultBC(qint32 objectDebugId, + const QString &expr, bool *success); - quint32 queryObjectsForLocationRecursive(const QString &file, - int lineNumber, int columnNumber, bool *success); - quint32 queryExpressionResult(int objectDebugId, - const QString &expr, - bool *success); - quint32 queryExpressionResultBC(int objectDebugId, - const QString &expr, - bool *success); - quint32 setBindingForObject(int objectDebugId, const QString &propertyName, - const QVariant &bindingExpression, - bool isLiteralValue, - const QString &source, int line, bool *success); - quint32 resetBindingForObject(int objectDebugId, - const QString &propertyName, bool *success); - quint32 setMethodBody(int objectDebugId, const QString &methodName, - const QString &methodBody, bool *success); - - quint32 getId(); + qint32 setBindingForObject(qint32 objectDebugId, const QString &propertyName, + const QVariant &bindingExpression, + bool isLiteralValue, + const QString &source, qint32 line, bool *success); + qint32 resetBindingForObject(qint32 objectDebugId, + const QString &propertyName, bool *success); + qint32 setMethodBody(qint32 objectDebugId, const QString &methodName, + const QString &methodBody, bool *success); + + qint32 getId(); void decode(QPacket &ds, QQmlEngineDebugContextReference &); void decode(QPacket &ds, QQmlEngineDebugObjectReference &, bool simple); @@ -153,7 +153,7 @@ public: bool valid() const; signals: - void newObject(int objectId); + void newObject(qint32 objectId); void valueChanged(QByteArray,QVariant); void result(); diff --git a/src/qmldebug/qqmlenginedebugclient_p_p.h b/src/qmldebug/qqmlenginedebugclient_p_p.h index 7c992ad3ab..b73da15e9d 100644 --- a/src/qmldebug/qqmlenginedebugclient_p_p.h +++ b/src/qmldebug/qqmlenginedebugclient_p_p.h @@ -62,7 +62,7 @@ class QQmlEngineDebugClientPrivate : public QQmlDebugClientPrivate public: QQmlEngineDebugClientPrivate(QQmlDebugConnection *connection); - quint32 nextId = 0; + qint32 nextId = 0; bool valid = false; QList<QQmlEngineDebugEngineReference> engines; QQmlEngineDebugContextReference rootContext; diff --git a/src/qmlmodels/qqmldelegatemodel.cpp b/src/qmlmodels/qqmldelegatemodel.cpp index 691b4b3c29..2c3382c643 100644 --- a/src/qmlmodels/qqmldelegatemodel.cpp +++ b/src/qmlmodels/qqmldelegatemodel.cpp @@ -453,7 +453,8 @@ void QQmlDelegateModel::setDelegate(QQmlComponent *delegate) } if (d->m_delegate == delegate) return; - bool wasValid = d->m_delegate != nullptr; + if (d->m_complete) + _q_itemsRemoved(0, d->m_count); d->m_delegate.setObject(delegate, this); d->m_delegateValidated = false; if (d->m_delegateChooser) @@ -469,7 +470,11 @@ void QQmlDelegateModel::setDelegate(QQmlComponent *delegate) [d](){ d->delegateChanged(); }); } } - d->delegateChanged(d->m_delegate, wasValid); + if (d->m_complete) { + _q_itemsInserted(0, d->adaptorModelCount()); + d->requestMoreIfNecessary(); + } + emit delegateChanged(); } /*! diff --git a/src/qmlmodels/qqmldelegatemodel_p.h b/src/qmlmodels/qqmldelegatemodel_p.h index 7492f2b77d..02904a71d7 100644 --- a/src/qmlmodels/qqmldelegatemodel_p.h +++ b/src/qmlmodels/qqmldelegatemodel_p.h @@ -77,7 +77,7 @@ class Q_QMLMODELS_PRIVATE_EXPORT QQmlDelegateModel : public QQmlInstanceModel, p Q_DECLARE_PRIVATE(QQmlDelegateModel) Q_PROPERTY(QVariant model READ model WRITE setModel) - Q_PROPERTY(QQmlComponent *delegate READ delegate WRITE setDelegate) + Q_PROPERTY(QQmlComponent *delegate READ delegate WRITE setDelegate NOTIFY delegateChanged) Q_PROPERTY(QString filterOnGroup READ filterGroup WRITE setFilterGroup NOTIFY filterGroupChanged RESET resetFilterGroup) Q_PROPERTY(QQmlDelegateModelGroup *items READ items CONSTANT) //TODO : worth renaming? Q_PROPERTY(QQmlDelegateModelGroup *persistedItems READ persistedItems CONSTANT) @@ -140,6 +140,7 @@ Q_SIGNALS: void filterGroupChanged(); void defaultGroupsChanged(); void rootIndexChanged(); + void delegateChanged(); private Q_SLOTS: void _q_itemsChanged(int index, int count, const QVector<int> &roles); diff --git a/src/qmlmodels/qqmllistmodel.cpp b/src/qmlmodels/qqmllistmodel.cpp index 1cd089f454..d68815cbc1 100644 --- a/src/qmlmodels/qqmllistmodel.cpp +++ b/src/qmlmodels/qqmllistmodel.cpp @@ -1641,8 +1641,18 @@ PropertyKey ModelObjectOwnPropertyKeyIterator::next(const Object *o, Property *p if (attrs) *attrs = QV4::Attr_Data; if (pd) { + QVariant value = that->d()->m_model->data(that->d()->elementIndex(), role.index); - pd->value = v4->fromVariant(value); + if (auto recursiveListModel = qvariant_cast<QQmlListModel*>(value)) { + auto size = recursiveListModel->count(); + auto array = ScopedArrayObject{scope, v4->newArrayObject(size)}; + for (auto i = 0; i < size; i++) { + array->arrayPut(i, QJSValuePrivate::convertedToValue(v4, recursiveListModel->get(i))); + } + pd->value = array; + } else { + pd->value = v4->fromVariant(value); + } } return roleName->toPropertyKey(); } diff --git a/src/quick/items/qquickitemview.cpp b/src/quick/items/qquickitemview.cpp index bbfbf6244c..e1af65c986 100644 --- a/src/quick/items/qquickitemview.cpp +++ b/src/quick/items/qquickitemview.cpp @@ -247,6 +247,8 @@ void QQuickItemView::setModel(const QVariant &m) connect(d->model, SIGNAL(modelUpdated(QQmlChangeSet,bool)), this, SLOT(modelUpdated(QQmlChangeSet,bool))); + if (QQmlDelegateModel *dataModel = qobject_cast<QQmlDelegateModel*>(d->model)) + QObjectPrivate::connect(dataModel, &QQmlDelegateModel::delegateChanged, d, &QQuickItemViewPrivate::applyDelegateChange); emit countChanged(); } emit modelChanged(); @@ -277,22 +279,8 @@ void QQuickItemView::setDelegate(QQmlComponent *delegate) if (QQmlDelegateModel *dataModel = qobject_cast<QQmlDelegateModel*>(d->model)) { int oldCount = dataModel->count(); dataModel->setDelegate(delegate); - if (isComponentComplete()) { - d->releaseVisibleItems(); - d->releaseItem(d->currentItem); - d->currentItem = nullptr; - d->updateSectionCriteria(); - d->refill(); - d->moveReason = QQuickItemViewPrivate::SetIndex; - d->updateCurrent(d->currentIndex); - if (d->highlight && d->currentItem) { - if (d->autoHighlight) - d->resetHighlightPosition(); - d->updateTrackedItem(); - } - d->moveReason = QQuickItemViewPrivate::Other; - d->updateViewport(); - } + if (isComponentComplete()) + d->applyDelegateChange(); if (oldCount != dataModel->count()) emit countChanged(); } @@ -1089,6 +1077,24 @@ qreal QQuickItemViewPrivate::calculatedMaxExtent() const return maxExtent; } +void QQuickItemViewPrivate::applyDelegateChange() +{ + releaseVisibleItems(); + releaseItem(currentItem); + currentItem = nullptr; + updateSectionCriteria(); + refill(); + moveReason = QQuickItemViewPrivate::SetIndex; + updateCurrent(currentIndex); + if (highlight && currentItem) { + if (autoHighlight) + resetHighlightPosition(); + updateTrackedItem(); + } + moveReason = QQuickItemViewPrivate::Other; + updateViewport(); +} + // for debugging only void QQuickItemViewPrivate::checkVisible() const { diff --git a/src/quick/items/qquickitemview_p_p.h b/src/quick/items/qquickitemview_p_p.h index ef674f0fc7..860cf5fa20 100644 --- a/src/quick/items/qquickitemview_p_p.h +++ b/src/quick/items/qquickitemview_p_p.h @@ -191,6 +191,8 @@ public: qreal calculatedMinExtent() const; qreal calculatedMaxExtent() const; + void applyDelegateChange(); + void applyPendingChanges(); bool applyModelChanges(ChangeResult *insertionResult, ChangeResult *removalResult); bool applyRemovalChange(const QQmlChangeSet::Change &removal, ChangeResult *changeResult, int *removedCount); diff --git a/src/quick/items/qquicktextcontrol.cpp b/src/quick/items/qquicktextcontrol.cpp index 127b3c3516..3c392be751 100644 --- a/src/quick/items/qquicktextcontrol.cpp +++ b/src/quick/items/qquicktextcontrol.cpp @@ -1212,8 +1212,8 @@ void QQuickTextControlPrivate::mouseReleaseEvent(QMouseEvent *e, const QPointF & QTextBlock block = q->blockWithMarkerAt(pos); if (block == blockWithMarkerUnderMousePress) { auto fmt = block.blockFormat(); - fmt.setMarker(fmt.marker() == QTextBlockFormat::Unchecked ? - QTextBlockFormat::Checked : QTextBlockFormat::Unchecked); + fmt.setMarker(fmt.marker() == QTextBlockFormat::MarkerType::Unchecked ? + QTextBlockFormat::MarkerType::Checked : QTextBlockFormat::MarkerType::Unchecked); cursor.setBlockFormat(fmt); } } @@ -1507,7 +1507,7 @@ void QQuickTextControlPrivate::hoverEvent(QHoverEvent *e, const QPointF &pos) emit q->markerHovered(block.isValid()); hoveredMarker = block.isValid(); if (hoveredMarker) - qCDebug(DBG_HOVER_TRACE) << q << e->type() << pos << "hovered marker" << block.blockFormat().marker() << block.text(); + qCDebug(DBG_HOVER_TRACE) << q << e->type() << pos << "hovered marker" << int(block.blockFormat().marker()) << block.text(); } } diff --git a/src/quick/items/qquicktextnodeengine.cpp b/src/quick/items/qquicktextnodeengine.cpp index f8ebf13a1d..a0ae4e5f97 100644 --- a/src/quick/items/qquicktextnodeengine.cpp +++ b/src/quick/items/qquicktextnodeengine.cpp @@ -1012,13 +1012,13 @@ void QQuickTextNodeEngine::addTextBlock(QTextDocument *textDocument, const QText }; switch (block.blockFormat().marker()) { - case QTextBlockFormat::Checked: + case QTextBlockFormat::MarkerType::Checked: listItemBullet = QChar(0x2612); // Checked checkbox break; - case QTextBlockFormat::Unchecked: + case QTextBlockFormat::MarkerType::Unchecked: listItemBullet = QChar(0x2610); // Unchecked checkbox break; - case QTextBlockFormat::NoMarker: + case QTextBlockFormat::MarkerType::NoMarker: break; } diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index 3885700af8..9e88f93b11 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -102,6 +102,7 @@ Q_LOGGING_CATEGORY(DBG_DIRTY, "qt.quick.dirty") Q_LOGGING_CATEGORY(lcTransient, "qt.quick.window.transient") extern Q_GUI_EXPORT QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format, bool include_alpha); +extern Q_GUI_EXPORT bool qt_sendShortcutOverrideEvent(QObject *o, ulong timestamp, int k, Qt::KeyboardModifiers mods, const QString &text = QString(), bool autorep = false, ushort count = 1); bool QQuickWindowPrivate::defaultAlphaBuffer = false; @@ -1794,6 +1795,13 @@ void QQuickWindowPrivate::deliverKeyEvent(QKeyEvent *e) { if (activeFocusItem) { QQuickItem *item = activeFocusItem; + + // In case of generated event, trigger ShortcutOverride event + if (e->type() == QEvent::KeyPress && e->spontaneous() == false) + qt_sendShortcutOverrideEvent(item, e->timestamp(), + e->key(), e->modifiers(), e->text(), + e->isAutoRepeat(), e->count()); + e->accept(); QCoreApplication::sendEvent(item, e); while (!e->isAccepted() && (item = item->parentItem())) { @@ -2820,32 +2828,49 @@ void QQuickWindowPrivate::deliverDragEvent(QQuickDragGrabber *grabber, QEvent *e for (; grabItem != grabber->end(); grabItem = grabber->release(grabItem)) QCoreApplication::sendEvent(**grabItem, &leaveEvent); return; - } else for (; grabItem != grabber->end(); grabItem = grabber->release(grabItem)) { + } else { QDragMoveEvent *moveEvent = static_cast<QDragMoveEvent *>(event); - if (deliverDragEvent(grabber, **grabItem, moveEvent)) { - for (++grabItem; grabItem != grabber->end();) { - QPointF p = (**grabItem)->mapFromScene(moveEvent->pos()); - if ((**grabItem)->contains(p)) { - QDragMoveEvent translatedEvent( - p.toPoint(), - moveEvent->possibleActions(), - moveEvent->mimeData(), - moveEvent->mouseButtons(), - moveEvent->keyboardModifiers()); - QQuickDropEventEx::copyActions(&translatedEvent, *moveEvent); - QCoreApplication::sendEvent(**grabItem, &translatedEvent); - ++grabItem; - } else { - QDragLeaveEvent leaveEvent; - QCoreApplication::sendEvent(**grabItem, &leaveEvent); - grabItem = grabber->release(grabItem); - } + + // Used to ensure we don't send DragEnterEvents to current drop targets, + // and to detect which current drop targets we have left + QVarLengthArray<QQuickItem*, 64> currentGrabItems; + for (; grabItem != grabber->end(); grabItem = grabber->release(grabItem)) + currentGrabItems.append(**grabItem); + + // Look for any other potential drop targets that are higher than the current ones + QDragEnterEvent enterEvent( + moveEvent->pos(), + moveEvent->possibleActions(), + moveEvent->mimeData(), + moveEvent->mouseButtons(), + moveEvent->keyboardModifiers()); + QQuickDropEventEx::copyActions(&enterEvent, *moveEvent); + event->setAccepted(deliverDragEvent(grabber, contentItem, &enterEvent, ¤tGrabItems)); + + for (grabItem = grabber->begin(); grabItem != grabber->end(); ++grabItem) { + int i = currentGrabItems.indexOf(**grabItem); + if (i >= 0) { + currentGrabItems.remove(i); + // Still grabbed: send move event + QDragMoveEvent translatedEvent( + (**grabItem)->mapFromScene(moveEvent->pos()).toPoint(), + moveEvent->possibleActions(), + moveEvent->mimeData(), + moveEvent->mouseButtons(), + moveEvent->keyboardModifiers()); + QQuickDropEventEx::copyActions(&translatedEvent, *moveEvent); + QCoreApplication::sendEvent(**grabItem, &translatedEvent); + event->setAccepted(translatedEvent.isAccepted()); + QQuickDropEventEx::copyActions(moveEvent, translatedEvent); } - return; - } else { - QDragLeaveEvent leaveEvent; - QCoreApplication::sendEvent(**grabItem, &leaveEvent); } + + // Anything left in currentGrabItems is no longer a drop target and should be sent a DragLeaveEvent + QDragLeaveEvent leaveEvent; + for (QQuickItem *i : currentGrabItems) + QCoreApplication::sendEvent(i, &leaveEvent); + + return; } } if (event->type() == QEvent::DragEnter || event->type() == QEvent::DragMove) { @@ -2861,9 +2886,8 @@ void QQuickWindowPrivate::deliverDragEvent(QQuickDragGrabber *grabber, QEvent *e } } -bool QQuickWindowPrivate::deliverDragEvent(QQuickDragGrabber *grabber, QQuickItem *item, QDragMoveEvent *event) +bool QQuickWindowPrivate::deliverDragEvent(QQuickDragGrabber *grabber, QQuickItem *item, QDragMoveEvent *event, QVarLengthArray<QQuickItem*, 64> *currentGrabItems) { - bool accepted = false; QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item); if (!item->isVisible() || !item->isEnabled() || QQuickItemPrivate::get(item)->culled) return false; @@ -2882,12 +2906,24 @@ bool QQuickWindowPrivate::deliverDragEvent(QQuickDragGrabber *grabber, QQuickIte event->keyboardModifiers()); QQuickDropEventEx::copyActions(&enterEvent, *event); QList<QQuickItem *> children = itemPrivate->paintOrderChildItems(); + + // Check children in front of this item first for (int ii = children.count() - 1; ii >= 0; --ii) { - if (deliverDragEvent(grabber, children.at(ii), &enterEvent)) + if (children.at(ii)->z() < 0) + continue; + if (deliverDragEvent(grabber, children.at(ii), &enterEvent, currentGrabItems)) return true; } if (itemContained) { + // If this item is currently grabbed, don't send it another DragEnter, + // just grab it again if it's still contained. + if (currentGrabItems && currentGrabItems->contains(item)) { + grabber->grab(item); + grabber->setTarget(item); + return true; + } + if (event->type() == QEvent::DragMove || itemPrivate->flags & QQuickItem::ItemAcceptsDrops) { QDragMoveEvent translatedEvent( p.toPoint(), @@ -2904,15 +2940,24 @@ bool QQuickWindowPrivate::deliverDragEvent(QQuickDragGrabber *grabber, QQuickIte if (event->type() == QEvent::DragEnter) { if (translatedEvent.isAccepted()) { grabber->grab(item); - accepted = true; + grabber->setTarget(item); + return true; } } else { - accepted = true; + return true; } } } - return accepted; + // Check children behind this item if this item or any higher children have not accepted + for (int ii = children.count() - 1; ii >= 0; --ii) { + if (children.at(ii)->z() >= 0) + continue; + if (deliverDragEvent(grabber, children.at(ii), &enterEvent, currentGrabItems)) + return true; + } + + return false; } #endif // quick_draganddrop diff --git a/src/quick/items/qquickwindow_p.h b/src/quick/items/qquickwindow_p.h index 432ed99a53..af7d65dac5 100644 --- a/src/quick/items/qquickwindow_p.h +++ b/src/quick/items/qquickwindow_p.h @@ -192,7 +192,7 @@ public: #if QT_CONFIG(quick_draganddrop) void deliverDragEvent(QQuickDragGrabber *, QEvent *); - bool deliverDragEvent(QQuickDragGrabber *, QQuickItem *, QDragMoveEvent *); + bool deliverDragEvent(QQuickDragGrabber *, QQuickItem *, QDragMoveEvent *, QVarLengthArray<QQuickItem*, 64> *currentGrabItems = nullptr); #endif #if QT_CONFIG(cursor) void updateCursor(const QPointF &scenePos); diff --git a/src/quick/scenegraph/qsgrenderloop.cpp b/src/quick/scenegraph/qsgrenderloop.cpp index ba231f8159..f609055677 100644 --- a/src/quick/scenegraph/qsgrenderloop.cpp +++ b/src/quick/scenegraph/qsgrenderloop.cpp @@ -619,6 +619,24 @@ void QSGGuiThreadRenderLoop::renderWindow(QQuickWindow *window) i++; } + // Check for context loss. + if (!current && !rhi && !gl->isValid()) { + for (auto it = m_windows.constBegin() ; it != m_windows.constEnd(); it++) { + QQuickWindowPrivate *windowPrivate = QQuickWindowPrivate::get(it.key()); + windowPrivate->cleanupNodesOnShutdown(); + } + rc->invalidate(); + current = gl->create() && gl->makeCurrent(window); + if (current) { + QSGDefaultRenderContext::InitParams rcParams; + rcParams.sampleCount = qMax(1, gl->format().samples()); + rcParams.openGLContext = gl; + rcParams.initialSurfacePixelSize = window->size() * window->effectiveDevicePixelRatio(); + rcParams.maybeSurface = window; + rc->initialize(&rcParams); + } + } + if (!current) return; diff --git a/src/quick/util/qquickvaluetypes.cpp b/src/quick/util/qquickvaluetypes.cpp index e4a03f3b52..0af29aed1c 100644 --- a/src/quick/util/qquickvaluetypes.cpp +++ b/src/quick/util/qquickvaluetypes.cpp @@ -109,6 +109,11 @@ qreal QQuickColorValueType::hslLightness() const return v.lightnessF(); } +bool QQuickColorValueType::isValid() const +{ + return v.isValid(); +} + void QQuickColorValueType::setR(qreal r) { v.setRedF(r); diff --git a/src/quick/util/qquickvaluetypes_p.h b/src/quick/util/qquickvaluetypes_p.h index 25fac72a38..91e3815d5b 100644 --- a/src/quick/util/qquickvaluetypes_p.h +++ b/src/quick/util/qquickvaluetypes_p.h @@ -84,6 +84,7 @@ class QQuickColorValueType Q_PROPERTY(qreal hslHue READ hslHue WRITE setHslHue FINAL) Q_PROPERTY(qreal hslSaturation READ hslSaturation WRITE setHslSaturation FINAL) Q_PROPERTY(qreal hslLightness READ hslLightness WRITE setHslLightness FINAL) + Q_PROPERTY(bool valid READ isValid) Q_GADGET public: Q_INVOKABLE QString toString() const; @@ -98,6 +99,7 @@ public: qreal hslHue() const; qreal hslSaturation() const; qreal hslLightness() const; + bool isValid() const; void setR(qreal); void setG(qreal); void setB(qreal); diff --git a/src/quickwidgets/qquickwidget.cpp b/src/quickwidgets/qquickwidget.cpp index 0da9b12e86..c975404d69 100644 --- a/src/quickwidgets/qquickwidget.cpp +++ b/src/quickwidgets/qquickwidget.cpp @@ -283,7 +283,16 @@ void QQuickWidgetPrivate::render(bool needsSync) Q_ASSERT(context); - if (!context->makeCurrent(offscreenSurface)) { + bool current = context->makeCurrent(offscreenSurface); + + if (!current && !context->isValid()) { + renderControl->invalidate(); + current = context->create() && context->makeCurrent(offscreenSurface); + if (current) + renderControl->initialize(context); + } + + if (!current) { qWarning("QQuickWidget: Cannot render due to failing makeCurrent()"); return; } |