diff options
author | Berthold Stoeger <bstoeger@mail.tuwien.ac.at> | 2021-01-19 09:54:39 +0100 |
---|---|---|
committer | bstoeger <32835590+bstoeger@users.noreply.github.com> | 2021-01-20 08:47:18 +0100 |
commit | ff536e98fc3e88c3c4fd769229cf901a9f272be0 (patch) | |
tree | 26273be759d7b1536978cabea55bc5ae06b86c2c /stats | |
parent | e32e6d63a7c158a03a851492f4f9d3edffe2f857 (diff) | |
download | subsurface-ff536e98fc3e88c3c4fd769229cf901a9f272be0.tar.gz |
statistics: don't replot chart when changing features
Up to now, when the user changed the visibility of chart features
(legend, quartiles, labels, etc.) the whole chart was replot.
Instead, only change the visibility status of these items.
After all, this modularity is one of the things the conversion
to QSG was all about.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
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; |