From e38b78b2aa787e3d1de97fb737601dc30a7fad6b Mon Sep 17 00:00:00 2001 From: Berthold Stoeger Date: Sun, 31 Jan 2021 21:30:51 +0100 Subject: statistics: select multiple dives in scatter-plot by shift-clicking Somewhat improve selection mechanics in the scatter-plot by allowing additional selections with shift-clicking. When the dives under the mouse are already selected, then deselect them. This appears to be a rather common UI idiom in desktop applications. Signed-off-by: Berthold Stoeger --- stats/barseries.cpp | 2 +- stats/barseries.h | 2 +- stats/boxseries.cpp | 2 +- stats/boxseries.h | 2 +- stats/pieseries.cpp | 2 +- stats/pieseries.h | 2 +- stats/scatterseries.cpp | 35 +++++++++++++++++++++++++++++++---- stats/scatterseries.h | 2 +- stats/statsseries.h | 2 +- stats/statsview.cpp | 3 ++- 10 files changed, 41 insertions(+), 13 deletions(-) diff --git a/stats/barseries.cpp b/stats/barseries.cpp index a501ddea9..ad956c454 100644 --- a/stats/barseries.cpp +++ b/stats/barseries.cpp @@ -406,7 +406,7 @@ void BarSeries::unhighlight() highlighted = Index(); } -void BarSeries::selectItemsUnderMouse(const QPointF &pos) +void BarSeries::selectItemsUnderMouse(const QPointF &pos, bool) { Index index = getItemUnderMouse(pos); if (index.bar < 0) diff --git a/stats/barseries.h b/stats/barseries.h index 9e0eec355..190efe19d 100644 --- a/stats/barseries.h +++ b/stats/barseries.h @@ -69,7 +69,7 @@ public: void updatePositions() override; bool hover(QPointF pos) override; void unhighlight() override; - void selectItemsUnderMouse(const QPointF &point) override; + void selectItemsUnderMouse(const QPointF &point, bool shiftPressed) override; private: BarSeries(StatsView &view, StatsAxis *xAxis, StatsAxis *yAxis, diff --git a/stats/boxseries.cpp b/stats/boxseries.cpp index 564842001..3d2de0e82 100644 --- a/stats/boxseries.cpp +++ b/stats/boxseries.cpp @@ -143,7 +143,7 @@ void BoxSeries::unhighlight() highlighted = -1; } -void BoxSeries::selectItemsUnderMouse(const QPointF &pos) +void BoxSeries::selectItemsUnderMouse(const QPointF &pos, bool) { int index = getItemUnderMouse(pos); if (index < 0) diff --git a/stats/boxseries.h b/stats/boxseries.h index ccf8b9883..d4ec09ac8 100644 --- a/stats/boxseries.h +++ b/stats/boxseries.h @@ -23,7 +23,7 @@ public: void updatePositions() override; bool hover(QPointF pos) override; void unhighlight() override; - void selectItemsUnderMouse(const QPointF &point) override; + void selectItemsUnderMouse(const QPointF &point, bool shiftPressed) override; // Note: this expects that all items are added with increasing pos // and that no bar is inside another bar, i.e. lowerBound and upperBound diff --git a/stats/pieseries.cpp b/stats/pieseries.cpp index ff0690bb8..9f55d41d2 100644 --- a/stats/pieseries.cpp +++ b/stats/pieseries.cpp @@ -265,7 +265,7 @@ void PieSeries::unhighlight() highlighted = -1; } -void PieSeries::selectItemsUnderMouse(const QPointF &pos) +void PieSeries::selectItemsUnderMouse(const QPointF &pos, bool) { int index = getItemUnderMouse(pos); if (index < 0) diff --git a/stats/pieseries.h b/stats/pieseries.h index 2706fbb41..d41469029 100644 --- a/stats/pieseries.h +++ b/stats/pieseries.h @@ -28,7 +28,7 @@ public: void updatePositions() override; bool hover(QPointF pos) override; void unhighlight() override; - void selectItemsUnderMouse(const QPointF &point) override; + void selectItemsUnderMouse(const QPointF &point, bool shiftPressed) override; std::vector binNames(); diff --git a/stats/scatterseries.cpp b/stats/scatterseries.cpp index f88837288..fe9889d33 100644 --- a/stats/scatterseries.cpp +++ b/stats/scatterseries.cpp @@ -78,12 +78,39 @@ std::vector ScatterSeries::getItemsUnderMouse(const QPointF &point) const return res; } -void ScatterSeries::selectItemsUnderMouse(const QPointF &point) +void ScatterSeries::selectItemsUnderMouse(const QPointF &point, bool shiftPressed) { std::vector selected; - - for(int idx: getItemsUnderMouse(point)) - selected.push_back(items[idx].d); + std::vector indices = getItemsUnderMouse(point); + + if (shiftPressed) { + // When shift is pressed, add the items under the mouse to the selection + // or, if all items under the mouse are selected, remove them. + selected = getDiveSelection(); + bool allSelected = std::all_of(indices.begin(), indices.end(), + [this] (int idx) { return items[idx].d->selected; }); + if (allSelected) { + // Remove items under cursor from selection. This could be made more efficient. + for (int idx: indices) { + auto it = std::find(selected.begin(), selected.end(), items[idx].d); + if (it != selected.end()) { + // Move last element to deselected element. If this already was + // the last element, this is a no-op. Then, chop off last element. + *it = selected.back(); + selected.pop_back(); + } + } + } else { + // Add items under cursor to selection + for (int idx: indices) { + if (std::find(selected.begin(), selected.end(), items[idx].d) == selected.end()) + selected.push_back(items[idx].d); + } + } + } else { + for(int idx: indices) + selected.push_back(items[idx].d); + } setSelection(selected, selected.empty() ? nullptr : selected.front()); } diff --git a/stats/scatterseries.h b/stats/scatterseries.h index 6f24c58e5..35526dfc0 100644 --- a/stats/scatterseries.h +++ b/stats/scatterseries.h @@ -27,7 +27,7 @@ public: // Note: this expects that all items are added with increasing pos! void append(dive *d, double pos, double value); - void selectItemsUnderMouse(const QPointF &point) override; + void selectItemsUnderMouse(const QPointF &point, bool shiftPressed) override; private: // Get items under mouse. diff --git a/stats/statsseries.h b/stats/statsseries.h index 8a4003550..cee2ec0a8 100644 --- a/stats/statsseries.h +++ b/stats/statsseries.h @@ -17,7 +17,7 @@ public: virtual void updatePositions() = 0; // Called if chart geometry changes. virtual bool hover(QPointF pos) = 0; // Called on mouse movement. Return true if an item of this series is highlighted. virtual void unhighlight() = 0; // Unhighlight any highlighted item. - virtual void selectItemsUnderMouse(const QPointF &pos) = 0; + virtual void selectItemsUnderMouse(const QPointF &pos, bool shiftPressed) = 0; virtual void divesSelected(const QVector &dives); protected: diff --git a/stats/statsview.cpp b/stats/statsview.cpp index bf4ecdc6a..9ee0f0e44 100644 --- a/stats/statsview.cpp +++ b/stats/statsview.cpp @@ -81,8 +81,9 @@ void StatsView::mousePressEvent(QMouseEvent *event) } } + bool shiftPressed = event->modifiers() & Qt::ShiftModifier; for (auto &series: series) - series->selectItemsUnderMouse(pos); + series->selectItemsUnderMouse(pos, shiftPressed); } void StatsView::mouseReleaseEvent(QMouseEvent *) -- cgit v1.2.3-70-g09d2