mirror of
https://github.com/subsurface/subsurface.git
synced 2024-12-01 06:30:26 +00:00
5a8d7617ce
Allow the user to restrict the analyzed dives based on the current selection. One button restricts to the current selection and one button resets the restriction. Thus, the user can for example select bars in the bar chart or a range in the scatter plot and perform statistics on these sets. The restriction works on top of the filter. The UI can certainly be improved, but it is a start. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
197 lines
7.4 KiB
C++
197 lines
7.4 KiB
C++
// SPDX-License-Identifier: GPL-2.0
|
|
#ifndef STATS_VIEW_H
|
|
#define STATS_VIEW_H
|
|
|
|
#include "statsstate.h"
|
|
#include "statshelper.h"
|
|
#include "statsselection.h"
|
|
#include <memory>
|
|
#include <QFont>
|
|
#include <QImage>
|
|
#include <QPainter>
|
|
#include <QQuickItem>
|
|
|
|
struct dive;
|
|
struct StatsBinner;
|
|
struct StatsBin;
|
|
struct StatsState;
|
|
struct StatsVariable;
|
|
|
|
class StatsSeries;
|
|
class CategoryAxis;
|
|
class ChartItem;
|
|
class ChartRectLineItem;
|
|
class ChartTextItem;
|
|
class CountAxis;
|
|
class HistogramAxis;
|
|
class HistogramMarker;
|
|
class QuartileMarker;
|
|
class RegressionItem;
|
|
class StatsAxis;
|
|
class StatsGrid;
|
|
class Legend;
|
|
class QSGTexture;
|
|
class RootNode; // Internal implementation detail
|
|
|
|
enum class ChartSubType : int;
|
|
enum class ChartZValue : int;
|
|
enum class StatsOperation : int;
|
|
|
|
class StatsView : public QQuickItem {
|
|
Q_OBJECT
|
|
public:
|
|
StatsView();
|
|
StatsView(QQuickItem *parent);
|
|
~StatsView();
|
|
|
|
void plot(const StatsState &state);
|
|
void updateFeatures(const StatsState &state); // Updates the visibility of chart features, such as legend, regression, etc.
|
|
void restrictToSelection();
|
|
void unrestrict();
|
|
int restrictionCount() const; // <0: no restriction
|
|
QQuickWindow *w() const; // Make window available to items
|
|
QSizeF size() const;
|
|
QRectF plotArea() const;
|
|
void addQSGNode(QSGNode *node, ChartZValue z); // Must only be called in render thread!
|
|
void registerChartItem(ChartItem &item);
|
|
void registerDirtyChartItem(ChartItem &item);
|
|
void emergencyShutdown(); // Called when QQuick decides to delete our root node.
|
|
|
|
// Create a chart item and add it to the scene.
|
|
// The item must not be deleted by the caller, but can be
|
|
// scheduled for deletion using deleteChartItem() below.
|
|
// Most items can be made invisible, which is preferred over deletion.
|
|
// All items on the scene will be deleted once the chart is reset.
|
|
template <typename T, class... Args>
|
|
ChartItemPtr<T> createChartItem(Args&&... args);
|
|
|
|
template <typename T>
|
|
void deleteChartItem(ChartItemPtr<T> &item);
|
|
private slots:
|
|
void replotIfVisible();
|
|
void divesSelected(const QVector<dive *> &dives);
|
|
private:
|
|
// QtQuick related things
|
|
bool backgroundDirty;
|
|
QRectF plotRect;
|
|
QSGNode *updatePaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNodeData *updatePaintNodeData) override;
|
|
|
|
void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) override;
|
|
void plotAreaChanged(const QSizeF &size);
|
|
void reset(); // clears all series and axes
|
|
void setAxes(StatsAxis *x, StatsAxis *y);
|
|
void plotBarChart(const std::vector<dive *> &dives,
|
|
ChartSubType subType,
|
|
const StatsVariable *categoryVariable, const StatsBinner *categoryBinner,
|
|
const StatsVariable *valueVariable, const StatsBinner *valueBinner);
|
|
void plotValueChart(const std::vector<dive *> &dives,
|
|
ChartSubType subType,
|
|
const StatsVariable *categoryVariable, const StatsBinner *categoryBinner,
|
|
const StatsVariable *valueVariable, StatsOperation valueAxisOperation);
|
|
void plotDiscreteCountChart(const std::vector<dive *> &dives,
|
|
ChartSubType subType,
|
|
const StatsVariable *categoryVariable, const StatsBinner *categoryBinner);
|
|
void plotPieChart(const std::vector<dive *> &dives,
|
|
const StatsVariable *categoryVariable, const StatsBinner *categoryBinner);
|
|
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);
|
|
void plotHistogramCountChart(const std::vector<dive *> &dives,
|
|
ChartSubType subType,
|
|
const StatsVariable *categoryVariable, const StatsBinner *categoryBinner);
|
|
void plotHistogramValueChart(const std::vector<dive *> &dives,
|
|
ChartSubType subType,
|
|
const StatsVariable *categoryVariable, const StatsBinner *categoryBinner,
|
|
const StatsVariable *valueVariable, StatsOperation valueAxisOperation);
|
|
void plotHistogramStackedChart(const std::vector<dive *> &dives,
|
|
ChartSubType subType,
|
|
const StatsVariable *categoryVariable, const StatsBinner *categoryBinner,
|
|
const StatsVariable *valueVariable, const StatsBinner *valueBinner);
|
|
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 &);
|
|
void updateTitlePos(); // After resizing, set title to correct position
|
|
void plotChart();
|
|
void updateFeatures(); // Updates the visibility of chart features, such as legend, regression, etc.
|
|
|
|
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);
|
|
|
|
StatsState state;
|
|
QFont titleFont;
|
|
std::vector<std::unique_ptr<StatsSeries>> series;
|
|
std::unique_ptr<StatsGrid> grid;
|
|
std::vector<ChartItemPtr<QuartileMarker>> quartileMarkers;
|
|
ChartItemPtr<HistogramMarker> medianMarker, meanMarker;
|
|
StatsSeries *highlightedSeries;
|
|
StatsAxis *xAxis, *yAxis;
|
|
ChartItemPtr<ChartTextItem> title;
|
|
ChartItemPtr<Legend> legend;
|
|
Legend *draggedItem;
|
|
ChartItemPtr<RegressionItem> regressionItem;
|
|
ChartItemPtr<ChartRectLineItem> selectionRect;
|
|
QPointF dragStartMouse, dragStartItem;
|
|
SelectionModifier selectionModifier;
|
|
std::vector<dive *> oldSelection;
|
|
bool restrictDives;
|
|
std::vector<dive *> restrictedDives; // sorted by pointer for quick lookup.
|
|
|
|
void hoverEnterEvent(QHoverEvent *event) override;
|
|
void hoverMoveEvent(QHoverEvent *event) override;
|
|
void mousePressEvent(QMouseEvent *event) override;
|
|
void mouseReleaseEvent(QMouseEvent *event) override;
|
|
void mouseMoveEvent(QMouseEvent *event) override;
|
|
RootNode *rootNode;
|
|
|
|
// There are three double linked lists of chart items:
|
|
// clean items, dirty items and items to be deleted.
|
|
// Note that only the render thread must delete chart items,
|
|
// and therefore these lists are the only owning pointers
|
|
// to chart items. All other pointers are non-owning and
|
|
// can therefore become stale.
|
|
struct ChartItemList {
|
|
ChartItemList();
|
|
ChartItem *first, *last;
|
|
void append(ChartItem &item);
|
|
void remove(ChartItem &item);
|
|
void clear();
|
|
void splice(ChartItemList &list);
|
|
};
|
|
ChartItemList cleanItems, dirtyItems, deletedItems;
|
|
void deleteChartItemInternal(ChartItem &item);
|
|
void freeDeletedChartItems();
|
|
};
|
|
|
|
// This implementation detail must be known to users of the class.
|
|
// Perhaps move it into a statsview_impl.h file.
|
|
template <typename T, class... Args>
|
|
ChartItemPtr<T> StatsView::createChartItem(Args&&... args)
|
|
{
|
|
return ChartItemPtr(new T(*this, std::forward<Args>(args)...));
|
|
}
|
|
|
|
template <typename T>
|
|
void StatsView::deleteChartItem(ChartItemPtr<T> &item)
|
|
{
|
|
deleteChartItemInternal(*item);
|
|
item.reset();
|
|
}
|
|
|
|
#endif
|