summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSean Harmer <sean.harmer@kdab.com>2016-05-20 10:31:30 +0100
committerSean Harmer <sean.harmer@kdab.com>2016-05-23 16:32:01 +0000
commit9e07d3ae8f5b90b84735b3b8b81fa6c749a646b2 (patch)
tree8cdf07d8129ddf49f451faa5897a2379534ae66e /src
parent073930f2ef030b3019c323999d910185f4639d9b (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.cpp18
-rw-r--r--src/quick3d/quick3d/qt3dquick_global.cpp27
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)