summaryrefslogtreecommitdiffstats
path: root/stats
diff options
context:
space:
mode:
authorGravatar Berthold Stoeger <bstoeger@mail.tuwien.ac.at>2021-01-13 15:17:54 +0100
committerGravatar bstoeger <32835590+bstoeger@users.noreply.github.com>2021-01-20 08:47:18 +0100
commit785d5189f617bab7d5dde668563fc4889e46f695 (patch)
tree67a3d41998725d77aadc98c1d57de4a0c7f459d8 /stats
parentd7878dad36e176ef0e2e1c54db891e115d29b489 (diff)
downloadsubsurface-785d5189f617bab7d5dde668563fc4889e46f695.tar.gz
statistics: turn infobox into a QSGNode
A small step in converting from QGraphicsScene to QQuickItem. This is the second item to be converted (after the legend) and for now items are drawn in order of creation, which means that the infobox is on top of the legend. This will have to be made deterministic in follow-up commits. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Diffstat (limited to 'stats')
-rw-r--r--stats/barseries.cpp3
-rw-r--r--stats/boxseries.cpp3
-rw-r--r--stats/informationbox.cpp65
-rw-r--r--stats/informationbox.h10
-rw-r--r--stats/pieseries.cpp3
-rw-r--r--stats/scatterseries.cpp3
-rw-r--r--stats/statsview.cpp8
-rw-r--r--stats/statsview.h16
8 files changed, 53 insertions, 58 deletions
diff --git a/stats/barseries.cpp b/stats/barseries.cpp
index 91ab1c941..733549d3d 100644
--- a/stats/barseries.cpp
+++ b/stats/barseries.cpp
@@ -4,6 +4,7 @@
#include "statscolors.h"
#include "statshelper.h"
#include "statstranslations.h"
+#include "statsview.h"
#include "zvalues.h"
#include <math.h> // for lrint()
@@ -403,7 +404,7 @@ bool BarSeries::hover(QPointF pos)
Item &item = items[highlighted.bar];
item.highlight(index.subitem, true, binCount());
if (!information)
- information = createItemPtr<InformationBox>(scene);
+ information = view.createChartItem<InformationBox>();
information->setText(makeInfo(item, highlighted.subitem), pos);
} else {
information.reset();
diff --git a/stats/boxseries.cpp b/stats/boxseries.cpp
index def20477e..b3dc2e5bd 100644
--- a/stats/boxseries.cpp
+++ b/stats/boxseries.cpp
@@ -4,6 +4,7 @@
#include "statscolors.h"
#include "statshelper.h"
#include "statstranslations.h"
+#include "statsview.h"
#include "zvalues.h"
#include <QLocale>
@@ -149,7 +150,7 @@ bool BoxSeries::hover(QPointF pos)
Item &item = *items[highlighted];
item.highlight(true);
if (!information)
- information = createItemPtr<InformationBox>(scene);
+ information = view.createChartItem<InformationBox>();
information->setText(formatInformation(item), pos);
} else {
information.reset();
diff --git a/stats/informationbox.cpp b/stats/informationbox.cpp
index 189fd1ab1..c768b77b3 100644
--- a/stats/informationbox.cpp
+++ b/stats/informationbox.cpp
@@ -1,9 +1,9 @@
#include "informationbox.h"
#include "statscolors.h"
+#include "statsview.h"
#include "zvalues.h"
#include <QFontMetrics>
-#include <QGraphicsScene>
static const QColor informationBorderColor(Qt::black);
static const QColor informationColor(0xff, 0xff, 0x00, 192); // Note: fourth argument is opacity
@@ -11,74 +11,65 @@ static const int informationBorder = 2;
static const double informationBorderRadius = 4.0; // Radius of rounded corners
static const int distanceFromPointer = 10; // Distance to place box from mouse pointer or scatter item
-InformationBox::InformationBox() : RoundRectItem(informationBorderRadius, nullptr)
+InformationBox::InformationBox(StatsView &v) :
+ ChartRectItem(v, QPen(informationBorderColor, informationBorder),
+ QBrush(informationColor), informationBorderRadius)
{
- setPen(QPen(informationBorderColor, informationBorder));
- setBrush(informationColor);
- setZValue(ZValues::informationBox);
}
void InformationBox::setText(const std::vector<QString> &text, QPointF pos)
{
- width = height = 0.0;
- textItems.clear();
+ QFontMetrics fm(font);
+ double fontHeight = fm.height();
+ std::vector<double> widths;
+ widths.reserve(text.size());
+ width = 0.0;
for (const QString &s: text) {
- if (!s.isEmpty())
- addLine(s);
+ widths.push_back(static_cast<double>(fm.size(Qt::TextSingleLine, s).width()));
+ width = std::max(width, widths.back());
}
width += 4.0 * informationBorder;
- height += 4.0 * informationBorder;
+ height = widths.size() * fontHeight + 4.0 * informationBorder;
+
+ ChartRectItem::resize(QSizeF(width, height));
- // Setting the position will also set the proper size
- setPos(pos);
+ painter->setPen(QPen(darkLabelColor)); // QPainter uses QPen to set text color!
+ double y = 2.0 * informationBorder;
+ for (size_t i = 0; i < widths.size(); ++i) {
+ QRectF rect(2.0 * informationBorder, y, widths[i], fontHeight);
+ painter->drawText(rect, text[i]);
+ y += fontHeight;
+ }
}
void InformationBox::setPos(QPointF pos)
{
- QRectF plotArea = scene()->sceneRect();
+ QSizeF size = sceneSize();
double x = pos.x() + distanceFromPointer;
- if (x + width >= plotArea.right()) {
- if (pos.x() - width >= plotArea.x())
+ if (x + width >= size.width()) {
+ if (pos.x() - width >= 0.0)
x = pos.x() - width;
else
x = pos.x() - width / 2.0;
}
double y = pos.y() + distanceFromPointer;
- if (y + height >= plotArea.bottom()) {
- if (pos.y() - height >= plotArea.y())
+ if (y + height >= size.height()) {
+ if (pos.y() - height >= 0.0)
y = pos.y() - height;
else
y = pos.y() - height / 2.0;
}
- setRect(x, y, width, height);
- double actY = y + 2.0 * informationBorder;
- for (auto &item: textItems) {
- item->setPos(QPointF(x + 2.0 * informationBorder, actY));
- actY += item->boundingRect().height();
- }
-}
-
-void InformationBox::addLine(const QString &s)
-{
- textItems.emplace_back(new QGraphicsSimpleTextItem(s, this));
- QGraphicsSimpleTextItem &item = *textItems.back();
- item.setBrush(QBrush(darkLabelColor));
- item.setPos(QPointF(0.0, height));
- item.setFont(font);
- item.setZValue(ZValues::informationBox);
- QRectF rect = item.boundingRect();
- width = std::max(width, rect.width());
- height += rect.height();
+ ChartRectItem::setPos(QPointF(x, y));
}
// Try to stay within three-thirds of the chart height
int InformationBox::recommendedMaxLines() const
{
QFontMetrics fm(font);
- int maxHeight = static_cast<int>(scene()->sceneRect().height());
+ int maxHeight = static_cast<int>(sceneSize().height());
return maxHeight * 2 / fm.height() / 3;
}
diff --git a/stats/informationbox.h b/stats/informationbox.h
index 741df537f..6ff2bb43e 100644
--- a/stats/informationbox.h
+++ b/stats/informationbox.h
@@ -4,26 +4,24 @@
#ifndef INFORMATION_BOX_H
#define INFORMATION_BOX_H
-#include "backend-shared/roundrectitem.h"
+#include "chartitem.h"
#include <vector>
#include <memory>
#include <QFont>
struct dive;
-class QGraphicsScene;
+class StatsView;
// Information window showing data of highlighted dive
-struct InformationBox : RoundRectItem {
- InformationBox();
+struct InformationBox : ChartRectItem {
+ InformationBox(StatsView &);
void setText(const std::vector<QString> &text, QPointF pos);
void setPos(QPointF pos);
int recommendedMaxLines() const;
private:
QFont font; // For future specialization.
double width, height;
- void addLine(const QString &s);
- std::vector<std::unique_ptr<QGraphicsSimpleTextItem>> textItems;
};
#endif
diff --git a/stats/pieseries.cpp b/stats/pieseries.cpp
index 85c42b93b..dc337aa8d 100644
--- a/stats/pieseries.cpp
+++ b/stats/pieseries.cpp
@@ -4,6 +4,7 @@
#include "statscolors.h"
#include "statshelper.h"
#include "statstranslations.h"
+#include "statsview.h"
#include "zvalues.h"
#include <numeric>
@@ -246,7 +247,7 @@ bool PieSeries::hover(QPointF pos)
if (highlighted >= 0 && highlighted < (int)items.size()) {
items[highlighted].highlight(highlighted, true, (int)items.size());
if (!information)
- information = createItemPtr<InformationBox>(scene);
+ information = view.createChartItem<InformationBox>();
information->setText(makeInfo(highlighted), pos);
} else {
information.reset();
diff --git a/stats/scatterseries.cpp b/stats/scatterseries.cpp
index 2c5cc7716..a073f6992 100644
--- a/stats/scatterseries.cpp
+++ b/stats/scatterseries.cpp
@@ -5,6 +5,7 @@
#include "statshelper.h"
#include "statstranslations.h"
#include "statsvariables.h"
+#include "statsview.h"
#include "zvalues.h"
#include "core/dive.h"
#include "core/divelist.h"
@@ -173,7 +174,7 @@ bool ScatterSeries::hover(QPointF pos)
return false;
} else {
if (!information)
- information = createItemPtr<InformationBox>(scene);
+ information = view.createChartItem<InformationBox>();
std::vector<QString> text;
text.reserve(highlighted.size() * 5);
diff --git a/stats/statsview.cpp b/stats/statsview.cpp
index e97510087..05693fd0b 100644
--- a/stats/statsview.cpp
+++ b/stats/statsview.cpp
@@ -279,14 +279,6 @@ T *StatsView::createAxis(const QString &title, Args&&... args)
return res;
}
-template <typename T, class... Args>
-std::unique_ptr<T> StatsView::createChartItem(Args&&... args)
-{
- std::unique_ptr<T> res(new T(*this, std::forward<Args>(args)...));
- items.push_back(res.get());
- return res;
-}
-
void StatsView::setAxes(StatsAxis *x, StatsAxis *y)
{
xAxis = x;
diff --git a/stats/statsview.h b/stats/statsview.h
index 8270c237f..62fb246cd 100644
--- a/stats/statsview.h
+++ b/stats/statsview.h
@@ -52,6 +52,9 @@ public:
QSizeF size() const;
void addQSGNode(QSGNode *node, int z); // Must only be called in render thread!
void unregisterChartItem(const ChartItem *item);
+ template <typename T, class... Args>
+ std::unique_ptr<T> createChartItem(Args&&... args);
+
private slots:
void replotIfVisible();
private:
@@ -109,9 +112,6 @@ private:
template <typename T, class... Args>
T *createAxis(const QString &title, Args&&... args);
- template <typename T, class... Args>
- std::unique_ptr<T> createChartItem(Args&&... args);
-
template<typename T>
CategoryAxis *createCategoryAxis(const QString &title, const StatsBinner &binner,
const std::vector<T> &bins, bool isHorizontal);
@@ -179,4 +179,14 @@ private:
QSGImageNode *rootNode;
};
+// This implementation detail must be known to users of the class.
+// Perhaps move it into a statsview_impl.h file.
+template <typename T, class... Args>
+std::unique_ptr<T> StatsView::createChartItem(Args&&... args)
+{
+ std::unique_ptr<T> res(new T(*this, std::forward<Args>(args)...));
+ items.push_back(res.get());
+ return res;
+}
+
#endif