stats: don't pass StatsTheme in ChartItem::render

To make the qt-quick code of the statistics module more general,
don't pass the StatsTheme in render calls to ChartItems. Items
that need it, may just store a reference to the theme.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
Berthold Stoeger 2023-04-16 12:19:56 +02:00
parent 7aefd704c2
commit 4c43764b36
8 changed files with 46 additions and 40 deletions

View file

@ -266,7 +266,7 @@ std::vector<BarSeries::SubItem> BarSeries::makeSubItems(std::vector<SubItemDesc>
for (auto &[v, dives, label]: items) { for (auto &[v, dives, label]: items) {
if (v > 0.0) { if (v > 0.0) {
bool selected = allDivesSelected(dives); bool selected = allDivesSelected(dives);
res.push_back({ view.createChartItem<ChartBarItem>(ChartZValue::Series, barBorderWidth), res.push_back({ view.createChartItem<ChartBarItem>(ChartZValue::Series, theme, barBorderWidth),
std::move(dives), std::move(dives),
{}, from, from + v, bin_nr, selected }); {}, from, from + v, bin_nr, selected });
if (!label.empty()) if (!label.empty())

View file

@ -32,7 +32,7 @@ BoxSeries::Item::Item(StatsView &view, BoxSeries *series, double lowerBound, dou
binName(binName), binName(binName),
selected(allDivesSelected(q.dives)) selected(allDivesSelected(q.dives))
{ {
item = view.createChartItem<ChartBoxItem>(ChartZValue::Series, boxBorderWidth); item = view.createChartItem<ChartBoxItem>(ChartZValue::Series, theme, boxBorderWidth);
highlight(false, theme); highlight(false, theme);
updatePosition(series); updatePosition(series);
} }

View file

@ -64,7 +64,7 @@ void ChartPixmapItem::setPositionDirty()
markDirty(); markDirty();
} }
void ChartPixmapItem::render(const StatsTheme &) void ChartPixmapItem::render()
{ {
if (!node) { if (!node) {
createNode(view.w()->createImageNode()); createNode(view.w()->createImageNode());
@ -111,7 +111,8 @@ QRectF ChartPixmapItem::getRect() const
static const int scatterItemDiameter = 10; static const int scatterItemDiameter = 10;
static const int scatterItemBorder = 1; static const int scatterItemBorder = 1;
ChartScatterItem::ChartScatterItem(StatsView &v, ChartZValue z, bool selected) : HideableChartItem(v, z), ChartScatterItem::ChartScatterItem(StatsView &v, ChartZValue z, const StatsTheme &theme, bool selected) : HideableChartItem(v, z),
theme(theme),
positionDirty(false), textureDirty(false), positionDirty(false), textureDirty(false),
highlight(selected ? Highlight::Selected : Highlight::Unselected) highlight(selected ? Highlight::Selected : Highlight::Unselected)
{ {
@ -138,7 +139,7 @@ static QSGTexture *createScatterTexture(StatsView &view, const QColor &color, co
return view.w()->createTextureFromImage(img, QQuickWindow::TextureHasAlphaChannel); return view.w()->createTextureFromImage(img, QQuickWindow::TextureHasAlphaChannel);
} }
QSGTexture *ChartScatterItem::getTexture(const StatsTheme &theme) const QSGTexture *ChartScatterItem::getTexture() const
{ {
switch (highlight) { switch (highlight) {
default: default:
@ -151,7 +152,7 @@ QSGTexture *ChartScatterItem::getTexture(const StatsTheme &theme) const
} }
} }
void ChartScatterItem::render(const StatsTheme &theme) void ChartScatterItem::render()
{ {
if (!theme.scatterItemTexture) { if (!theme.scatterItemTexture) {
theme.scatterItemTexture = register_global(createScatterTexture(view, theme.fillColor, theme.borderColor)); theme.scatterItemTexture = register_global(createScatterTexture(view, theme.fillColor, theme.borderColor));
@ -165,7 +166,7 @@ void ChartScatterItem::render(const StatsTheme &theme)
} }
updateVisible(); updateVisible();
if (textureDirty) { if (textureDirty) {
node->node->setTexture(getTexture(theme)); node->node->setTexture(getTexture());
textureDirty = false; textureDirty = false;
} }
if (positionDirty) { if (positionDirty) {
@ -279,7 +280,8 @@ void ChartTextItem::setColor(const QColor &c, const QColor &background)
setTextureDirty(); setTextureDirty();
} }
ChartPieItem::ChartPieItem(StatsView &v, ChartZValue z, double borderWidth) : ChartPixmapItem(v, z), ChartPieItem::ChartPieItem(StatsView &v, ChartZValue z, const StatsTheme &theme, double borderWidth) : ChartPixmapItem(v, z),
theme(theme),
borderWidth(borderWidth) borderWidth(borderWidth)
{ {
} }
@ -300,7 +302,7 @@ static QBrush makeBrush(QColor fill, bool selected, const StatsTheme &theme)
return QBrush(img); return QBrush(img);
} }
void ChartPieItem::drawSegment(double from, double to, QColor fill, QColor border, bool selected, const StatsTheme &theme) void ChartPieItem::drawSegment(double from, double to, QColor fill, QColor border, bool selected)
{ {
painter->setPen(QPen(border, borderWidth)); painter->setPen(QPen(border, borderWidth));
painter->setBrush(makeBrush(fill, selected, theme)); painter->setBrush(makeBrush(fill, selected, theme));
@ -349,7 +351,7 @@ void setPoint(QSGGeometry::TexturedPoint2D &v, const QPointF &p, const QPointF &
static_cast<float>(t.x()), static_cast<float>(t.y())); static_cast<float>(t.x()), static_cast<float>(t.y()));
} }
void ChartLineItem::render(const StatsTheme &) void ChartLineItem::render()
{ {
if (!node) { if (!node) {
geometry.reset(new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), 2)); geometry.reset(new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), 2));
@ -380,7 +382,7 @@ void ChartLineItem::render(const StatsTheme &)
positionDirty = materialDirty = false; positionDirty = materialDirty = false;
} }
void ChartRectLineItem::render(const StatsTheme &) void ChartRectLineItem::render()
{ {
if (!node) { if (!node) {
geometry.reset(new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), 5)); geometry.reset(new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), 5));
@ -414,7 +416,8 @@ void ChartRectLineItem::render(const StatsTheme &)
positionDirty = materialDirty = false; positionDirty = materialDirty = false;
} }
ChartBarItem::ChartBarItem(StatsView &v, ChartZValue z, double borderWidth) : HideableChartItem(v, z), ChartBarItem::ChartBarItem(StatsView &v, ChartZValue z, const StatsTheme &theme, double borderWidth) : HideableChartItem(v, z),
theme(theme),
borderWidth(borderWidth), selected(false), borderWidth(borderWidth), selected(false),
positionDirty(false), colorDirty(false), selectedDirty(false) positionDirty(false), colorDirty(false), selectedDirty(false)
{ {
@ -424,7 +427,7 @@ ChartBarItem::~ChartBarItem()
{ {
} }
QSGTexture *ChartBarItem::getSelectedTexture(const StatsTheme &theme) const QSGTexture *ChartBarItem::getSelectedTexture() const
{ {
if (!theme.selectedTexture) { if (!theme.selectedTexture) {
QImage img(2, 2, QImage::Format_ARGB32); QImage img(2, 2, QImage::Format_ARGB32);
@ -436,7 +439,7 @@ QSGTexture *ChartBarItem::getSelectedTexture(const StatsTheme &theme) const
return theme.selectedTexture; return theme.selectedTexture;
} }
void ChartBarItem::render(const StatsTheme &theme) void ChartBarItem::render()
{ {
if (!node) { if (!node) {
createNode(view.w()->createRectangleNode()); createNode(view.w()->createRectangleNode());
@ -481,7 +484,7 @@ void ChartBarItem::render(const StatsTheme &theme)
selectionGeometry.reset(new QSGGeometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4)); selectionGeometry.reset(new QSGGeometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4));
selectionGeometry->setDrawingMode(QSGGeometry::DrawTriangleStrip); selectionGeometry->setDrawingMode(QSGGeometry::DrawTriangleStrip);
selectionMaterial.reset(new QSGTextureMaterial); selectionMaterial.reset(new QSGTextureMaterial);
selectionMaterial->setTexture(getSelectedTexture(theme)); selectionMaterial->setTexture(getSelectedTexture());
selectionMaterial->setHorizontalWrapMode(QSGTexture::Repeat); selectionMaterial->setHorizontalWrapMode(QSGTexture::Repeat);
selectionMaterial->setVerticalWrapMode(QSGTexture::Repeat); selectionMaterial->setVerticalWrapMode(QSGTexture::Repeat);
selectionNode.reset(new QSGGeometryNode); selectionNode.reset(new QSGGeometryNode);
@ -545,8 +548,8 @@ QRectF ChartBarItem::getRect() const
return rect; return rect;
} }
ChartBoxItem::ChartBoxItem(StatsView &v, ChartZValue z, double borderWidth) : ChartBoxItem::ChartBoxItem(StatsView &v, ChartZValue z, const StatsTheme &theme, double borderWidth) :
ChartBarItem(v, z, borderWidth) ChartBarItem(v, z, theme, borderWidth)
{ {
} }
@ -554,12 +557,12 @@ ChartBoxItem::~ChartBoxItem()
{ {
} }
void ChartBoxItem::render(const StatsTheme &theme) void ChartBoxItem::render()
{ {
// Remember old dirty values, since ChartBarItem::render() will clear them // Remember old dirty values, since ChartBarItem::render() will clear them
bool oldPositionDirty = positionDirty; bool oldPositionDirty = positionDirty;
bool oldColorDirty = colorDirty; bool oldColorDirty = colorDirty;
ChartBarItem::render(theme); // This will create the base node, so no need to check for that. ChartBarItem::render(); // This will create the base node, so no need to check for that.
if (!whiskersNode) { if (!whiskersNode) {
whiskersGeometry.reset(new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), 10)); whiskersGeometry.reset(new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), 10));
whiskersGeometry->setDrawingMode(QSGGeometry::DrawLines); whiskersGeometry->setDrawingMode(QSGGeometry::DrawLines);

View file

@ -23,7 +23,7 @@ enum class ChartZValue : int;
class ChartItem { class ChartItem {
public: public:
// Only call on render thread! // Only call on render thread!
virtual void render(const StatsTheme &theme) = 0; virtual void render() = 0;
bool dirty; // If true, call render() when rebuilding the scene bool dirty; // If true, call render() when rebuilding the scene
ChartItem *prev, *next; // Double linked list of items ChartItem *prev, *next; // Double linked list of items
const ChartZValue zValue; const ChartZValue zValue;
@ -60,7 +60,7 @@ public:
~ChartPixmapItem(); ~ChartPixmapItem();
void setPos(QPointF pos); void setPos(QPointF pos);
void render(const StatsTheme &theme) override; void render() override;
QRectF getRect() const; QRectF getRect() const;
protected: protected:
void resize(QSizeF size); // Resets the canvas. Attention: image is *unitialized*. void resize(QSizeF size); // Resets the canvas. Attention: image is *unitialized*.
@ -108,10 +108,11 @@ private:
// A pie chart item: draws disk segments onto a pixmap. // A pie chart item: draws disk segments onto a pixmap.
class ChartPieItem : public ChartPixmapItem { class ChartPieItem : public ChartPixmapItem {
public: public:
ChartPieItem(StatsView &v, ChartZValue z, double borderWidth); ChartPieItem(StatsView &v, ChartZValue z, const StatsTheme &theme, double borderWidth);
void drawSegment(double from, double to, QColor fill, QColor border, bool selected, const StatsTheme &theme); // from and to are relative (0-1 is full disk). 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 void resize(QSizeF size); // As in base class, but clears the canvas
private: private:
const StatsTheme &theme;
double borderWidth; double borderWidth;
}; };
@ -134,27 +135,28 @@ protected:
class ChartLineItem : public ChartLineItemBase { class ChartLineItem : public ChartLineItemBase {
public: public:
using ChartLineItemBase::ChartLineItemBase; using ChartLineItemBase::ChartLineItemBase;
void render(const StatsTheme &theme) override; void render() override;
}; };
// A simple rectangle without fill. Specified by any two opposing vertices. // A simple rectangle without fill. Specified by any two opposing vertices.
class ChartRectLineItem : public ChartLineItemBase { class ChartRectLineItem : public ChartLineItemBase {
public: public:
using ChartLineItemBase::ChartLineItemBase; using ChartLineItemBase::ChartLineItemBase;
void render(const StatsTheme &theme) override; void render() override;
}; };
// A bar in a bar chart: a rectangle bordered by lines. // A bar in a bar chart: a rectangle bordered by lines.
class ChartBarItem : public HideableChartProxyItem<QSGRectangleNode> { class ChartBarItem : public HideableChartProxyItem<QSGRectangleNode> {
public: public:
ChartBarItem(StatsView &v, ChartZValue z, double borderWidth); ChartBarItem(StatsView &v, ChartZValue z, const StatsTheme &theme, double borderWidth);
~ChartBarItem(); ~ChartBarItem();
void setColor(QColor color, QColor borderColor); void setColor(QColor color, QColor borderColor);
void setRect(const QRectF &rect); void setRect(const QRectF &rect);
void setSelected(bool selected); void setSelected(bool selected);
QRectF getRect() const; QRectF getRect() const;
void render(const StatsTheme &theme) override; void render() override;
protected: protected:
const StatsTheme &theme;
QColor color, borderColor; QColor color, borderColor;
double borderWidth; double borderWidth;
QRectF rect; QRectF rect;
@ -170,17 +172,17 @@ private:
std::unique_ptr<QSGGeometryNode> selectionNode; std::unique_ptr<QSGGeometryNode> selectionNode;
std::unique_ptr<QSGTextureMaterial> selectionMaterial; std::unique_ptr<QSGTextureMaterial> selectionMaterial;
std::unique_ptr<QSGGeometry> selectionGeometry; std::unique_ptr<QSGGeometry> selectionGeometry;
QSGTexture *getSelectedTexture(const StatsTheme &theme) const; QSGTexture *getSelectedTexture() const;
}; };
// A box-and-whiskers item. This is a bit lazy: derive from the bar item and add whiskers. // A box-and-whiskers item. This is a bit lazy: derive from the bar item and add whiskers.
class ChartBoxItem : public ChartBarItem { class ChartBoxItem : public ChartBarItem {
public: public:
ChartBoxItem(StatsView &v, ChartZValue z, double borderWidth); ChartBoxItem(StatsView &v, ChartZValue z, const StatsTheme &theme, double borderWidth);
~ChartBoxItem(); ~ChartBoxItem();
void setBox(const QRectF &rect, double min, double max, double median); // The rect describes Q1, Q3. 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. QRectF getRect() const; // Note: this extends the center rectangle to include the whiskers.
void render(const StatsTheme &theme) override; void render() override;
private: private:
double min, max, median; double min, max, median;
std::unique_ptr<QSGGeometryNode> whiskersNode; std::unique_ptr<QSGGeometryNode> whiskersNode;
@ -194,7 +196,7 @@ private:
// scatter item here, but so it is for now. // scatter item here, but so it is for now.
class ChartScatterItem : public HideableChartProxyItem<QSGImageNode> { class ChartScatterItem : public HideableChartProxyItem<QSGImageNode> {
public: public:
ChartScatterItem(StatsView &v, ChartZValue z, bool selected); ChartScatterItem(StatsView &v, ChartZValue z, const StatsTheme &theme, bool selected);
~ChartScatterItem(); ~ChartScatterItem();
// Currently, there is no highlighted and selected status. // Currently, there is no highlighted and selected status.
@ -205,12 +207,13 @@ public:
}; };
void setPos(QPointF pos); // Specifies the *center* of the item. void setPos(QPointF pos); // Specifies the *center* of the item.
void setHighlight(Highlight highlight); // In the future, support different kinds of scatter items. void setHighlight(Highlight highlight); // In the future, support different kinds of scatter items.
void render(const StatsTheme &theme) override; void render() override;
QRectF getRect() const; QRectF getRect() const;
bool contains(QPointF point) const; bool contains(QPointF point) const;
bool inRect(const QRectF &rect) const; bool inRect(const QRectF &rect) const;
private: private:
QSGTexture *getTexture(const StatsTheme &theme) const; const StatsTheme &theme;
QSGTexture *getTexture() const;
QRectF rect; QRectF rect;
QSizeF textureSize; QSizeF textureSize;
bool positionDirty, textureDirty; bool positionDirty, textureDirty;

View file

@ -78,13 +78,13 @@ void PieSeries::Item::highlight(ChartPieItem &item, int bin_nr, bool highlight,
QColor border = highlight ? theme.highlightedBorderColor : theme.borderColor; QColor border = highlight ? theme.highlightedBorderColor : theme.borderColor;
if (innerLabel) if (innerLabel)
innerLabel->setColor(highlight ? theme.darkLabelColor : theme.labelColor(bin_nr, numBins), fill); innerLabel->setColor(highlight ? theme.darkLabelColor : theme.labelColor(bin_nr, numBins), fill);
item.drawSegment(angleFrom, angleTo, fill, border, selected, theme); item.drawSegment(angleFrom, angleTo, fill, border, selected);
} }
PieSeries::PieSeries(StatsView &view, StatsAxis *xAxis, StatsAxis *yAxis, const QString &categoryName, PieSeries::PieSeries(StatsView &view, StatsAxis *xAxis, StatsAxis *yAxis, const QString &categoryName,
std::vector<std::pair<QString, std::vector<dive *>>> data, ChartSortMode sortMode) : std::vector<std::pair<QString, std::vector<dive *>>> data, ChartSortMode sortMode) :
StatsSeries(view, xAxis, yAxis), StatsSeries(view, xAxis, yAxis),
item(view.createChartItem<ChartPieItem>(ChartZValue::Series, pieBorderWidth)), item(view.createChartItem<ChartPieItem>(ChartZValue::Series, theme, pieBorderWidth)),
categoryName(categoryName), categoryName(categoryName),
radius(0), radius(0),
highlighted(-1), highlighted(-1),

View file

@ -24,8 +24,8 @@ ScatterSeries::~ScatterSeries()
{ {
} }
ScatterSeries::Item::Item(StatsView &view, ScatterSeries *series, dive *d, double pos, double value) : ScatterSeries::Item::Item(StatsView &view, ScatterSeries *series, const StatsTheme &theme, dive *d, double pos, double value) :
item(view.createChartItem<ChartScatterItem>(ChartZValue::Series, d->selected)), item(view.createChartItem<ChartScatterItem>(ChartZValue::Series, theme, d->selected)),
d(d), d(d),
selected(d->selected), selected(d->selected),
pos(pos), pos(pos),
@ -50,7 +50,7 @@ void ScatterSeries::Item::highlight(bool highlight)
void ScatterSeries::append(dive *d, double pos, double value) void ScatterSeries::append(dive *d, double pos, double value)
{ {
items.emplace_back(view, this, d, pos, value); items.emplace_back(view, this, theme, d, pos, value);
} }
void ScatterSeries::updatePositions() void ScatterSeries::updatePositions()

View file

@ -41,7 +41,7 @@ private:
dive *d; dive *d;
bool selected; bool selected;
double pos, value; double pos, value;
Item(StatsView &view, ScatterSeries *series, dive *d, double pos, double value); Item(StatsView &view, ScatterSeries *series, const StatsTheme &theme, dive *d, double pos, double value);
void updatePosition(ScatterSeries *series); void updatePosition(ScatterSeries *series);
void highlight(bool highlight); void highlight(bool highlight);
}; };

View file

@ -183,7 +183,7 @@ QSGNode *StatsView::updatePaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNod
} }
for (ChartItem *item = dirtyItems.first; item; item = item->next) { for (ChartItem *item = dirtyItems.first; item; item = item->next) {
item->render(*currentTheme); item->render();
item->dirty = false; item->dirty = false;
} }
dirtyItems.splice(cleanItems); dirtyItems.splice(cleanItems);