stats: make number of z-levels dynamic

Other users of the qtquick code might have different needs
for z-levels.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
Berthold Stoeger 2023-04-16 12:59:19 +02:00
parent 4c43764b36
commit 533cff96f3
5 changed files with 50 additions and 44 deletions

View file

@ -19,7 +19,7 @@ static int round_up(double f)
return static_cast<int>(ceil(f));
}
ChartItem::ChartItem(StatsView &v, ChartZValue z) :
ChartItem::ChartItem(StatsView &v, size_t z) :
dirty(false), prev(nullptr), next(nullptr),
zValue(z), view(v)
{
@ -42,7 +42,7 @@ void ChartItem::markDirty()
view.registerDirtyChartItem(*this);
}
ChartPixmapItem::ChartPixmapItem(StatsView &v, ChartZValue z) : HideableChartItem(v, z),
ChartPixmapItem::ChartPixmapItem(StatsView &v, size_t z) : HideableChartItem(v, z),
positionDirty(false), textureDirty(false)
{
}
@ -111,7 +111,7 @@ QRectF ChartPixmapItem::getRect() const
static const int scatterItemDiameter = 10;
static const int scatterItemBorder = 1;
ChartScatterItem::ChartScatterItem(StatsView &v, ChartZValue z, const StatsTheme &theme, bool selected) : HideableChartItem(v, z),
ChartScatterItem::ChartScatterItem(StatsView &v, size_t z, const StatsTheme &theme, bool selected) : HideableChartItem(v, z),
theme(theme),
positionDirty(false), textureDirty(false),
highlight(selected ? Highlight::Selected : Highlight::Unselected)
@ -214,7 +214,7 @@ QRectF ChartScatterItem::getRect() const
return rect;
}
ChartRectItem::ChartRectItem(StatsView &v, ChartZValue z,
ChartRectItem::ChartRectItem(StatsView &v, size_t z,
const QPen &pen, const QBrush &brush, double radius) : ChartPixmapItem(v, z),
pen(pen), brush(brush), radius(radius)
{
@ -236,7 +236,7 @@ void ChartRectItem::resize(QSizeF size)
painter->drawRoundedRect(rect, radius, radius, Qt::AbsoluteSize);
}
ChartTextItem::ChartTextItem(StatsView &v, ChartZValue z, const QFont &f, const std::vector<QString> &text, bool center) :
ChartTextItem::ChartTextItem(StatsView &v, size_t z, const QFont &f, const std::vector<QString> &text, bool center) :
ChartPixmapItem(v, z), f(f), center(center)
{
QFontMetrics fm(f);
@ -254,7 +254,7 @@ ChartTextItem::ChartTextItem(StatsView &v, ChartZValue z, const QFont &f, const
resize(QSizeF(totalWidth, totalHeight));
}
ChartTextItem::ChartTextItem(StatsView &v, ChartZValue z, const QFont &f, const QString &text) :
ChartTextItem::ChartTextItem(StatsView &v, size_t z, const QFont &f, const QString &text) :
ChartTextItem(v, z, f, std::vector<QString>({ text }), true)
{
}
@ -280,7 +280,7 @@ void ChartTextItem::setColor(const QColor &c, const QColor &background)
setTextureDirty();
}
ChartPieItem::ChartPieItem(StatsView &v, ChartZValue z, const StatsTheme &theme, double borderWidth) : ChartPixmapItem(v, z),
ChartPieItem::ChartPieItem(StatsView &v, size_t z, const StatsTheme &theme, double borderWidth) : ChartPixmapItem(v, z),
theme(theme),
borderWidth(borderWidth)
{
@ -322,7 +322,7 @@ void ChartPieItem::resize(QSizeF size)
img->fill(Qt::transparent);
}
ChartLineItemBase::ChartLineItemBase(StatsView &v, ChartZValue z, QColor color, double width) : HideableChartItem(v, z),
ChartLineItemBase::ChartLineItemBase(StatsView &v, size_t z, QColor color, double width) : HideableChartItem(v, z),
color(color), width(width), positionDirty(false), materialDirty(false)
{
}
@ -416,7 +416,7 @@ void ChartRectLineItem::render()
positionDirty = materialDirty = false;
}
ChartBarItem::ChartBarItem(StatsView &v, ChartZValue z, const StatsTheme &theme, double borderWidth) : HideableChartItem(v, z),
ChartBarItem::ChartBarItem(StatsView &v, size_t z, const StatsTheme &theme, double borderWidth) : HideableChartItem(v, z),
theme(theme),
borderWidth(borderWidth), selected(false),
positionDirty(false), colorDirty(false), selectedDirty(false)
@ -548,7 +548,7 @@ QRectF ChartBarItem::getRect() const
return rect;
}
ChartBoxItem::ChartBoxItem(StatsView &v, ChartZValue z, const StatsTheme &theme, double borderWidth) :
ChartBoxItem::ChartBoxItem(StatsView &v, size_t z, const StatsTheme &theme, double borderWidth) :
ChartBarItem(v, z, theme, borderWidth)
{
}

View file

