diff options
author | Berthold Stoeger <bstoeger@mail.tuwien.ac.at> | 2021-01-05 13:04:53 +0100 |
---|---|---|
committer | Dirk Hohndel <dirk@hohndel.org> | 2021-01-06 12:31:22 -0800 |
commit | 8dfa3f6db3eda8bce432afb7407efe2d8822ebbd (patch) | |
tree | 2a1c6f629fc161c33da6e7515c42fad138a0d6de /stats | |
parent | 4ab9f1c6b06204285267e79b5ed993514e0213e2 (diff) | |
download | subsurface-8dfa3f6db3eda8bce432afb7407efe2d8822ebbd.tar.gz |
statistics: draw title of axes
Easy enough to implement, but one weirdness:
To get the height of the rotated text, one has to access the
width() member of the boundingRect. I'm not sure if that makes
sense, but so be it.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Diffstat (limited to 'stats')
-rw-r--r-- | stats/statsaxis.cpp | 65 | ||||
-rw-r--r-- | stats/statsaxis.h | 16 | ||||
-rw-r--r-- | stats/statsview.cpp | 3 |
3 files changed, 55 insertions, 29 deletions
diff --git a/stats/statsaxis.cpp b/stats/statsaxis.cpp index 1a425cc0c..23923e7ea 100644 --- a/stats/statsaxis.cpp +++ b/stats/statsaxis.cpp @@ -23,10 +23,10 @@ static const double axisLabelSpaceVertical = 2.0; // Space between axis or ticks static const double axisTitleSpaceHorizontal = 2.0; // Space between labels and title static const double axisTitleSpaceVertical = 2.0; // Space between labels and title -StatsAxis::StatsAxis(QtCharts::QChart *chart, bool horizontal, bool labelsBetweenTicks) : +StatsAxis::StatsAxis(QtCharts::QChart *chart, const QString &titleIn, bool horizontal, bool labelsBetweenTicks) : QGraphicsLineItem(chart), chart(chart), horizontal(horizontal), labelsBetweenTicks(labelsBetweenTicks), - size(1.0), zeroOnScreen(0.0), min(0.0), max(1.0) + size(1.0), zeroOnScreen(0.0), min(0.0), max(1.0), labelWidth(0.0) { // use a Light version of the application fond for both labels and title labelFont = QFont(); @@ -34,6 +34,13 @@ StatsAxis::StatsAxis(QtCharts::QChart *chart, bool horizontal, bool labelsBetwee titleFont = labelFont; setPen(QPen(axisColor, axisWidth)); setZValue(ZValues::axes); + if (!titleIn.isEmpty()) { + title = std::make_unique<QGraphicsSimpleTextItem>(titleIn, chart); + title->setFont(titleFont); + title->setBrush(darkLabelColor); + if (!horizontal) + title->setRotation(-90.0); + } } StatsAxis::~StatsAxis() @@ -76,18 +83,19 @@ int StatsAxis::guessNumTicks(const std::vector<QString> &strings) const return std::max(numTicks, 2); } +double StatsAxis::titleSpace() const +{ + if (!title) + return 0.0; + return horizontal ? QFontMetrics(titleFont).height() + axisTitleSpaceHorizontal + : QFontMetrics(titleFont).height() + axisTitleSpaceVertical; +} + double StatsAxis::width() const { if (horizontal) return 0.0; // Only supported for vertical axes - double labelWidth = 0.0; - for (const Label &label: labels) { - double w = label.label->boundingRect().width(); - if (w > labelWidth) - labelWidth = w; - } - return labelWidth + axisLabelSpaceVertical + - QFontMetrics(titleFont).height() + axisTitleSpaceVertical + + return labelWidth + axisLabelSpaceVertical + titleSpace() + (labelsBetweenTicks ? 0.0 : axisTickSizeVertical); } @@ -96,7 +104,7 @@ double StatsAxis::height() const if (!horizontal) return 0.0; // Only supported for horizontal axes return QFontMetrics(labelFont).height() + axisLabelSpaceHorizontal + - QFontMetrics(titleFont).height() + axisTitleSpaceHorizontal + + titleSpace() + (labelsBetweenTicks ? 0.0 : axisTickSizeHorizontal); } @@ -146,6 +154,12 @@ void StatsAxis::setSize(double sizeIn) { size = sizeIn; updateLabels(); + labelWidth = 0.0; + for (const Label &label: labels) { + double w = label.label->boundingRect().width(); + if (w > labelWidth) + labelWidth = w; + } } void StatsAxis::setPos(QPointF pos) @@ -164,6 +178,9 @@ void StatsAxis::setPos(QPointF pos) tick.item->setLine(x, y, x, y + axisTickSizeHorizontal); } setLine(zeroOnScreen, y, zeroOnScreen + size, y); + if (title) + title->setPos(zeroOnScreen + (size - title->boundingRect().width()) / 2.0, + labelY + QFontMetrics(labelFont).height() + axisTitleSpaceHorizontal); } else { double fontHeight = QFontMetrics(labelFont).height(); zeroOnScreen = pos.y(); @@ -178,12 +195,18 @@ void StatsAxis::setPos(QPointF pos) double y = toScreen(tick.pos); tick.item->setLine(x, y, x - axisTickSizeVertical, y); } + // This is very confusing: even though we need the height of the title, the correct + // size is stored in boundingRect().width(). Presumably because the item is rotated + // by -90°. Apparently, the boundingRect is in item-local coordinates? + if (title) + title->setPos(labelX - labelWidth - QFontMetrics(labelFont).height() - axisTitleSpaceVertical, + zeroOnScreen - (size - title->boundingRect().width()) / 2.0); setLine(x, zeroOnScreen, x, zeroOnScreen - size); } } -ValueAxis::ValueAxis(QtCharts::QChart *chart, double min, double max, int decimals, bool horizontal) : - StatsAxis(chart, horizontal, false), +ValueAxis::ValueAxis(QtCharts::QChart *chart, const QString &title, double min, double max, int decimals, bool horizontal) : + StatsAxis(chart, title, horizontal, false), min(min), max(max), decimals(decimals) { } @@ -237,8 +260,8 @@ void ValueAxis::updateLabels() } } -CountAxis::CountAxis(QtCharts::QChart *chart, int count, bool horizontal) : - ValueAxis(chart, 0.0, (double)count, 0, horizontal), +CountAxis::CountAxis(QtCharts::QChart *chart, const QString &title, int count, bool horizontal) : + ValueAxis(chart, title, 0.0, (double)count, 0, horizontal), count(count) { } @@ -290,8 +313,8 @@ void CountAxis::updateLabels() } } -CategoryAxis::CategoryAxis(QtCharts::QChart *chart, const std::vector<QString> &labelsIn, bool horizontal) : - StatsAxis(chart, horizontal, true) +CategoryAxis::CategoryAxis(QtCharts::QChart *chart, const QString &title, const std::vector<QString> &labelsIn, bool horizontal) : + StatsAxis(chart, title, horizontal, true) { labels.reserve(labelsIn.size()); ticks.reserve(labelsIn.size() + 1); @@ -309,8 +332,8 @@ void CategoryAxis::updateLabels() { } -HistogramAxis::HistogramAxis(QtCharts::QChart *chart, std::vector<HistogramAxisEntry> bins, bool horizontal) : - StatsAxis(chart, horizontal, false), +HistogramAxis::HistogramAxis(QtCharts::QChart *chart, const QString &title, std::vector<HistogramAxisEntry> bins, bool horizontal) : + StatsAxis(chart, title, horizontal, false), bin_values(std::move(bins)) { if (bin_values.size() < 2) // Less than two makes no sense -> there must be at least one category @@ -498,7 +521,7 @@ static std::vector<HistogramAxisEntry> timeRangeToBins(double from, double to) return res; } -DateAxis::DateAxis(QtCharts::QChart *chart, double from, double to, bool horizontal) : - HistogramAxis(chart, timeRangeToBins(from, to), horizontal) +DateAxis::DateAxis(QtCharts::QChart *chart, const QString &title, double from, double to, bool horizontal) : + HistogramAxis(chart, title, timeRangeToBins(from, to), horizontal) { } diff --git a/stats/statsaxis.h b/stats/statsaxis.h index c9619a124..c25ffe692 100644 --- a/stats/statsaxis.h +++ b/stats/statsaxis.h @@ -31,7 +31,7 @@ public: double toScreen(double) const; double toValue(double) const; protected: - StatsAxis(QtCharts::QChart *chart, bool horizontal, bool labelsBetweenTicks); + StatsAxis(QtCharts::QChart *chart, const QString &title, bool horizontal, bool labelsBetweenTicks); QtCharts::QChart *chart; struct Label { @@ -56,14 +56,18 @@ protected: bool labelsBetweenTicks; // When labels are between ticks, they can be moved closer to the axis QFont labelFont, titleFont; + std::unique_ptr<QGraphicsSimpleTextItem> title; double size; // width for horizontal, height for vertical double zeroOnScreen; double min, max; + double labelWidth; // Maximum width of labels +private: + double titleSpace() const; // Space needed for title }; class ValueAxis : public StatsAxis { public: - ValueAxis(QtCharts::QChart *chart, double min, double max, int decimals, bool horizontal); + ValueAxis(QtCharts::QChart *chart, const QString &title, double min, double max, int decimals, bool horizontal); private: double min, max; int decimals; @@ -72,7 +76,7 @@ private: class CountAxis : public ValueAxis { public: - CountAxis(QtCharts::QChart *chart, int count, bool horizontal); + CountAxis(QtCharts::QChart *chart, const QString &title, int count, bool horizontal); private: int count; void updateLabels() override; @@ -80,7 +84,7 @@ private: class CategoryAxis : public StatsAxis { public: - CategoryAxis(QtCharts::QChart *chart, const std::vector<QString> &labels, bool horizontal); + CategoryAxis(QtCharts::QChart *chart, const QString &title, const std::vector<QString> &labels, bool horizontal); private: void updateLabels(); }; @@ -93,7 +97,7 @@ struct HistogramAxisEntry { class HistogramAxis : public StatsAxis { public: - HistogramAxis(QtCharts::QChart *chart, std::vector<HistogramAxisEntry> bin_values, bool horizontal); + HistogramAxis(QtCharts::QChart *chart, const QString &title, std::vector<HistogramAxisEntry> bin_values, bool horizontal); private: void updateLabels() override; std::vector<HistogramAxisEntry> bin_values; @@ -102,7 +106,7 @@ private: class DateAxis : public HistogramAxis { public: - DateAxis(QtCharts::QChart *chart, double from, double to, bool horizontal); + DateAxis(QtCharts::QChart *chart, const QString &title, double from, double to, bool horizontal); }; #endif diff --git a/stats/statsview.cpp b/stats/statsview.cpp index fdf6e9dc3..394620d13 100644 --- a/stats/statsview.cpp +++ b/stats/statsview.cpp @@ -186,8 +186,7 @@ void StatsView::updateTitlePos() template <typename T, class... Args> T *StatsView::createAxis(const QString &title, Args&&... args) { - // TODO: set title - T *res = new T(chart, std::forward<Args>(args)...); + T *res = new T(chart, title, std::forward<Args>(args)...); axes.emplace_back(res); return res; } |