diff options
author | Paul Lemire <paul.lemire@kdab.com> | 2018-01-19 15:34:58 +0100 |
---|---|---|
committer | Paul Lemire <paul.lemire@kdab.com> | 2018-02-21 07:04:30 +0000 |
commit | 0fd16cf43fc94344ab7944379f3dd9645156a4fd (patch) | |
tree | 517cc1455baf02399b442173721ec97976e527b0 | |
parent | ba3c6bc0ffcbc9987eab2027102d9972de4592bb (diff) |
QParameter: add bookkeeping of QNode values
Change-Id: I0a7334907e4b34df6955fb24832958b674d7b62b
Reviewed-by: Sean Harmer <sean.harmer@kdab.com>
-rw-r--r-- | src/core/nodes/qnode_p.h | 21 | ||||
-rw-r--r-- | src/render/materialsystem/qparameter.cpp | 9 | ||||
-rw-r--r-- | tests/auto/render/qparameter/tst_qparameter.cpp | 22 |
3 files changed, 48 insertions, 4 deletions
diff --git a/src/core/nodes/qnode_p.h b/src/core/nodes/qnode_p.h index c203b342f..73893cc1e 100644 --- a/src/core/nodes/qnode_p.h +++ b/src/core/nodes/qnode_p.h @@ -108,13 +108,13 @@ public: static void nodePtrDeleter(QNode *q); template<typename Caller, typename NodeType> - using DestructionFunction = void (Caller::*)(NodeType *); + using DestructionFunctionPointer = void (Caller::*)(NodeType *); template<typename Caller, typename NodeType, typename PropertyType> - void registerDestructionHelper(NodeType *, DestructionFunction<Caller, NodeType>, PropertyType); + void registerDestructionHelper(NodeType *, DestructionFunctionPointer<Caller, NodeType>, PropertyType); template<typename Caller, typename NodeType> - void registerDestructionHelper(NodeType *node, DestructionFunction<Caller, NodeType> func, NodeType *&) + void registerDestructionHelper(NodeType *node, DestructionFunctionPointer<Caller, NodeType> func, NodeType *&) { // If the node is destoyed, we make sure not to keep a dangling pointer to it Q_Q(QNode); @@ -123,7 +123,7 @@ public: } template<typename Caller, typename NodeType> - void registerDestructionHelper(NodeType *node, DestructionFunction<Caller, NodeType> func, QVector<NodeType*> &) + void registerDestructionHelper(NodeType *node, DestructionFunctionPointer<Caller, NodeType> func, QVector<NodeType*> &) { // If the node is destoyed, we make sure not to keep a dangling pointer to it Q_Q(QNode); @@ -131,6 +131,19 @@ public: m_destructionConnections.insert(node, QObject::connect(node, &QNode::nodeDestroyed, f)); } + template<typename Caller, typename ValueType> + using DestructionFunctionValue = void (Caller::*)(const ValueType&); + + template<typename Caller, typename NodeType, typename ValueType> + void registerDestructionHelper(NodeType *node, DestructionFunctionValue<Caller, ValueType> func, NodeType *&, + const ValueType &resetValue) + { + // If the node is destoyed, we make sure not to keep a dangling pointer to it + Q_Q(QNode); + auto f = [q, func, resetValue]() { (static_cast<Caller *>(q)->*func)(resetValue); }; + m_destructionConnections.insert(node, QObject::connect(node, &QNode::nodeDestroyed, f)); + } + void unregisterDestructionHelper(QNode *node) { QObject::disconnect(m_destructionConnections.take(node)); diff --git a/src/render/materialsystem/qparameter.cpp b/src/render/materialsystem/qparameter.cpp index 2b2dd29d5..afaf42158 100644 --- a/src/render/materialsystem/qparameter.cpp +++ b/src/render/materialsystem/qparameter.cpp @@ -288,12 +288,21 @@ void QParameter::setValue(const QVariant &dv) Q_D(QParameter); if (d->m_value != dv) { + QNode *oldNodeValue = d->m_value.value<QNode *>(); + if (oldNodeValue != nullptr) + d->unregisterDestructionHelper(oldNodeValue); + // In case node values are declared inline QNode *nodeValue = dv.value<QNode *>(); if (nodeValue != nullptr && !nodeValue->parent()) nodeValue->setParent(this); d->setValue(dv); + + // Ensures proper bookkeeping + if (nodeValue != nullptr) + d->registerDestructionHelper(nodeValue, &QParameter::setValue, nodeValue, QVariant()); + emit valueChanged(dv); } } diff --git a/tests/auto/render/qparameter/tst_qparameter.cpp b/tests/auto/render/qparameter/tst_qparameter.cpp index f124af809..d5957db27 100644 --- a/tests/auto/render/qparameter/tst_qparameter.cpp +++ b/tests/auto/render/qparameter/tst_qparameter.cpp @@ -249,6 +249,28 @@ private Q_SLOTS: } + void checkBookeeping() + { + // GIVEN + Qt3DRender::QParameter parameter; + QSignalSpy spy(¶meter, SIGNAL(valueChanged(QVariant))); + + { + // WHEN + QScopedPointer<Qt3DCore::QNode> node(new Qt3DCore::QNode()); + parameter.setValue(QVariant::fromValue(node.data())); + + // THEN + QCOMPARE(spy.count(), 1); + QCOMPARE(parameter.value(), QVariant::fromValue(node.data())); + spy.clear(); + } + + // THEN + QCOMPARE(spy.count(), 1); + QCOMPARE(parameter.value(), QVariant()); + } + }; QTEST_MAIN(tst_QParameter) |