summaryrefslogtreecommitdiffstats
path: root/stats/chartitem.cpp
diff options
context:
space:
mode:
authorGravatar Berthold Stoeger <bstoeger@mail.tuwien.ac.at>2021-01-15 22:48:32 +0100
committerGravatar bstoeger <32835590+bstoeger@users.noreply.github.com>2021-01-20 08:47:18 +0100
commitb42e19e36b4d80716059011581851c8600338cbb (patch)
treee752618c95a6ab4dcb980209800d3c3bbf292a0e /stats/chartitem.cpp
parent20088576604a3159cc9891bcfea888c15b096a96 (diff)
downloadsubsurface-b42e19e36b4d80716059011581851c8600338cbb.tar.gz
statistics: convert bar series to QSGNodes
To this end, two new ChartItems were added: A "bar" (a rectangle with a border) and a "text" (multiple lines of text). It turns out that the text on the bars now looks atrocious. The reason appears to be that the antialiasing of the font-rendering does not blend into the alpha channel, but into a supposed background color? This will have to be investigated. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Diffstat (limited to 'stats/chartitem.cpp')
-rw-r--r--stats/chartitem.cpp119
1 files changed, 117 insertions, 2 deletions
diff --git a/stats/chartitem.cpp b/stats/chartitem.cpp
index aeb395d41..bb01c6e2c 100644
--- a/stats/chartitem.cpp
+++ b/stats/chartitem.cpp
@@ -6,6 +6,7 @@
#include <QQuickWindow>
#include <QSGFlatColorMaterial>
#include <QSGImageNode>
+#include <QSGRectangleNode>
#include <QSGTexture>
static int round_up(double f)
@@ -116,6 +117,40 @@ 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) :
+ ChartPixmapItem(v, z), f(f), center(center)
+{
+ QFontMetrics fm(f);
+ double totalWidth = 1.0;
+ fontHeight = static_cast<double>(fm.height());
+ double totalHeight = std::max(1.0, static_cast<double>(text.size()) * fontHeight);
+
+ items.reserve(text.size());
+ for (const QString &s: text) {
+ double w = fm.size(Qt::TextSingleLine, s).width();
+ items.push_back({ s, w });
+ if (w > totalWidth)
+ totalWidth = w;
+ }
+ resize(QSizeF(totalWidth, totalHeight));
+}
+
+void ChartTextItem::setColor(const QColor &c)
+{
+ img->fill(Qt::transparent);
+ double y = 0.0;
+ painter->setPen(QPen(c));
+ painter->setFont(f);
+ double totalWidth = getRect().width();
+ for (const auto &[s, w]: items) {
+ double x = center ? round((totalWidth - w) / 2.0) : 0.0;
+ QRectF rect(x, y, w, fontHeight);
+ painter->drawText(rect, s);
+ y += fontHeight;
+ }
+ setTextureDirty();
+}
+
ChartLineItem::ChartLineItem(StatsView &v, ChartZValue z, QColor color, double width) : ChartItem(v, z),
color(color), width(width), positionDirty(false), materialDirty(false)
{
@@ -125,6 +160,12 @@ ChartLineItem::~ChartLineItem()
{
}
+// Helper function to set points
+void setPoint(QSGGeometry::Point2D &v, const QPointF &p)
+{
+ v.set(static_cast<float>(p.x()), static_cast<float>(p.y()));
+}
+
void ChartLineItem::render()
{
if (!node) {
@@ -142,8 +183,8 @@ void ChartLineItem::render()
// Attention: width is a geometry property and therefore handled by position dirty!
geometry->setLineWidth(static_cast<float>(width));
auto vertices = geometry->vertexDataAsPoint2D();
- vertices[0].set(static_cast<float>(from.x()), static_cast<float>(from.y()));
- vertices[1].set(static_cast<float>(to.x()), static_cast<float>(to.y()));
+ setPoint(vertices[0], from);
+ setPoint(vertices[1], to);
node->markDirty(QSGNode::DirtyGeometry);
}
@@ -162,3 +203,77 @@ void ChartLineItem::setLine(QPointF fromIn, QPointF toIn)
positionDirty = true;
view.registerDirtyChartItem(*this);
}
+
+ChartBarItem::ChartBarItem(StatsView &v, ChartZValue z, double borderWidth, bool horizontal) : ChartItem(v, z),
+ borderWidth(borderWidth), horizontal(horizontal),
+ positionDirty(false), colorDirty(false)
+{
+}
+
+ChartBarItem::~ChartBarItem()
+{
+}
+
+void ChartBarItem::render()
+{
+ if (!node) {
+ node.reset(view.w()->createRectangleNode());
+
+ borderGeometry.reset(new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), 4));
+ borderGeometry->setDrawingMode(QSGGeometry::DrawLineLoop);
+ borderGeometry->setLineWidth(static_cast<float>(borderWidth));
+ borderMaterial.reset(new QSGFlatColorMaterial);
+ borderNode.reset(new QSGGeometryNode);
+ borderNode->setGeometry(borderGeometry.get());
+ borderNode->setMaterial(borderMaterial.get());
+
+ node->appendChildNode(borderNode.get());
+ view.addQSGNode(node.get(), zValue);
+ positionDirty = colorDirty = true;
+ }
+
+ if (colorDirty) {
+ node->setColor(color);
+ borderMaterial->setColor(borderColor);
+ borderNode->markDirty(QSGNode::DirtyMaterial);
+ }
+
+ if (positionDirty) {
+ node->setRect(rect);
+ auto vertices = borderGeometry->vertexDataAsPoint2D();
+ if (horizontal) {
+ setPoint(vertices[0], rect.topLeft());
+ setPoint(vertices[1], rect.topRight());
+ setPoint(vertices[2], rect.bottomRight());
+ setPoint(vertices[3], rect.bottomLeft());
+ } else {
+ setPoint(vertices[0], rect.bottomLeft());
+ setPoint(vertices[1], rect.topLeft());
+ setPoint(vertices[2], rect.topRight());
+ setPoint(vertices[3], rect.bottomRight());
+ }
+ borderNode->markDirty(QSGNode::DirtyGeometry);
+ }
+
+ positionDirty = colorDirty = false;
+}
+
+void ChartBarItem::setColor(QColor colorIn, QColor borderColorIn)
+{
+ color = colorIn;
+ borderColor = borderColorIn;
+ colorDirty = true;
+ view.registerDirtyChartItem(*this);
+}
+
+void ChartBarItem::setRect(const QRectF &rectIn)
+{
+ rect = rectIn;
+ positionDirty = true;
+ view.registerDirtyChartItem(*this);
+}
+
+QRectF ChartBarItem::getRect() const
+{
+ return rect;
+}