@ -18,7 +18,6 @@ class QSGTexture;
class QSGTextureMaterial;
class StatsTheme;
class StatsView;
enum class ChartZValue : int;
class ChartItem {
public:
@ -26,10 +25,10 @@ public:
virtual void render() = 0;
bool dirty; // If true, call render() when rebuilding the scene
ChartItem *prev, *next; // Double linked list of items
const ChartZValue zValue;
const size_t zValue;
virtual ~ChartItem(); // Attention: must only be called by render thread.
protected:
ChartItem(StatsView &v, ChartZValue z);
ChartItem(StatsView &v, size_t z);
QSizeF sceneSize() const;
StatsView &view;
void markDirty();
@ -38,7 +37,7 @@ protected:
template <typename Node>
class HideableChartItem : public ChartItem {
protected:
HideableChartItem(StatsView &v, ChartZValue z);
HideableChartItem(StatsView &v, size_t z);
std::unique_ptr<Node> node;
bool visible;
bool visibleChanged;
@ -56,7 +55,7 @@ using HideableChartProxyItem = HideableChartItem<HideableQSGNode<QSGProxyNode<No
// A chart item that blits a precalculated pixmap onto the scene.
class ChartPixmapItem : public HideableChartProxyItem<QSGImageNode> {
public:
ChartPixmapItem(StatsView &v, ChartZValue z);
ChartPixmapItem(StatsView &v, size_t z);
~ChartPixmapItem();
void setPos(QPointF pos);
@ -78,7 +77,7 @@ private:
// Draw a rectangular background after resize. Children are responsible for calling update().
class ChartRectItem : public ChartPixmapItem {
public:
ChartRectItem(StatsView &v, ChartZValue z, const QPen &pen, const QBrush &brush, double radius);
ChartRectItem(StatsView &v, size_t z, const QPen &pen, const QBrush &brush, double radius);
~ChartRectItem();
void resize(QSizeF size);
private:
@ -90,8 +89,8 @@ private:
// Attention: text is only drawn after calling setColor()!
class ChartTextItem : public ChartPixmapItem {
public:
ChartTextItem(StatsView &v, ChartZValue z, const QFont &f, const std::vector<QString> &text, bool center);
ChartTextItem(StatsView &v, ChartZValue z, const QFont &f, const QString &text);
ChartTextItem(StatsView &v, size_t z, const QFont &f, const std::vector<QString> &text, bool center);
ChartTextItem(StatsView &v, size_t z, const QFont &f, const QString &text);
void setColor(const QColor &color); // Draw on transparent background
void setColor(const QColor &color, const QColor &background); // Fill rectangle with given background color
private:
@ -108,7 +107,7 @@ private:
// A pie chart item: draws disk segments onto a pixmap.
class ChartPieItem : public ChartPixmapItem {
public:
ChartPieItem(StatsView &v, ChartZValue z, const StatsTheme &theme, double borderWidth);
ChartPieItem(StatsView &v, size_t z, const StatsTheme &theme, double borderWidth);
void drawSegment(double from, double to, QColor fill, QColor border, bool selected); // from and to are relative (0-1 is full disk).
void resize(QSizeF size); // As in base class, but clears the canvas
private:
@ -119,7 +118,7 @@ private:
// Common data for line and rect items. Both are represented by two points.
class ChartLineItemBase : public HideableChartItem<HideableQSGNode<QSGGeometryNode>> {
public:
ChartLineItemBase(StatsView &v, ChartZValue z, QColor color, double width);
ChartLineItemBase(StatsView &v, size_t z, QColor color, double width);
~ChartLineItemBase();
void setLine(QPointF from, QPointF to);
protected:
@ -148,7 +147,7 @@ public:
// A bar in a bar chart: a rectangle bordered by lines.
class ChartBarItem : public HideableChartProxyItem<QSGRectangleNode> {
public:
ChartBarItem(StatsView &v, ChartZValue z, const StatsTheme &theme, double borderWidth);
ChartBarItem(StatsView &v, size_t z, const StatsTheme &theme, double borderWidth);
~ChartBarItem();
void setColor(QColor color, QColor borderColor);
void setRect(const QRectF &rect);
@ -178,7 +177,7 @@ private:
// A box-and-whiskers item. This is a bit lazy: derive from the bar item and add whiskers.
class ChartBoxItem : public ChartBarItem {
public:
ChartBoxItem(StatsView &v, ChartZValue z, const StatsTheme &theme, double borderWidth);
ChartBoxItem(StatsView &v, size_t z, const StatsTheme &theme, double borderWidth);
~ChartBoxItem();
void setBox(const QRectF &rect, double min, double max, double median); // The rect describes Q1, Q3.
QRectF getRect() const; // Note: this extends the center rectangle to include the whiskers.
@ -196,7 +195,7 @@ private:
// scatter item here, but so it is for now.
class ChartScatterItem : public HideableChartProxyItem<QSGImageNode> {
public:
ChartScatterItem(StatsView &v, ChartZValue z, const StatsTheme &theme, bool selected);
ChartScatterItem(StatsView &v, size_t z, const StatsTheme &theme, bool selected);
~ChartScatterItem();
// Currently, there is no highlighted and selected status.
@ -240,7 +239,7 @@ void HideableChartItem<Node>::createNode(Args&&... args)
}
template <typename Node>
HideableChartItem<Node>::HideableChartItem(StatsView &v, ChartZValue z) : ChartItem(v, z),
HideableChartItem<Node>::HideableChartItem(StatsView &v, size_t z) : ChartItem(v, z),
visible(true), visibleChanged(false)
{
}

View file

@ -21,7 +21,6 @@
#include "core/selection.h"
#include "core/trip.h"
#include <array> // for std::array
#include <cmath>
#include <QQuickItem>
#include <QQuickWindow>
@ -35,6 +34,7 @@ static const double titleBorder = 2.0; // Border between title and chart
static const double selectionLassoWidth = 2.0; // Border between title and chart
StatsView::StatsView(QQuickItem *parent) : QQuickItem(parent),
maxZ(ChartZValue::Count),
backgroundDirty(true),
currentTheme(&getStatsTheme(false)),
backgroundColor(currentTheme->backgroundColor),
@ -129,16 +129,18 @@ using ZNode = HideableQSGNode<QSGNode>;
class RootNode : public QSGNode
{
public:
RootNode(StatsView &view, QColor backgroundColor);
RootNode(StatsView &view, QColor backgroundColor, size_t maxZ);
~RootNode();
StatsView &view;
std::unique_ptr<QSGRectangleNode> backgroundNode; // solid background
// We entertain one node per Z-level.
std::array<std::unique_ptr<ZNode>, (size_t)ChartZValue::Count> zNodes;
std::vector<std::unique_ptr<ZNode>> zNodes;
};
RootNode::RootNode(StatsView &view, QColor backgroundColor) : view(view)
RootNode::RootNode(StatsView &view, QColor backgroundColor, size_t maxZ) : view(view)
{
zNodes.resize(maxZ);
// Add a background rectangle with a solid color. This could
// also be done on the widget level, but would have to be done
// separately for desktop and mobile, so do it here.
@ -172,7 +174,7 @@ QSGNode *StatsView::updatePaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNod
// This is just a copy of what is found in Qt's documentation.
RootNode *n = static_cast<RootNode *>(oldNode);
if (!n)
n = rootNode = new RootNode(*this, backgroundColor);
n = rootNode = new RootNode(*this, backgroundColor, maxZ);
// Delete all chart items that are marked for deletion.
freeDeletedChartItems();
@ -217,9 +219,9 @@ void StatsView::emergencyShutdown()
rootNode = nullptr;
}
void StatsView::addQSGNode(QSGNode *node, ChartZValue z)
void StatsView::addQSGNode(QSGNode *node, size_t z)
{
int idx = std::clamp((int)z, 0, (int)ChartZValue::Count - 1);
size_t idx = std::clamp(z, (size_t)0, maxZ);
rootNode->zNodes[idx]->appendChildNode(node);
}
@ -617,7 +619,7 @@ void StatsView::updateFeatures()
// For labels, we are brutal: simply show/hide the whole z-level with the labels
if (rootNode)
rootNode->zNodes[(int)ChartZValue::SeriesLabels]->setVisible(state.labels);
rootNode->zNodes[ChartZValue::SeriesLabels]->setVisible(state.labels);
if (meanMarker)
meanMarker->setVisible(state.mean);

View file

@ -34,7 +34,6 @@ class QSGTexture;
class RootNode; // Internal implementation detail
enum class ChartSubType : int;
enum class ChartZValue : int;
enum class StatsOperation : int;
enum class ChartSortMode : int;
@ -56,7 +55,7 @@ public:
void setBackgroundColor(QColor color); // Chart must be replot for color to become effective.
void setTheme(bool dark); // Chart must be replot for theme to become effective.
const StatsTheme &getCurrentTheme() const;
void addQSGNode(QSGNode *node, ChartZValue z); // Must only be called in render thread!
void addQSGNode(QSGNode *node, size_t z); // Must only be called in render thread!
void registerChartItem(ChartItem &item);
void registerDirtyChartItem(ChartItem &item);
void emergencyShutdown(); // Called when QQuick decides to delete our root node.
@ -76,6 +75,7 @@ private slots:
void divesSelected(const QVector<dive *> &dives);
private:
// QtQuick related things
size_t maxZ;
bool backgroundDirty;
QRectF plotRect;
QSGNode *updatePaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNodeData *updatePaintNodeData) override;

View file

@ -5,7 +5,11 @@
// drawn in order of addition to the scene.
#ifndef ZVALUES_H
enum class ChartZValue {
// Encapsulating an enum in a struct is stupid, but allows us
// to not poison the namespace and yet autoconvert to int
// (in constrast to enum class). enum is so broken!
struct ChartZValue {
enum ZValues {
Grid = 0,
Series,
Axes,
@ -15,6 +19,7 @@ enum class ChartZValue {
InformationBox,
Legend,
Count
};
};
#endif