aboutsummaryrefslogtreecommitdiffstats
path: root/stats/statsview.h
diff options
context:
space:
mode:
Diffstat (limited to 'stats/statsview.h')
-rw-r--r--stats/statsview.h138
1 files changed, 138 insertions, 0 deletions
diff --git a/stats/statsview.h b/stats/statsview.h
new file mode 100644
index 000000000..c65a4232a
--- /dev/null
+++ b/stats/statsview.h
@@ -0,0 +1,138 @@
+// SPDX-License-Identifier: GPL-2.0
+#ifndef STATS_VIEW_H
+#define STATS_VIEW_H
+
+#include "statsstate.h"
+#include <memory>
+#include <QQuickWidget>
+
+struct dive;
+struct StatsBinner;
+struct StatsBin;
+struct StatsState;
+struct StatsVariable;
+
+namespace QtCharts {
+ class QAbstractSeries;
+ class QChart;
+}
+class QGraphicsLineItem;
+class StatsSeries;
+class CategoryAxis;
+class CountAxis;
+class HistogramAxis;
+class StatsAxis;
+class Legend;
+
+enum class ChartSubType : int;
+enum class StatsOperation : int;
+
+class StatsView : public QQuickWidget {
+ Q_OBJECT
+public:
+ StatsView(QWidget *parent = NULL);
+ ~StatsView();
+
+ void plot(const StatsState &state);
+private slots:
+ void plotAreaChanged(const QRectF &plotArea);
+ void replotIfVisible();
+private:
+ void reset(); // clears all series and axes
+ void addAxes(StatsAxis *x, StatsAxis *y); // Add new x- and y-axis
+ void plotBarChart(const std::vector<dive *> &dives,
+ ChartSubType subType,
+ const StatsVariable *categoryVariable, const StatsBinner *categoryBinner,
+ const StatsVariable *valueVariable, const StatsBinner *valueBinner, bool labels, bool legend);
+ void plotValueChart(const std::vector<dive *> &dives,
+ ChartSubType subType,
+ const StatsVariable *categoryVariable, const StatsBinner *categoryBinner,
+ const StatsVariable *valueVariable, StatsOperation valueAxisOperation, bool labels);
+ void plotDiscreteCountChart(const std::vector<dive *> &dives,
+ ChartSubType subType,
+ const StatsVariable *categoryVariable, const StatsBinner *categoryBinner, bool labels);
+ void plotPieChart(const std::vector<dive *> &dives,
+ const StatsVariable *categoryVariable, const StatsBinner *categoryBinner, bool labels, bool legend);
+ void plotDiscreteBoxChart(const std::vector<dive *> &dives,
+ const StatsVariable *categoryVariable, const StatsBinner *categoryBinner, const StatsVariable *valueVariable);
+ void plotDiscreteScatter(const std::vector<dive *> &dives,
+ const StatsVariable *categoryVariable, const StatsBinner *categoryBinner,
+ const StatsVariable *valueVariable, bool quartiles);
+ void plotHistogramCountChart(const std::vector<dive *> &dives,
+ ChartSubType subType,
+ const StatsVariable *categoryVariable, const StatsBinner *categoryBinner,
+ bool labels, bool showMedian, bool showMean);
+ void plotHistogramValueChart(const std::vector<dive *> &dives,
+ ChartSubType subType,
+ const StatsVariable *categoryVariable, const StatsBinner *categoryBinner,
+ const StatsVariable *valueVariable, StatsOperation valueAxisOperation, bool labels);
+ void plotHistogramStackedChart(const std::vector<dive *> &dives,
+ ChartSubType subType,
+ const StatsVariable *categoryVariable, const StatsBinner *categoryBinner,
+ const StatsVariable *valueVariable, const StatsBinner *valueBinner, bool labels, bool legend);
+ void plotHistogramBoxChart(const std::vector<dive *> &dives,
+ const StatsVariable *categoryVariable, const StatsBinner *categoryBinner, const StatsVariable *valueVariable);
+ void plotScatter(const std::vector<dive *> &dives, const StatsVariable *categoryVariable, const StatsVariable *valueVariable);
+ void setTitle(const QString &);
+
+ template <typename T, class... Args>
+ T *createSeries(Args&&... args);
+
+ template <typename T, class... Args>
+ T *createAxis(const QString &title, Args&&... args);
+
+ template<typename T>
+ CategoryAxis *createCategoryAxis(const QString &title, const StatsBinner &binner,
+ const std::vector<T> &bins, bool isHorizontal);
+ template<typename T>
+ HistogramAxis *createHistogramAxis(const QString &title, const StatsBinner &binner,
+ const std::vector<T> &bins, bool isHorizontal);
+ CountAxis *createCountAxis(int maxVal, bool isHorizontal);
+
+ // Helper functions to add feature to the chart
+ void addLineMarker(double pos, double low, double high, const QPen &pen, bool isHorizontal);
+
+ // A short line used to mark quartiles
+ struct QuartileMarker {
+ std::unique_ptr<QGraphicsLineItem> item;
+ QtCharts::QAbstractSeries *series; // In case we ever support charts with multiple axes
+ double pos, value;
+ QuartileMarker(double pos, double value, QtCharts::QAbstractSeries *series);
+ void updatePosition();
+ };
+
+ // A general line marker
+ struct LineMarker {
+ std::unique_ptr<QGraphicsLineItem> item;
+ QtCharts::QAbstractSeries *series; // In case we ever support charts with multiple axes
+ QPointF from, to; // In local coordinates
+ void updatePosition();
+ LineMarker(QPointF from, QPointF to, QPen pen, QtCharts::QAbstractSeries *series);
+ };
+
+ void addLinearRegression(double a, double b, double minX, double maxX, QtCharts::QAbstractSeries *series);
+ void addHistogramMarker(double pos, double low, double high, const QPen &pen, bool isHorizontal, QtCharts::QAbstractSeries *series);
+
+ StatsState state;
+ QtCharts::QChart *chart;
+ std::vector<std::unique_ptr<StatsAxis>> axes;
+ std::vector<std::unique_ptr<StatsSeries>> series;
+ std::unique_ptr<Legend> legend;
+ std::vector<QuartileMarker> quartileMarkers;
+ std::vector<LineMarker> lineMarkers;
+ StatsSeries *highlightedSeries;
+
+ // This is unfortunate: we can't derive from QChart, because the chart is allocated by QML.
+ // Therefore, we have to listen to hover events using an events-filter.
+ // Probably we should try to get rid of the QML ChartView.
+ struct EventFilter : public QObject {
+ StatsView *view;
+ EventFilter(StatsView *view) : view(view) {}
+ private:
+ bool eventFilter(QObject *o, QEvent *event);
+ } eventFilter;
+ friend EventFilter;
+ void hover(QPointF pos);
+};
+
+#endif