qskinny
qskinny copied to clipboard
Add QSG/QSK Nodes Dos and Donts / Pitfalls documentation
I had to fix this issues multiple times now, maybe we could add a "QSG/QSK Nodes Dos and Donts" or "QSG/QSK Nodes pitfalls" documentation
Do NOT attach QSG nodes to a node that YOU DON'T control!
Scenario
class QskNotYourNode : public QSGNode
{
public:
QskNotYourNode()
{
appendChildNode(new QskBoxNode); // background
appendChildNode(new QskTextNode); // forground
}
void update()
{
auto* const background = static_cast<QskBoxNode*>(firstChild()); // HERE AN EXPLICIT TYPE AND POSITION ARE ASSUMED!
auto* const foreground = static_cast<QskTextNode*>(lastChild()); // HERE AN EXPLICIT TYPE AND POSITION ARE ASSUMED!
background->update();
foreground->update();
}
};
class YourNode : public QSGNode
{
public:
YourNode()
{
auto* const background = new QskNotYourNode;
auto* const handleNode = new QskBoxNode;
background->appendChildNode(handleNode); // now QskNotYourNode will cause a crash when being updated!
appendChildNode(background);
}
}
Solution A - Add sibling instead of child
Place your additionaly node next to the node you don't control.
class YourNode : public QSGNode
{
public:
YourNode()
{
auto* const background = new QskNotYourNode;
auto* const handleNode = new QskBoxNode;
appendChildNode(background);
appendChildNode(handleNode);
}
}
There are strategies to prevent this, but they are not being used everywhere since they introduce more complexity and computation:
- one could use
dynamic_cast
which is slower thatstatic_cast
- still doesn't improve positional expectations!
- one could use
QskSGNode::setNodeRole
to give a node a role id (int
)- this requires linearly scanning the children and checking for their role!
Concerning dynamic_cast: I would not mind the extra costs compared to the static_cast - it is more that building a library without RTTI ( gcc: -fno-rtti ) is one of the ways to reduce the binary size, what might be relevant on embedded platforms. Not the strongest argument, as Qt is in general no good platform if memory counts ...
IMHO using node roles is probably the best option if you do not have full control over the subtree. Whenever having a non trivial number of children you would use it anyway and the cost for running over the children can IMHO be neglected for your 2 children example.
We should check the existing code base to always use node roles.
By the way: the nodeRole is stored in some ( so far ) unused bits that are reserved for QSGNode::flags(). Fingers crossed, that they will never be used in future Qt versions.