// SPDX-License-Identifier: GPL-2.0 // A small custom bar series, which displays information // when hovering over a bar. The QtCharts bar series were // too inflexible with respect to placement of the bars. #ifndef BAR_SERIES_H #define BAR_SERIES_H #include "statshelper.h" #include "statsseries.h" #include "statsvariables.h" #include #include #include #include class ChartBarItem; class ChartTextItem; struct InformationBox; struct StatsVariable; class BarSeries : public StatsSeries { public: // There are three versions of creating bar series: for value-based (mean, etc) charts, for counts // based charts and for stacked bar charts with multiple items. struct CountItem { double lowerBound, upperBound; std::vector dives; std::vector label; QString binName; int total; }; struct ValueItem { double lowerBound, upperBound; double value; std::vector label; QString binName; StatsOperationResults res; // Contains the dives }; struct MultiItem { struct Item { std::vector dives; std::vector label; }; double lowerBound, upperBound; std::vector items; QString binName; }; // If the horizontal flag is true, independent variable is plotted on the y-axis. // A non-empty valueBinNames vector flags that this is a stacked bar chart. // In that case, a valueVariable must also be provided. // For count-based bar series in one variable, valueVariable is null. // Note: this expects that all items are added with increasing pos // and that no bar is inside another bar, i.e. lowerBound and upperBound // are ordered identically. BarSeries(StatsView &view, StatsAxis *xAxis, StatsAxis *yAxis, bool horizontal, const QString &categoryName, std::vector items); BarSeries(StatsView &view, StatsAxis *xAxis, StatsAxis *yAxis, bool horizontal, const QString &categoryName, const StatsVariable *valueVariable, std::vector items); BarSeries(StatsView &view, StatsAxis *xAxis, StatsAxis *yAxis, bool horizontal, bool stacked, const QString &categoryName, const StatsVariable *valueVariable, std::vector valueBinNames, std::vector items); ~BarSeries(); void updatePositions() override; bool hover(QPointF pos) override; void unhighlight() override; bool selectItemsUnderMouse(const QPointF &point, SelectionModifier modifier) override; private: BarSeries(StatsView &view, StatsAxis *xAxis, StatsAxis *yAxis, bool horizontal, bool stacked, const QString &categoryName, const StatsVariable *valueVariable, std::vector valueBinNames); struct Index { int bar; int subitem; Index(); Index(int bar, int subitem); bool operator==(const Index &i2) const; bool operator<=(const Index &i2) const; }; void inc(Index &index); // Get item under mouse pointer, or -1 if none Index getItemUnderMouse(const QPointF &f) const; // A label that is composed of multiple lines struct BarLabel { ChartItemPtr item; bool isOutside; // Is shown outside of bar BarLabel(StatsView &view, const std::vector &labels, int bin_nr, int binCount); void setVisible(bool visible); void updatePosition(bool horizontal, bool center, const QRectF &rect, int bin_nr, int binCount, const QColor &background, const StatsTheme &theme); void highlight(bool highlight, int bin_nr, int binCount, const QColor &background, const StatsTheme &theme); }; struct SubItem { ChartItemPtr item; std::vector dives; std::unique_ptr label; double value_from; double value_to; int bin_nr; bool selected; QColor fill; void updatePosition(BarSeries *series, bool horizontal, bool stacked, double from, double to, int binCount, const StatsTheme &theme); void highlight(bool highlight, int binCount, const StatsTheme &theme); }; struct Item { double lowerBound, upperBound; std::vector subitems; QRectF rect; const QString binName; StatsOperationResults res; int total; Item(BarSeries *series, double lowerBound, double upperBound, std::vector subitems, const QString &binName, const StatsOperationResults &res, int total, bool horizontal, bool stacked, int binCount, const StatsTheme &theme); void updatePosition(BarSeries *series, bool horizontal, bool stacked, int binCount, const StatsTheme &theme); void highlight(int subitem, bool highlight, int binCount, const StatsTheme &theme); int getSubItemUnderMouse(const QPointF &f, bool horizontal, bool stacked) const; }; ChartItemPtr information; std::vector items; bool horizontal; bool stacked; QString categoryName; const StatsVariable *valueVariable; // null: this is count based std::vector valueBinNames; Index highlighted; Index lastClicked; struct SubItemDesc { double v; std::vector dives; std::vector label; }; std::vector makeSubItems(SubItemDesc item) const; std::vector makeSubItems(std::vector items) const; void add_item(double lowerBound, double upperBound, std::vector subitems, const QString &binName, const StatsOperationResults &res, int total, bool horizontal, bool stacked); std::vector makeInfo(const Item &item, int subitem) const; int binCount() const; void divesSelected(const QVector &) override; }; #endif