diff options
Diffstat (limited to 'stats')
-rw-r--r-- | stats/pieseries.cpp | 20 | ||||
-rw-r--r-- | stats/pieseries.h | 4 | ||||
-rw-r--r-- | stats/statsview.cpp | 154 | ||||
-rw-r--r-- | stats/statsview.h | 24 |
4 files changed, 104 insertions, 98 deletions
diff --git a/stats/pieseries.cpp b/stats/pieseries.cpp index a100d66e0..50c76a8ed 100644 --- a/stats/pieseries.cpp +++ b/stats/pieseries.cpp @@ -17,7 +17,7 @@ static const double innerLabelRadius = 0.75; // 1.0 = at outer border of pie static const double outerLabelRadius = 1.01; // 1.0 = at outer border of pie PieSeries::Item::Item(StatsView &view, const QString &name, int from, int count, int totalCount, - int bin_nr, int numBins, bool labels) : + int bin_nr, int numBins) : name(name), count(count) { @@ -30,14 +30,12 @@ PieSeries::Item::Item(StatsView &view, const QString &name, int from, int count, innerLabelPos = QPointF(cos(meanAngle) * innerLabelRadius, -sin(meanAngle) * innerLabelRadius); outerLabelPos = QPointF(cos(meanAngle) * outerLabelRadius, -sin(meanAngle) * outerLabelRadius); - if (labels) { - double percentage = count * 100.0 / totalCount; - QString innerLabelText = QStringLiteral("%1\%").arg(loc.toString(percentage, 'f', 1)); - innerLabel = view.createChartItem<ChartTextItem>(ChartZValue::SeriesLabels, f, innerLabelText); + double percentage = count * 100.0 / totalCount; + QString innerLabelText = QStringLiteral("%1\%").arg(loc.toString(percentage, 'f', 1)); + innerLabel = view.createChartItem<ChartTextItem>(ChartZValue::SeriesLabels, f, innerLabelText); - outerLabel = view.createChartItem<ChartTextItem>(ChartZValue::SeriesLabels, f, name); - outerLabel->setColor(darkLabelColor); - } + outerLabel = view.createChartItem<ChartTextItem>(ChartZValue::SeriesLabels, f, name); + outerLabel->setColor(darkLabelColor); } void PieSeries::Item::updatePositions(const QPointF ¢er, double radius) @@ -75,7 +73,7 @@ void PieSeries::Item::highlight(ChartPieItem &item, int bin_nr, bool highlight, } PieSeries::PieSeries(StatsView &view, StatsAxis *xAxis, StatsAxis *yAxis, const QString &categoryName, - const std::vector<std::pair<QString, int>> &data, bool keepOrder, bool labels) : + const std::vector<std::pair<QString, int>> &data, bool keepOrder) : StatsSeries(view, xAxis, yAxis), item(view.createChartItem<ChartPieItem>(ChartZValue::Series, pieBorderWidth)), categoryName(categoryName), @@ -137,7 +135,7 @@ PieSeries::PieSeries(StatsView &view, StatsAxis *xAxis, StatsAxis *yAxis, const int act = 0; for (auto it2 = sorted.begin(); it2 != it; ++it2) { int count = data[*it2].second; - items.emplace_back(view, data[*it2].first, act, count, totalCount, (int)items.size(), numBins, labels); + items.emplace_back(view, data[*it2].first, act, count, totalCount, (int)items.size(), numBins); act += count; } @@ -147,7 +145,7 @@ PieSeries::PieSeries(StatsView &view, StatsAxis *xAxis, StatsAxis *yAxis, const for (auto it2 = it; it2 != sorted.end(); ++it2) other.push_back({ data[*it2].first, data[*it2].second }); QString name = StatsTranslations::tr("other (%1 items)").arg(other.size()); - items.emplace_back(view, name, act, totalCount - act, totalCount, (int)items.size(), numBins, labels); + items.emplace_back(view, name, act, totalCount - act, totalCount, (int)items.size(), numBins); } } diff --git a/stats/pieseries.h b/stats/pieseries.h index a75909efe..0cb5e12cb 100644 --- a/stats/pieseries.h +++ b/stats/pieseries.h @@ -21,7 +21,7 @@ public: // If keepOrder is false, bins will be sorted by size, otherwise the sorting // of the shown bins will be retained. Small bins are omitted for clarity. PieSeries(StatsView &view, StatsAxis *xAxis, StatsAxis *yAxis, const QString &categoryName, - const std::vector<std::pair<QString, int>> &data, bool keepOrder, bool labels); + const std::vector<std::pair<QString, int>> &data, bool keepOrder); ~PieSeries(); void updatePositions() override; @@ -45,7 +45,7 @@ private: int count; QPointF innerLabelPos, outerLabelPos; // With respect to a (-1, -1)-(1, 1) rectangle. Item(StatsView &view, const QString &name, int from, int count, int totalCount, - int bin_nr, int numBins, bool labels); + int bin_nr, int numBins); void updatePositions(const QPointF ¢er, double radius); void highlight(ChartPieItem &item, int bin_nr, bool highlight, int numBins); }; diff --git a/stats/statsview.cpp b/stats/statsview.cpp index 5d7183fc3..e5cd0f8be 100644 --- a/stats/statsview.cpp +++ b/stats/statsview.cpp @@ -80,13 +80,17 @@ void StatsView::mouseReleaseEvent(QMouseEvent *) } } +// Define a hideable dummy QSG node that is used as a parent node to make +// all objects of a z-level visible / invisible. +using ZNode = HideableQSGNode<QSGNode>; + class RootNode : public QSGNode { public: RootNode(QQuickWindow *w); std::unique_ptr<QSGRectangleNode> backgroundNode; // solid background // We entertain one node per Z-level. - std::array<std::unique_ptr<QSGNode>, (size_t)ChartZValue::Count> zNodes; + std::array<std::unique_ptr<ZNode>, (size_t)ChartZValue::Count> zNodes; }; RootNode::RootNode(QQuickWindow *w) @@ -99,7 +103,7 @@ RootNode::RootNode(QQuickWindow *w) appendChildNode(backgroundNode.get()); for (auto &zNode: zNodes) { - zNode.reset(new QSGNode); + zNode.reset(new ZNode(true)); appendChildNode(zNode.get()); } } @@ -268,8 +272,10 @@ void StatsView::plotAreaChanged(const QSizeF &s) marker->updatePosition(); if (regressionItem) regressionItem->updatePosition(); - for (auto &marker: histogramMarkers) - marker->updatePosition(); + if (meanMarker) + meanMarker->updatePosition(); + if (medianMarker) + medianMarker->updatePosition(); if (legend) legend->resize(); updateTitlePos(); @@ -369,6 +375,8 @@ void StatsView::reset() title.reset(); legend.reset(); regressionItem.reset(); + meanMarker.reset(); + medianMarker.reset(); // Mark clean and dirty chart items for deletion cleanItems.splice(deletedItems); @@ -376,7 +384,6 @@ void StatsView::reset() series.clear(); quartileMarkers.clear(); - histogramMarkers.clear(); grid.reset(); } @@ -384,10 +391,18 @@ void StatsView::plot(const StatsState &stateIn) { state = stateIn; plotChart(); + updateFeatures(); // Show / hide chart features, such as legend, etc. plotAreaChanged(boundingRect().size()); update(); } +void StatsView::updateFeatures(const StatsState &stateIn) +{ + state = stateIn; + updateFeatures(); + update(); +} + void StatsView::plotChart() { if (!state.var1) @@ -398,27 +413,26 @@ void StatsView::plotChart() switch (state.type) { case ChartType::DiscreteBar: return plotBarChart(dives, state.subtype, state.var1, state.var1Binner, state.var2, - state.var2Binner, state.labels, state.legend); + state.var2Binner); case ChartType::DiscreteValue: return plotValueChart(dives, state.subtype, state.var1, state.var1Binner, state.var2, - state.var2Operation, state.labels); + state.var2Operation); case ChartType::DiscreteCount: - return plotDiscreteCountChart(dives, state.subtype, state.var1, state.var1Binner, state.labels); + return plotDiscreteCountChart(dives, state.subtype, state.var1, state.var1Binner); case ChartType::Pie: - return plotPieChart(dives, state.var1, state.var1Binner, state.labels, state.legend); + return plotPieChart(dives, state.var1, state.var1Binner); case ChartType::DiscreteBox: return plotDiscreteBoxChart(dives, state.var1, state.var1Binner, state.var2); case ChartType::DiscreteScatter: - return plotDiscreteScatter(dives, state.var1, state.var1Binner, state.var2, state.quartiles); + return plotDiscreteScatter(dives, state.var1, state.var1Binner, state.var2); case ChartType::HistogramCount: - return plotHistogramCountChart(dives, state.subtype, state.var1, state.var1Binner, - state.labels, state.median, state.mean); + return plotHistogramCountChart(dives, state.subtype, state.var1, state.var1Binner); case ChartType::HistogramValue: return plotHistogramValueChart(dives, state.subtype, state.var1, state.var1Binner, state.var2, - state.var2Operation, state.labels); + state.var2Operation); case ChartType::HistogramStacked: return plotHistogramStackedChart(dives, state.subtype, state.var1, state.var1Binner, - state.var2, state.var2Binner, state.labels, state.legend); + state.var2, state.var2Binner); case ChartType::HistogramBox: return plotHistogramBoxChart(dives, state.var1, state.var1Binner, state.var2); case ChartType::ScatterPlot: @@ -431,6 +445,25 @@ void StatsView::plotChart() } } +void StatsView::updateFeatures() +{ + if (legend) + legend->setVisible(state.legend); + + // For labels, we are brutal: simply show/hide the whole z-level with the labels + if (rootNode) + rootNode->zNodes[(int)ChartZValue::SeriesLabels]->setVisible(state.labels); + + if (meanMarker) + meanMarker->setVisible(state.mean); + + if (medianMarker) + medianMarker->setVisible(state.median); + + for (ChartItemPtr<QuartileMarker> &marker: quartileMarkers) + marker->setVisible(state.quartiles); +} + template<typename T> CategoryAxis *StatsView::createCategoryAxis(const QString &name, const StatsBinner &binner, const std::vector<T> &bins, bool isHorizontal) @@ -517,14 +550,12 @@ static std::vector<QString> makePercentageLabels(int count, int total, bool isHo // From a list of counts, make (count, label) pairs, where the label // formats the total number and the percentage of dives. -static std::vector<std::pair<int, std::vector<QString>>> makeCountLabels(const std::vector<int> &counts, int total, - bool labels, bool isHorizontal) +static std::vector<std::pair<int, std::vector<QString>>> makeCountLabels(const std::vector<int> &counts, int total, bool isHorizontal) { std::vector<std::pair<int, std::vector<QString>>> count_labels; count_labels.reserve(counts.size()); for (int count: counts) { - std::vector<QString> label = labels ? makePercentageLabels(count, total, isHorizontal) - : std::vector<QString>(); + std::vector<QString> label = makePercentageLabels(count, total, isHorizontal); count_labels.push_back(std::make_pair(count, label)); } return count_labels; @@ -533,7 +564,7 @@ static std::vector<std::pair<int, std::vector<QString>>> makeCountLabels(const s void StatsView::plotBarChart(const std::vector<dive *> &dives, ChartSubType subType, const StatsVariable *categoryVariable, const StatsBinner *categoryBinner, - const StatsVariable *valueVariable, const StatsBinner *valueBinner, bool labels, bool showLegend) + const StatsVariable *valueVariable, const StatsBinner *valueBinner) { if (!categoryBinner || !valueBinner) return; @@ -561,14 +592,13 @@ void StatsView::plotBarChart(const std::vector<dive *> &dives, setAxes(catAxis, valAxis); // Paint legend first, because the bin-names will be moved away from. - if (showLegend) - legend = createChartItem<Legend>(data.vbinNames); + legend = createChartItem<Legend>(data.vbinNames); std::vector<BarSeries::MultiItem> items; items.reserve(data.hbin_counts.size()); double pos = 0.0; for (auto &[hbin, counts, total]: data.hbin_counts) { - items.push_back({ pos - 0.5, pos + 0.5, makeCountLabels(counts, total, labels, isHorizontal), + items.push_back({ pos - 0.5, pos + 0.5, makeCountLabels(counts, total, isHorizontal), categoryBinner->formatWithUnit(*hbin) }); pos += 1.0; } @@ -645,8 +675,7 @@ static std::pair<double, double> getMinMaxValue(const std::vector<StatsBinOp> &b void StatsView::plotValueChart(const std::vector<dive *> &dives, ChartSubType subType, const StatsVariable *categoryVariable, const StatsBinner *categoryBinner, - const StatsVariable *valueVariable, StatsOperation valueAxisOperation, - bool labels) + const StatsVariable *valueVariable, StatsOperation valueAxisOperation) { if (!categoryBinner) return; @@ -681,8 +710,7 @@ void StatsView::plotValueChart(const std::vector<dive *> &dives, if (res.isValid()) { double height = res.get(valueAxisOperation); QString value = QString("%L1").arg(height, 0, 'f', decimals); - std::vector<QString> label = labels ? std::vector<QString> { value } - : std::vector<QString>(); + std::vector<QString> label = std::vector<QString> { value }; items.push_back({ pos - 0.5, pos + 0.5, height, label, categoryBinner->formatWithUnit(*bin), res }); } @@ -713,8 +741,7 @@ static int getMaxCount(const std::vector<T> &bins) void StatsView::plotDiscreteCountChart(const std::vector<dive *> &dives, ChartSubType subType, - const StatsVariable *categoryVariable, const StatsBinner *categoryBinner, - bool labels) + const StatsVariable *categoryVariable, const StatsBinner *categoryBinner) { if (!categoryBinner) return; @@ -745,8 +772,7 @@ void StatsView::plotDiscreteCountChart(const std::vector<dive *> &dives, items.reserve(categoryBins.size()); double pos = 0.0; for (auto const &[bin, count]: categoryBins) { - std::vector<QString> label = labels ? makePercentageLabels(count, total, isHorizontal) - : std::vector<QString>(); + std::vector<QString> label = makePercentageLabels(count, total, isHorizontal); items.push_back({ pos - 0.5, pos + 0.5, count, label, categoryBinner->formatWithUnit(*bin), total }); pos += 1.0; @@ -756,8 +782,7 @@ void StatsView::plotDiscreteCountChart(const std::vector<dive *> &dives, } void StatsView::plotPieChart(const std::vector<dive *> &dives, - const StatsVariable *categoryVariable, const StatsBinner *categoryBinner, - bool labels, bool showLegend) + const StatsVariable *categoryVariable, const StatsBinner *categoryBinner) { if (!categoryBinner) return; @@ -776,10 +801,9 @@ void StatsView::plotPieChart(const std::vector<dive *> &dives, data.emplace_back(categoryBinner->formatWithUnit(*bin), count); bool keepOrder = categoryVariable->type() != StatsVariable::Type::Discrete; - PieSeries *series = createSeries<PieSeries>(categoryVariable->name(), data, keepOrder, labels); + PieSeries *series = createSeries<PieSeries>(categoryVariable->name(), data, keepOrder); - if (showLegend) - legend = createChartItem<Legend>(series->binNames()); + legend = createChartItem<Legend>(series->binNames()); } void StatsView::plotDiscreteBoxChart(const std::vector<dive *> &dives, @@ -818,7 +842,7 @@ void StatsView::plotDiscreteBoxChart(const std::vector<dive *> &dives, void StatsView::plotDiscreteScatter(const std::vector<dive *> &dives, const StatsVariable *categoryVariable, const StatsBinner *categoryBinner, - const StatsVariable *valueVariable, bool quartiles) + const StatsVariable *valueVariable) { if (!categoryBinner) return; @@ -846,26 +870,19 @@ void StatsView::plotDiscreteScatter(const std::vector<dive *> &dives, for (const auto &[bin, array]: categoryBins) { for (auto [v, d]: array) series->append(d, x, v); - if (quartiles) { - StatsQuartiles quartiles = StatsVariable::quartiles(array); - if (quartiles.isValid()) { - quartileMarkers.push_back(createChartItem<QuartileMarker>( - x, quartiles.q1, catAxis, valAxis)); - quartileMarkers.push_back(createChartItem<QuartileMarker>( - x, quartiles.q2, catAxis, valAxis)); - quartileMarkers.push_back(createChartItem<QuartileMarker>( - x, quartiles.q3, catAxis, valAxis)); - } + StatsQuartiles quartiles = StatsVariable::quartiles(array); + if (quartiles.isValid()) { + quartileMarkers.push_back(createChartItem<QuartileMarker>( + x, quartiles.q1, catAxis, valAxis)); + quartileMarkers.push_back(createChartItem<QuartileMarker>( + x, quartiles.q2, catAxis, valAxis)); + quartileMarkers.push_back(createChartItem<QuartileMarker>( + x, quartiles.q3, catAxis, valAxis)); } x += 1.0; } } -void StatsView::addHistogramMarker(double pos, QColor color, bool isHorizontal, StatsAxis *xAxis, StatsAxis *yAxis) -{ - histogramMarkers.push_back(createChartItem<HistogramMarker>(pos, isHorizontal, color, xAxis, yAxis)); -} - // Yikes, we get our data in different kinds of (bin, value) pairs. // To create a category axis from this, we have to templatify the function. template<typename T> @@ -890,8 +907,7 @@ HistogramAxis *StatsView::createHistogramAxis(const QString &name, const StatsBi void StatsView::plotHistogramCountChart(const std::vector<dive *> &dives, ChartSubType subType, - const StatsVariable *categoryVariable, const StatsBinner *categoryBinner, - bool labels, bool showMedian, bool showMean) + const StatsVariable *categoryVariable, const StatsBinner *categoryBinner) { if (!categoryBinner) return; @@ -924,8 +940,7 @@ void StatsView::plotHistogramCountChart(const std::vector<dive *> &dives, for (auto const &[bin, count]: categoryBins) { double lowerBound = categoryBinner->lowerBoundToFloat(*bin); double upperBound = categoryBinner->upperBoundToFloat(*bin); - std::vector<QString> label = labels ? makePercentageLabels(count, total, isHorizontal) - : std::vector<QString>(); + std::vector<QString> label = makePercentageLabels(count, total, isHorizontal); items.push_back({ lowerBound, upperBound, count, label, categoryBinner->formatWithUnit(*bin), total }); @@ -934,24 +949,19 @@ void StatsView::plotHistogramCountChart(const std::vector<dive *> &dives, createSeries<BarSeries>(isHorizontal, categoryVariable->name(), items); if (categoryVariable->type() == StatsVariable::Type::Numeric) { - if (showMean) { - double mean = categoryVariable->mean(dives); - if (!std::isnan(mean)) - addHistogramMarker(mean, Qt::green, isHorizontal, xAxis, yAxis); - } - if (showMedian) { - double median = categoryVariable->quartiles(dives).q2; - if (!std::isnan(median)) - addHistogramMarker(median, Qt::red, isHorizontal, xAxis, yAxis); - } + double mean = categoryVariable->mean(dives); + if (!std::isnan(mean)) + meanMarker = createChartItem<HistogramMarker>(mean, isHorizontal, Qt::green, xAxis, yAxis); + double median = categoryVariable->quartiles(dives).q2; + if (!std::isnan(median)) + medianMarker = createChartItem<HistogramMarker>(median, isHorizontal, Qt::red, xAxis, yAxis); } } void StatsView::plotHistogramValueChart(const std::vector<dive *> &dives, ChartSubType subType, const StatsVariable *categoryVariable, const StatsBinner *categoryBinner, - const StatsVariable *valueVariable, StatsOperation valueAxisOperation, - bool labels) + const StatsVariable *valueVariable, StatsOperation valueAxisOperation) { if (!categoryBinner) return; @@ -990,8 +1000,7 @@ void StatsView::plotHistogramValueChart(const std::vector<dive *> &dives, double lowerBound = categoryBinner->lowerBoundToFloat(*bin); double upperBound = categoryBinner->upperBoundToFloat(*bin); QString value = QString("%L1").arg(height, 0, 'f', decimals); - std::vector<QString> label = labels ? std::vector<QString> { value } - : std::vector<QString>(); + std::vector<QString> label = std::vector<QString> { value }; items.push_back({ lowerBound, upperBound, height, label, categoryBinner->formatWithUnit(*bin), res }); } @@ -1002,7 +1011,7 @@ void StatsView::plotHistogramValueChart(const std::vector<dive *> &dives, void StatsView::plotHistogramStackedChart(const std::vector<dive *> &dives, ChartSubType subType, const StatsVariable *categoryVariable, const StatsBinner *categoryBinner, - const StatsVariable *valueVariable, const StatsBinner *valueBinner, bool labels, bool showLegend) + const StatsVariable *valueVariable, const StatsBinner *valueBinner) { if (!categoryBinner || !valueBinner) return; @@ -1018,8 +1027,7 @@ void StatsView::plotHistogramStackedChart(const std::vector<dive *> &dives, *categoryBinner, categoryBins, !isHorizontal); BarPlotData data(categoryBins, *valueBinner); - if (showLegend) - legend = createChartItem<Legend>(data.vbinNames); + legend = createChartItem<Legend>(data.vbinNames); CountAxis *valAxis = createCountAxis(data.maxCategoryCount, isHorizontal); @@ -1034,7 +1042,7 @@ void StatsView::plotHistogramStackedChart(const std::vector<dive *> &dives, for (auto &[hbin, counts, total]: data.hbin_counts) { double lowerBound = categoryBinner->lowerBoundToFloat(*hbin); double upperBound = categoryBinner->upperBoundToFloat(*hbin); - items.push_back({ lowerBound, upperBound, makeCountLabels(counts, total, labels, isHorizontal), + items.push_back({ lowerBound, upperBound, makeCountLabels(counts, total, isHorizontal), categoryBinner->formatWithUnit(*hbin) }); } diff --git a/stats/statsview.h b/stats/statsview.h index dab666ec8..0af91b382 100644 --- a/stats/statsview.h +++ b/stats/statsview.h @@ -43,7 +43,8 @@ public: ~StatsView(); void plot(const StatsState &state); - QQuickWindow *w() const; // Make window available to items + void updateFeatures(const StatsState &state); // Updates the visibility of chart features, such as legend, regression, etc. + 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! @@ -75,39 +76,39 @@ private: 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); + 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, bool labels); + const StatsVariable *valueVariable, StatsOperation valueAxisOperation); void plotDiscreteCountChart(const std::vector<dive *> &dives, ChartSubType subType, - const StatsVariable *categoryVariable, const StatsBinner *categoryBinner, bool labels); + const StatsVariable *categoryVariable, const StatsBinner *categoryBinner); void plotPieChart(const std::vector<dive *> &dives, - const StatsVariable *categoryVariable, const StatsBinner *categoryBinner, bool labels, bool legend); + 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, bool quartiles); + const StatsVariable *valueVariable); void plotHistogramCountChart(const std::vector<dive *> &dives, ChartSubType subType, - const StatsVariable *categoryVariable, const StatsBinner *categoryBinner, - bool labels, bool showMedian, bool showMean); + 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, bool labels); + 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, bool labels, bool legend); + 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); @@ -126,14 +127,13 @@ private: // Helper functions to add feature to the chart void addLineMarker(double pos, double low, double high, const QPen &pen, bool isHorizontal); - void addHistogramMarker(double pos, QColor color, bool isHorizontal, StatsAxis *xAxis, StatsAxis *yAxis); StatsState state; QFont titleFont; std::vector<std::unique_ptr<StatsSeries>> series; std::unique_ptr<StatsGrid> grid; std::vector<ChartItemPtr<QuartileMarker>> quartileMarkers; - std::vector<ChartItemPtr<HistogramMarker>> histogramMarkers; + ChartItemPtr<HistogramMarker> medianMarker, meanMarker; StatsSeries *highlightedSeries; StatsAxis *xAxis, *yAxis; ChartItemPtr<ChartTextItem> title; |