subsurface/stats/statsstate.h
Berthold Stoeger 7b0455b4d8 statistics: reverse chart selection logic
The old ways was to select the chart first, then depending on
the chart choose the binning.

Willem says that it should work the other way round: select
the binning (or operation) and make the charts depend on
that.

I'm not arguing one way or the other, just note that the new
way is much more tricky, because it is easy to get unsupported
combinations. For example, there is no chart where the
first variable is unbinned, but the second axis is binned
or has an operation. This makes things distinctly more tricky
and this code still needs a thorough audit.

Since this is all more tricky, implement a "invalid" chart
state. Ideally that should be never shown to the user, but
let's try to be defensive.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-01-03 13:41:15 -08:00

119 lines
2.3 KiB
C++

// SPDX-License-Identifier: GPL-2.0
// Describes the current state of the statistics widget
// (selected variables, chart type, etc.) and is the
// interface between UI and plotting code.
#ifndef STATS_STATE_H
#define STATS_STATE_H
#include <vector>
#include <QString>
enum class ChartType {
DiscreteBar,
DiscreteValue,
DiscreteCount,
DiscreteBox,
DiscreteScatter,
Pie,
HistogramCount,
HistogramValue,
HistogramBox,
HistogramStacked,
ScatterPlot,
Invalid
};
enum class ChartSubType {
Vertical = 0,
VerticalGrouped,
VerticalStacked,
Horizontal,
HorizontalGrouped,
HorizontalStacked,
Dots,
Box,
Pie,
Count
};
struct ChartTypeDesc; // Internal implementation detail
struct StatsVariable;
struct StatsBinner;
enum class StatsOperation : int;
struct StatsState {
public:
StatsState();
int setFirstAxis();
int setSecondAxis();
struct Variable {
QString name;
int id;
};
struct VariableList {
std::vector<Variable> variables;
int selected;
};
struct Chart {
QString name;
QString subtypeName;
ChartSubType subtype;
int id;
bool warning; // Not recommended for that combination
};
struct ChartList {
std::vector<Chart> charts;
int selected;
};
struct BinnerList {
std::vector<QString> binners;
int selected;
};
struct Feature {
QString name;
int id;
bool selected;
};
struct UIState {
VariableList var1;
VariableList var2;
QString var1Name;
QString var2Name;
ChartList charts;
std::vector<Feature> features;
BinnerList binners1;
BinnerList binners2;
// Currently, operations are only supported on the second variable
// This reuses the variable list - not very nice.
VariableList operations2;
};
UIState getUIState() const;
// State changers
void var1Changed(int id);
void var2Changed(int id);
void chartChanged(int id);
void binner1Changed(int id);
void binner2Changed(int id);
void var2OperationChanged(int id);
void featureChanged(int id, bool state);
const StatsVariable *var1; // Independent variable
const StatsVariable *var2; // Dependent variable (nullptr: count)
ChartType type;
ChartSubType subtype;
bool labels;
bool legend;
bool median;
bool mean;
bool quartiles;
const StatsBinner *var1Binner; // nullptr: undefined
const StatsBinner *var2Binner; // nullptr: undefined
StatsOperation var2Operation;
private:
void validate(bool varChanged);
int chartFeatures;
};
#endif