summaryrefslogtreecommitdiffstats
path: root/stats
diff options
context:
space:
mode:
Diffstat (limited to 'stats')
-rw-r--r--stats/statsaxis.cpp56
-rw-r--r--stats/statsaxis.h6
-rw-r--r--stats/statsview.cpp12
3 files changed, 63 insertions, 11 deletions
diff --git a/stats/statsaxis.cpp b/stats/statsaxis.cpp
index 8b8694964..d31b5827b 100644
--- a/stats/statsaxis.cpp
+++ b/stats/statsaxis.cpp
@@ -57,6 +57,17 @@ std::pair<double, double> StatsAxis::minMaxScreen() const
: std::make_pair(zeroOnScreen, zeroOnScreen - size);
}
+std::pair<double, double> StatsAxis::horizontalOverhang() const
+{
+ // If the labels are between ticks, they cannot peak out
+ if (!horizontal || labelsBetweenTicks)
+ return { 0.0, 0.0 };
+ QFontMetrics fm(labelFont);
+ auto [firstLabel, lastLabel] = getFirstLastLabel();
+ return { fm.size(Qt::TextSingleLine, firstLabel).width() / 2.0,
+ fm.size(Qt::TextSingleLine, lastLabel).width() / 2.0 };
+}
+
void StatsAxis::setRange(double minIn, double maxIn)
{
min = minIn;
@@ -223,6 +234,19 @@ ValueAxis::ValueAxis(const QString &title, double min, double max, int decimals,
StatsAxis(title, horizontal, false),
min(min), max(max), decimals(decimals)
{
+ // Avoid degenerate cases
+ if (max - min < 0.0001) {
+ max += 0.5;
+ min -= 0.5;
+ }
+}
+
+// Attention: this is only heuristics. Before setting the actual size, we
+// don't know the actual numbers of the minimum and maximum value.
+std::pair<QString, QString> ValueAxis::getFirstLastLabel() const
+{
+ QLocale loc;
+ return { loc.toString(min, 'f', decimals), loc.toString(max, 'f', decimals) };
}
void ValueAxis::updateLabels()
@@ -230,15 +254,8 @@ void ValueAxis::updateLabels()
labels.clear();
ticks.clear();
- // Avoid degenerate cases
- if (max - min < 0.0001) {
- max += 0.5;
- min -= 0.5;
- }
-
QLocale loc;
- QString minString = loc.toString(min, 'f', decimals);
- QString maxString = loc.toString(max, 'f', decimals);
+ auto [minString, maxString] = getFirstLastLabel();
int numTicks = guessNumTicks({ minString, maxString});
// Use full decimal increments
@@ -279,6 +296,14 @@ CountAxis::CountAxis(const QString &title, int count, bool horizontal) :
{
}
+// Attention: this is only heuristics. Before setting the actual size, we
+// don't know the actual numbers of the minimum and maximum value.
+std::pair<QString, QString> CountAxis::getFirstLastLabel() const
+{
+ QLocale loc;
+ return { QString("0"), loc.toString(count) };
+}
+
void CountAxis::updateLabels()
{
labels.clear();
@@ -333,6 +358,13 @@ CategoryAxis::CategoryAxis(const QString &title, const std::vector<QString> &lab
setRange(-0.5, static_cast<double>(labels.size()) + 0.5);
}
+// No implementation because the labels are inside ticks and this
+// is only used to calculate the "overhang" of labels under ticks.
+std::pair<QString, QString> CategoryAxis::getFirstLastLabel() const
+{
+ return { QString(), QString() };
+}
+
void CategoryAxis::updateLabels()
{
// TODO: paint ellipses if space too small
@@ -370,6 +402,14 @@ HistogramAxis::HistogramAxis(const QString &title, std::vector<HistogramAxisEntr
setRange(bin_values.front().value, bin_values.back().value);
}
+std::pair<QString, QString> HistogramAxis::getFirstLastLabel() const
+{
+ if (bin_values.empty())
+ return { QString(), QString() };
+ else
+ return { bin_values.front().name, bin_values.back().name };
+}
+
// Initialize a histogram axis with the given labels. Labels are specified as (name, value, recommended) triplets.
// If labels are skipped, try to skip it in such a way that a recommended label is shown.
// The one example where this is relevant is the quarterly bins, which are formated as (2019, q1, q2, q3, 2020, ...).
diff --git a/stats/statsaxis.h b/stats/statsaxis.h
index 72a191963..9d46f753a 100644
--- a/stats/statsaxis.h
+++ b/stats/statsaxis.h
@@ -16,6 +16,7 @@ public:
// Returns minimum and maximum of shown range, not of data points.
std::pair<double, double> minMax() const;
std::pair<double, double> minMaxScreen() const; // minimum and maximum in screen coordinates
+ std::pair<double, double> horizontalOverhang() const; // space that labels peak out in horizontal axes
double width() const; // Only supported by vertical axes. Only valid after setSize().
double height() const; // Only supported for horizontal axes. Always valid.
@@ -39,6 +40,7 @@ protected:
std::vector<Label> labels;
void addLabel(const QString &label, double pos);
virtual void updateLabels() = 0;
+ virtual std::pair<QString, QString> getFirstLastLabel() const = 0;
struct Tick {
std::unique_ptr<QGraphicsLineItem> item;
@@ -69,6 +71,7 @@ private:
double min, max;
int decimals;
void updateLabels() override;
+ std::pair<QString, QString> getFirstLastLabel() const override;
};
class CountAxis : public ValueAxis {
@@ -77,6 +80,7 @@ public:
private:
int count;
void updateLabels() override;
+ std::pair<QString, QString> getFirstLastLabel() const override;
};
class CategoryAxis : public StatsAxis {
@@ -85,6 +89,7 @@ public:
private:
std::vector<QString> labelsText;
void updateLabels();
+ std::pair<QString, QString> getFirstLastLabel() const override;
};
struct HistogramAxisEntry {
@@ -98,6 +103,7 @@ public:
HistogramAxis(const QString &title, std::vector<HistogramAxisEntry> bin_values, bool horizontal);
private:
void updateLabels() override;
+ std::pair<QString, QString> getFirstLastLabel() const override;
std::vector<HistogramAxisEntry> bin_values;
int preferred_step;
};
diff --git a/stats/statsview.cpp b/stats/statsview.cpp
index 1533583ba..5583643d7 100644
--- a/stats/statsview.cpp
+++ b/stats/statsview.cpp
@@ -97,15 +97,21 @@ void StatsView::plotAreaChanged(const QSizeF &s)
if (title)
top += title->boundingRect().height() + titleBorder;
// Currently, we only have either none, or an x- and a y-axis
- if (xAxis)
+ std::pair<double,double> horizontalSpace{ 0.0, 0.0 };
+ if (xAxis) {
bottom -= xAxis->height();
+ horizontalSpace = xAxis->horizontalOverhang();
+ }
if (bottom - top < minSize)
return;
if (yAxis) {
yAxis->setSize(bottom - top);
- left += yAxis->width();
- yAxis->setPos(QPointF(left, bottom));
+ horizontalSpace.first = std::max(horizontalSpace.first, yAxis->width());
}
+ left += horizontalSpace.first;
+ right -= horizontalSpace.second;
+ if (yAxis)
+ yAxis->setPos(QPointF(left, bottom));
if (right - left < minSize)
return;
if (xAxis) {