// SPDX-License-Identifier: GPL-2.0 // Helper functions to render the stats. Currently only // contains a small template to create scene-items. This // is for historical reasons to ease transition from QtCharts // and might be removed. #ifndef STATSHELPER_H #define STATSHELPER_H #include #include #include template T *createItem(QGraphicsScene *scene, Args&&... args) { T *res = new T(std::forward(args)...); scene->addItem(res); return res; } template std::unique_ptr createItemPtr(QGraphicsScene *scene, Args&&... args) { return std::unique_ptr(createItem(scene, std::forward(args)...)); } // In general, we want chart items to be hideable. For example to show/hide // labels on demand. Very sadly, the QSG API is absolutely terrible with // respect to temporarily disabling. Instead of simply having a flag, // a QSGNode is queried using the "isSubtreeBlocked()" virtual function(!). // // Not only is this a slow operation performed on every single node, it // also is often not possible to override this function: For improved // performance, the documentation recommends to create QSG nodes via // QQuickWindow. This provides nodes optimized for the actual hardware. // However, this obviously means that these nodes cannot be derived from! // // In that case, there are two possibilities: Add a proxy node with an // overridden "isSubtreeBlocked()" function or remove the node from the // scene. The former was chosen here, because it is less complex. // // The following slightly cryptic templates are used to unify the two // cases: The QSGNode is generated by our own code or the QSGNode is // obtained from QQuickWindow. // // The "HideableQSGNode" template augments the QSGNode "Node" // by a "setVisible()" function and overrides "isSubtreeBlocked()" // // The "QSGProxyNode" template is a QSGNode with a single // child of type "Node". // // Thus, if the node can be created, use: // HideableQSGNode node // and if the node can only be obtained from QQuickWindow, use: // HideableQSGNode> node // The latter should obviously be typedef-ed. // // Yes, that's all horrible, but if nothing else it teaches us about // composition. template class HideableQSGNode : public Node { bool hidden; bool isSubtreeBlocked() const override final; public: template HideableQSGNode(bool visible, Args&&... args); void setVisible(bool visible); }; template class QSGProxyNode : public QSGNode { public: std::unique_ptr node; QSGProxyNode(Node *node); }; // Implementation detail of templates - move to serparate header file template QSGProxyNode::QSGProxyNode(Node *node) : node(node) { appendChildNode(node); } template bool HideableQSGNode::isSubtreeBlocked() const { return hidden; } template template HideableQSGNode::HideableQSGNode(bool visible, Args&&... args) : Node(std::forward(args)...), hidden(!visible) { } template void HideableQSGNode::setVisible(bool visible) { hidden = !visible; } #endif