mirror of
https://github.com/subsurface/subsurface.git
synced 2025-02-19 22:16:15 +00:00
statistics: add notion of Z-value to chart items
The chart items were drawn in order of creation. To control this, add a notion of Z-value. In contrast to QGraphicsScene, make this a small integer value. To controll order of drawing, a plain QSGNode is created for every possible Z-Value and items are added to these nodes. Thus, items are rendered by Z-value and if the Z-value is equal by order of creation. Likewise split the list of chart-items into Z-values, so that items can be quickly unregistered: The items that will be removed individually will usuall be part of Z-levels with only few items (e.g. legend, infobox). Z-levels with many items (notably the series) will always be fully rebuilt. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
parent
785d5189f6
commit
e1c0cace95
7 changed files with 82 additions and 31 deletions
|
@ -80,17 +80,33 @@ void StatsView::mouseReleaseEvent(QMouseEvent *)
|
|||
}
|
||||
}
|
||||
|
||||
class RootNode : public QSGNode
|
||||
{
|
||||
public:
|
||||
RootNode();
|
||||
QSGImageNode *imageNode; // imageNode to plot QGRaphicsScene on. Remove in due course.
|
||||
// We entertain one node per Z-level.
|
||||
std::array<QSGNode *, (size_t)ChartZValue::Count> zNodes;
|
||||
std::array<std::vector<ChartItem *>, (size_t)ChartZValue::Count> items;
|
||||
};
|
||||
|
||||
RootNode::RootNode()
|
||||
{
|
||||
for (QSGNode *&zNode: zNodes) {
|
||||
zNode = new QSGNode;
|
||||
appendChildNode(zNode);
|
||||
}
|
||||
}
|
||||
|
||||
QSGNode *StatsView::updatePaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNodeData *)
|
||||
{
|
||||
// The QtQuick drawing interface is utterly bizzare with a distinct 1980ies-style memory management.
|
||||
// This is just a copy of what is found in Qt's documentation.
|
||||
QSGImageNode *n = static_cast<QSGImageNode *>(oldNode);
|
||||
if (!n)
|
||||
n = rootNode = window()->createImageNode();
|
||||
|
||||
for (ChartItem *item: items) {
|
||||
if (item->dirty)
|
||||
item->render();
|
||||
RootNode *n = static_cast<RootNode *>(oldNode);
|
||||
if (!n) {
|
||||
n = rootNode = new RootNode;
|
||||
n->imageNode = window()->createImageNode();
|
||||
n->zNodes[(int)ChartZValue::Series]->appendChildNode(n->imageNode);
|
||||
}
|
||||
|
||||
QRectF rect = boundingRect();
|
||||
|
@ -99,28 +115,43 @@ QSGNode *StatsView::updatePaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNod
|
|||
plotAreaChanged(plotRect.size());
|
||||
}
|
||||
|
||||
for (auto &v: n->items) {
|
||||
for (ChartItem *item: v) {
|
||||
if (item->dirty)
|
||||
item->render();
|
||||
}
|
||||
}
|
||||
|
||||
img->fill(backgroundColor);
|
||||
scene.render(painter.get());
|
||||
texture.reset(window()->createTextureFromImage(*img, QQuickWindow::TextureIsOpaque));
|
||||
n->setTexture(texture.get());
|
||||
n->setRect(rect);
|
||||
n->imageNode->setTexture(texture.get());
|
||||
n->imageNode->setRect(rect);
|
||||
return n;
|
||||
}
|
||||
|
||||
void StatsView::addQSGNode(QSGNode *node, int)
|
||||
void StatsView::addQSGNode(QSGNode *node, ChartZValue z)
|
||||
{
|
||||
rootNode->appendChildNode(node);
|
||||
int idx = std::clamp((int)z, 0, (int)ChartZValue::Count - 1);
|
||||
rootNode->zNodes[idx]->appendChildNode(node);
|
||||
}
|
||||
|
||||
// Currently this does an inefficient linear search in the chart-item vector.
|
||||
// The reason is that removing individual chart items is very rare: for now,
|
||||
// it is only done when hiding an InfoBox. In the future, this might have to
|
||||
// be improved.
|
||||
// However, we entertain one vector of items per Z-value and currently
|
||||
// only the infobox is explicitly deleted, which has a unique Z-value.
|
||||
void StatsView::unregisterChartItem(const ChartItem *item)
|
||||
{
|
||||
auto it = std::find(items.begin(), items.end(), item);
|
||||
if (it != items.end())
|
||||
items.erase(it);
|
||||
int idx = std::clamp((int)item->zValue, 0, (int)ChartZValue::Count - 1);
|
||||
std::vector<ChartItem *> &v = rootNode->items[idx];
|
||||
auto it = std::find(v.begin(), v.end(), item);
|
||||
if (it != v.end())
|
||||
v.erase(it);
|
||||
}
|
||||
|
||||
void StatsView::registerChartItem(ChartItem *item)
|
||||
{
|
||||
int idx = std::clamp((int)item->zValue, 0, (int)ChartZValue::Count - 1);
|
||||
rootNode->items[idx].push_back(item);
|
||||
}
|
||||
|
||||
QQuickWindow *StatsView::w() const
|
||||
|
@ -292,7 +323,10 @@ void StatsView::reset()
|
|||
highlightedSeries = nullptr;
|
||||
xAxis = yAxis = nullptr;
|
||||
draggedItem = nullptr;
|
||||
items.clear(); // non-owning pointers
|
||||
if (rootNode) {
|
||||
for (auto &v: rootNode->items)
|
||||
v.clear(); // non-owning pointers
|
||||
}
|
||||
legend.reset();
|
||||
series.clear();
|
||||
quartileMarkers.clear();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue