mirror of
https://github.com/subsurface/subsurface.git
synced 2024-11-28 05:00:20 +00:00
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>
This commit is contained in:
parent
4ab9f1c6b0
commit
8dfa3f6db3
3 changed files with 55 additions and 29 deletions
|
@ -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)
|
||||
{
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue