summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Lemire <paul.lemire@kdab.com>2018-01-19 15:34:58 +0100
committerPaul Lemire <paul.lemire@kdab.com>2018-02-21 07:04:30 +0000
commit0fd16cf43fc94344ab7944379f3dd9645156a4fd (patch)
tree517cc1455baf02399b442173721ec97976e527b0
parentba3c6bc0ffcbc9987eab2027102d9972de4592bb (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.h21
-rw-r--r--src/render/materialsystem/qparameter.cpp9
-rw-r--r--tests/auto/render/qparameter/tst_qparameter.cpp22
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(&parameter, 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)