diff options
author | Berthold Stoeger <bstoeger@mail.tuwien.ac.at> | 2021-02-12 10:56:48 +0100 |
---|---|---|
committer | Dirk Hohndel <dirk@hohndel.org> | 2021-02-13 13:02:54 -0800 |
commit | 5a8d7617ce3d1b54f22a0438f593e844757ecc46 (patch) | |
tree | 3ec045749e4535fa38094300dcb639299e4a7b2d | |
parent | 2943b1cbde1a60ef00f1878a27f811246d9b2bc3 (diff) | |
download | subsurface-5a8d7617ce3d1b54f22a0438f593e844757ecc46.tar.gz |
statistics: implement primitive "restrict to selection" feature
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>
-rw-r--r-- | desktop-widgets/statswidget.cpp | 29 | ||||
-rw-r--r-- | desktop-widgets/statswidget.h | 3 | ||||
-rw-r--r-- | desktop-widgets/statswidget.ui | 26 | ||||
-rw-r--r-- | stats/statsview.cpp | 34 | ||||
-rw-r--r-- | stats/statsview.h | 8 |
5 files changed, 97 insertions, 3 deletions
diff --git a/desktop-widgets/statswidget.cpp b/desktop-widgets/statswidget.cpp index 33174778d..b74a26863 100644 --- a/desktop-widgets/statswidget.cpp +++ b/desktop-widgets/statswidget.cpp @@ -84,6 +84,8 @@ StatsWidget::StatsWidget(QWidget *parent) : QWidget(parent) connect(ui.var1Binner, QOverload<int>::of(&QComboBox::activated), this, &StatsWidget::var1BinnerChanged); connect(ui.var2Binner, QOverload<int>::of(&QComboBox::activated), this, &StatsWidget::var2BinnerChanged); connect(ui.var2Operation, QOverload<int>::of(&QComboBox::activated), this, &StatsWidget::var2OperationChanged); + connect(ui.restrictButton, &QToolButton::clicked, this, &StatsWidget::restrict); + connect(ui.unrestrictButton, &QToolButton::clicked, this, &StatsWidget::unrestrict); ui.stats->setSource(urlStatsView); ui.stats->setResizeMode(QQuickWidget::SizeRootObjectToView); @@ -141,6 +143,18 @@ void StatsWidget::updateUi() view->plot(state); } +void StatsWidget::updateRestrictionLabel() +{ + if (!view) + return; + int num = view->restrictionCount(); + if (num < 0) + ui.restrictionLabel->setText(tr("Analyzing all dives")); + else + ui.restrictionLabel->setText(tr("Analyzing subset (%L1) dives").arg(num)); + ui.unrestrictButton->setEnabled(num > 0); +} + void StatsWidget::closeStats() { MainWindow::instance()->setApplicationState(ApplicationState::Default); @@ -192,6 +206,21 @@ void StatsWidget::featureChanged(int idx, bool status) void StatsWidget::showEvent(QShowEvent *e) { + unrestrict(); updateUi(); QWidget::showEvent(e); } + +void StatsWidget::restrict() +{ + if (view) + view->restrictToSelection(); + updateRestrictionLabel(); +} + +void StatsWidget::unrestrict() +{ + if (view) + view->unrestrict(); + updateRestrictionLabel(); +} diff --git a/desktop-widgets/statswidget.h b/desktop-widgets/statswidget.h index 51b94ac87..4ae86a015 100644 --- a/desktop-widgets/statswidget.h +++ b/desktop-widgets/statswidget.h @@ -25,11 +25,14 @@ slots: void var2BinnerChanged(int); void var2OperationChanged(int); void featureChanged(int, bool); + void restrict(); + void unrestrict(); private: Ui::StatsWidget ui; StatsState state; StatsView *view; void updateUi(); + void updateRestrictionLabel(); std::vector<std::unique_ptr<QCheckBox>> features; ChartListModel charts; diff --git a/desktop-widgets/statswidget.ui b/desktop-widgets/statswidget.ui index a20fb4a8f..27a10ffd3 100644 --- a/desktop-widgets/statswidget.ui +++ b/desktop-widgets/statswidget.ui @@ -96,6 +96,32 @@ </widget> </item> <item> + <widget class="QGroupBox" name="restrictionGroup"> + <property name="title"> + <string>Restriction</string> + </property> + <layout class="QVBoxLayout" name="chartLayout"> + <item> + <widget class="QLabel" name="restrictionLabel" /> + </item> + <item> + <widget class="QToolButton" name="restrictButton"> + <property name="text"> + <string>Restrict to selection</string> + </property> + </widget> + </item> + <item> + <widget class="QToolButton" name="unrestrictButton"> + <property name="text"> + <string>Reset restriction</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> <spacer name="verticalSpacer"> <property name="orientation"> <enum>Qt::Vertical</enum> diff --git a/stats/statsview.cpp b/stats/statsview.cpp index 09a984bdb..148611cfc 100644 --- a/stats/statsview.cpp +++ b/stats/statsview.cpp @@ -39,6 +39,7 @@ StatsView::StatsView(QQuickItem *parent) : QQuickItem(parent), xAxis(nullptr), yAxis(nullptr), draggedItem(nullptr), + restrictDives(false), rootNode(nullptr) { setFlag(ItemHasContents, true); @@ -496,6 +497,25 @@ void StatsView::reset() grid.reset(); } +void StatsView::restrictToSelection() +{ + restrictedDives = getDiveSelection(); + std::sort(restrictedDives.begin(), restrictedDives.end()); // Sort by pointer for quick lookup + restrictDives = true; + plot(state); +} + +void StatsView::unrestrict() +{ + restrictDives = false; + plot(state); +} + +int StatsView::restrictionCount() const +{ + return restrictDives ? (int)restrictedDives.size() : -1; +} + void StatsView::plot(const StatsState &stateIn) { state = stateIn; @@ -518,7 +538,19 @@ void StatsView::plotChart() return; reset(); - const std::vector<dive *> dives = DiveFilter::instance()->visibleDives(); + std::vector<dive *> dives; + if (restrictDives) { + std::vector<dive *> visible = DiveFilter::instance()->visibleDives(); + dives.reserve(visible.size()); + for (dive *d: visible) { + // binary search + auto it = std::lower_bound(restrictedDives.begin(), restrictedDives.end(), d); + if (it != restrictedDives.end() && *it == d) + dives.push_back(d); + } + } else { + dives = DiveFilter::instance()->visibleDives(); + } switch (state.type) { case ChartType::DiscreteBar: return plotBarChart(dives, state.subtype, state.var1, state.var1Binner, state.var2, diff --git a/stats/statsview.h b/stats/statsview.h index 6e0fe8967..204d4f568 100644 --- a/stats/statsview.h +++ b/stats/statsview.h @@ -46,13 +46,16 @@ public: 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 out root node. + 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 @@ -131,7 +134,6 @@ private: // 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; @@ -148,6 +150,8 @@ private: 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; |