diff options
author | Sean Harmer <sean.harmer@kdab.com> | 2016-05-20 10:31:30 +0100 |
---|---|---|
committer | Sean Harmer <sean.harmer@kdab.com> | 2016-05-23 16:32:01 +0000 |
commit | 9e07d3ae8f5b90b84735b3b8b81fa6c749a646b2 (patch) | |
tree | 8cdf07d8129ddf49f451faa5897a2379534ae66e /src | |
parent | 073930f2ef030b3019c323999d910185f4639d9b (diff) |
Add hook to set QNode parent when creating a QNode in QML
Just need to be a little careful in QNode::setParent() and the
helper in case the qml engine sets a QObject parent but QNode
doesn't know about it yet.
Task-number: QTBUG-47055
Change-Id: I30269bd230ee6eacd2816282fd48f879cfb7c83a
Reviewed-by: Kevin Ottens <kevin.ottens@kdab.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/core/nodes/qnode.cpp | 18 | ||||
-rw-r--r-- | src/quick3d/quick3d/qt3dquick_global.cpp | 27 |
2 files changed, 43 insertions, 2 deletions
diff --git a/src/core/nodes/qnode.cpp b/src/core/nodes/qnode.cpp index 4cdd9ca7b..871eaed39 100644 --- a/src/core/nodes/qnode.cpp +++ b/src/core/nodes/qnode.cpp @@ -115,6 +115,10 @@ void QNodePrivate::init(QNode *parent) void QNodePrivate::notifyCreationChange() { Q_Q(QNode); + // Do nothing if we already have already sent a node creation change + // and not a subsequent node destroyed change. + if (m_hasBackendNode) + return; QNodeCreatedChangeGenerator generator(q); const auto creationChanges = generator.creationChanges(); for (const auto &change : creationChanges) @@ -265,6 +269,13 @@ void QNodePrivate::_q_setParentHelper(QNode *parent) Q_Q(QNode); QNode *oldParentNode = q->parentNode(); + // We may get the situation where the QML engine has set the QObject + // parent but we have not yet set up the QNode parent requirements. + // This check handles this and means we propagate the scene and arbiter + // from the parent in the code below. + const bool needsSceneInit = !oldParentNode + || (oldParentNode && m_parentId != oldParentNode->id()); + // If we had a parent, we let him know that we are about to change // parent if (oldParentNode) { @@ -283,7 +294,7 @@ void QNodePrivate::_q_setParentHelper(QNode *parent) if (newParentNode) { // If we had no parent but are about to set one, // we need to send a QNodeCreatedChange - if (!oldParentNode) { + if (needsSceneInit) { QNodePrivate *newParentPrivate = QNodePrivate::get(newParentNode); // Set the scene helper / arbiter @@ -696,7 +707,10 @@ bool QNode::blockNotifications(bool block) void QNode::setParent(QNode *parent) { Q_D(QNode); - if (parentNode() == parent) + + // If we already have a parent don't do anything. Be careful to ensure + // that QNode knows about the parent, not just QObject (by checking the ids) + if (parentNode() == parent && d->m_parentId == parentNode()->id()) return; d->_q_setParentHelper(parent); diff --git a/src/quick3d/quick3d/qt3dquick_global.cpp b/src/quick3d/quick3d/qt3dquick_global.cpp index 78523aa4a..f25aae268 100644 --- a/src/quick3d/quick3d/qt3dquick_global.cpp +++ b/src/quick3d/quick3d/qt3dquick_global.cpp @@ -669,12 +669,39 @@ static Quick3DColorProvider *getColorProvider() return &colorProvider; } +static QQmlPrivate::AutoParentResult qquick3ditem_autoParent(QObject *obj, QObject *parent) +{ + // When setting a parent (especially during dynamic object creation) in QML, + // also try to set up the analogous item/window relationship. + auto parentNode = qmlobject_cast<Qt3DCore::QNode *>(parent); + if (parentNode) { + auto node = qmlobject_cast<Qt3DCore::QNode *>(obj); + if (node) { + // A QNode has another QNode child + node->setParent(parentNode); + return QQmlPrivate::Parented; + } + } else { + return QQmlPrivate::IncompatibleParent; + } + return QQmlPrivate::IncompatibleObject; +} + void Quick3D_initialize() { Qt3DCore::Quick::Quick3DValueTypes::registerValueTypes(); QQml_addValueTypeProvider(getValueTypeProvider()); QQml_setColorProvider(getColorProvider()); QAbstractNodeFactory::registerNodeFactory(QuickNodeFactory::instance()); + + // Register a hook called when we do component.create() that sets the + // parent. We need this as QObject::setParent() is insufficient to propagate + // the arbiter and scene to the children (see QNode::setParent(QNode *). + // TODO: Replace this with virtual void QObjectPrivate::setParent(QObject *) + // that can be called from QObject ctor and QObject::setParent(). That would + // allow removal of this hook here and in QtQuick. + QQmlPrivate::RegisterAutoParent autoparent = { 0, &qquick3ditem_autoParent }; + QQmlPrivate::qmlregister(QQmlPrivate::AutoParentRegistration, &autoparent); } void Quick3D_registerType(const char *className, const char *quickName, int major, int minor) |