From 64b82b16a26bcaa624cc35e775b821e33133bdbb Mon Sep 17 00:00:00 2001 From: Berthold Stoeger Date: Mon, 8 Feb 2021 17:07:37 +0100 Subject: statistics: make selection keyboard modifiers more general Up to now, we passed a "shiftPressed" flag to the individual selection functions. To be more general replace by a struct with "shift" and "ctrl" flags. While doing this: 1) Move the struct into a new statsselection file for better encapsulation. 2) Change shift to control in the scatter series, since individual selection of items is usually done with control, not shift. Shift usually means "select range". Signed-off-by: Berthold Stoeger --- stats/CMakeLists.txt | 2 ++ 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 | 8 ++++---- stats/scatterseries.h | 4 ++-- stats/statsselection.cpp | 2 ++ stats/statsselection.h | 15 +++++++++++++++ stats/statsseries.cpp | 2 +- stats/statsseries.h | 6 ++++-- stats/statsview.cpp | 13 +++++++------ stats/statsview.h | 3 ++- 15 files changed, 45 insertions(+), 22 deletions(-) create mode 100644 stats/statsselection.cpp create mode 100644 stats/statsselection.h (limited to 'stats') diff --git a/stats/CMakeLists.txt b/stats/CMakeLists.txt index 1381797da..1525d7f69 100644 --- a/stats/CMakeLists.txt +++ b/stats/CMakeLists.txt @@ -36,6 +36,8 @@ set(SUBSURFACE_STATS_SRCS statsgrid.cpp statshelper.h statshelper.cpp + statsselection.h + statsselection.cpp statsseries.h statsseries.cpp statsstate.h diff --git a/stats/barseries.cpp b/stats/barseries.cpp index 3220bbd1a..0f931e367 100644 --- a/stats/barseries.cpp +++ b/stats/barseries.cpp @@ -411,7 +411,7 @@ void BarSeries::unhighlight() highlighted = Index(); } -bool BarSeries::selectItemsUnderMouse(const QPointF &pos, bool) +bool BarSeries::selectItemsUnderMouse(const QPointF &pos, SelectionModifier) { Index index = getItemUnderMouse(pos); if (index.bar < 0) { diff --git a/stats/barseries.h b/stats/barseries.h index d5cfb10e4..6779e5b6c 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; - bool selectItemsUnderMouse(const QPointF &point, bool shiftPressed) override; + bool selectItemsUnderMouse(const QPointF &point, SelectionModifier modifier) override; private: BarSeries(StatsView &view, StatsAxis *xAxis, StatsAxis *yAxis, diff --git a/stats/boxseries.cpp b/stats/boxseries.cpp index 78a3d258f..09f9ccf9c 100644 --- a/stats/boxseries.cpp +++ b/stats/boxseries.cpp @@ -146,7 +146,7 @@ void BoxSeries::unhighlight() highlighted = -1; } -bool BoxSeries::selectItemsUnderMouse(const QPointF &pos, bool) +bool BoxSeries::selectItemsUnderMouse(const QPointF &pos, SelectionModifier) { int index = getItemUnderMouse(pos); if (index < 0) { diff --git a/stats/boxseries.h b/stats/boxseries.h index cd54ea86b..75e6cfa49 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; - bool selectItemsUnderMouse(const QPointF &point, bool shiftPressed) override; + bool selectItemsUnderMouse(const QPointF &point, SelectionModifier modifier) 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 5d940c2b2..30d28774a 100644 --- a/stats/pieseries.cpp +++ b/stats/pieseries.cpp @@ -266,7 +266,7 @@ void PieSeries::unhighlight() highlighted = -1; } -bool PieSeries::selectItemsUnderMouse(const QPointF &pos, bool) +bool PieSeries::selectItemsUnderMouse(const QPointF &pos, SelectionModifier) { int index = getItemUnderMouse(pos); if (index < 0) { diff --git a/stats/pieseries.h b/stats/pieseries.h index 83e9acba7..1a132ebc3 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; - bool selectItemsUnderMouse(const QPointF &point, bool shiftPressed) override; + bool selectItemsUnderMouse(const QPointF &point, SelectionModifier modifier) override; std::vector binNames(); diff --git a/stats/scatterseries.cpp b/stats/scatterseries.cpp index 63fdaae1b..38385edd1 100644 --- a/stats/scatterseries.cpp +++ b/stats/scatterseries.cpp @@ -96,12 +96,12 @@ std::vector ScatterSeries::getItemsInRect(const QRectF &rect) const return res; } -bool ScatterSeries::selectItemsUnderMouse(const QPointF &point, bool shiftPressed) +bool ScatterSeries::selectItemsUnderMouse(const QPointF &point, SelectionModifier modifier) { std::vector selected; std::vector indices = getItemsUnderMouse(point); - if (shiftPressed) { + if (modifier.ctrl) { // 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(); @@ -141,13 +141,13 @@ bool ScatterSeries::supportsLassoSelection() const return true; } -void ScatterSeries::selectItemsInRect(const QRectF &rect, bool shiftPressed, const std::vector &oldSelection) +void ScatterSeries::selectItemsInRect(const QRectF &rect, SelectionModifier modifier, const std::vector &oldSelection) { std::vector selected; std::vector indices = getItemsInRect(rect); selected.reserve(oldSelection.size() + indices.size()); - if (shiftPressed) { + if (modifier.ctrl) { selected = oldSelection; // Ouch - this primitive merging of the selections grows with O(n^2). Fix this. for (int idx: indices) { diff --git a/stats/scatterseries.h b/stats/scatterseries.h index 1b8db0337..eeb28415b 100644 --- a/stats/scatterseries.h +++ b/stats/scatterseries.h @@ -27,9 +27,9 @@ public: // Note: this expects that all items are added with increasing pos! void append(dive *d, double pos, double value); - bool selectItemsUnderMouse(const QPointF &point, bool shiftPressed) override; + bool selectItemsUnderMouse(const QPointF &point, SelectionModifier modifier) override; bool supportsLassoSelection() const override; - void selectItemsInRect(const QRectF &rect, bool shiftPressed, const std::vector &oldSelection) override; + void selectItemsInRect(const QRectF &rect, SelectionModifier modifier, const std::vector &oldSelection) override; private: // Get items under mouse. diff --git a/stats/statsselection.cpp b/stats/statsselection.cpp new file mode 100644 index 000000000..38bbd7f8b --- /dev/null +++ b/stats/statsselection.cpp @@ -0,0 +1,2 @@ +// SPDX-License-Identifier: GPL-2.0 +#include "statsselection.h" diff --git a/stats/statsselection.h b/stats/statsselection.h new file mode 100644 index 000000000..e3f590466 --- /dev/null +++ b/stats/statsselection.h @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: GPL-2.0 +// Functions and data structures handling dive selections. + +#ifndef STATS_SELECTION_H +#define STATS_SELECTION_H + +struct SelectionModifier { + unsigned int ctrl : 1; + unsigned int shift : 1; + // Note: default member initializers for bit-fields becomes available with C++20. + // Therefore, for now an inline constructor. + SelectionModifier() : ctrl(0), shift(0) {} +}; + +#endif diff --git a/stats/statsseries.cpp b/stats/statsseries.cpp index 379628fe1..08d0c031d 100644 --- a/stats/statsseries.cpp +++ b/stats/statsseries.cpp @@ -22,6 +22,6 @@ bool StatsSeries::supportsLassoSelection() const return false; } -void StatsSeries::selectItemsInRect(const QRectF &, bool, const std::vector &) +void StatsSeries::selectItemsInRect(const QRectF &, SelectionModifier, const std::vector &) { } diff --git a/stats/statsseries.h b/stats/statsseries.h index 196427eaf..16c88b047 100644 --- a/stats/statsseries.h +++ b/stats/statsseries.h @@ -4,6 +4,8 @@ #ifndef STATS_SERIES_H #define STATS_SERIES_H +#include "statsselection.h" + #include #include @@ -20,10 +22,10 @@ public: 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. // Returns true if an item was under the mouse. - virtual bool selectItemsUnderMouse(const QPointF &pos, bool shiftPressed) = 0; + virtual bool selectItemsUnderMouse(const QPointF &pos, SelectionModifier modifier) = 0; virtual bool supportsLassoSelection() const; // Needs only be defined if supportsLassoSelection() returns true. - virtual void selectItemsInRect(const QRectF &rect, bool shiftPressed, const std::vector &oldSelection); + virtual void selectItemsInRect(const QRectF &rect, SelectionModifier modifier, const std::vector &oldSelection); virtual void divesSelected(const QVector &dives) = 0; protected: diff --git a/stats/statsview.cpp b/stats/statsview.cpp index 88f394550..09a984bdb 100644 --- a/stats/statsview.cpp +++ b/stats/statsview.cpp @@ -39,7 +39,6 @@ StatsView::StatsView(QQuickItem *parent) : QQuickItem(parent), xAxis(nullptr), yAxis(nullptr), draggedItem(nullptr), - shiftSelection(false), rootNode(nullptr) { setFlag(ItemHasContents, true); @@ -84,10 +83,12 @@ void StatsView::mousePressEvent(QMouseEvent *event) } } - bool shiftPressed = event->modifiers() & Qt::ShiftModifier; + SelectionModifier modifier; + modifier.shift = (event->modifiers() & Qt::ShiftModifier) != 0; + modifier.ctrl = (event->modifiers() & Qt::ControlModifier) != 0; bool itemSelected = false; for (auto &series: series) - itemSelected |= series->selectItemsUnderMouse(pos, shiftPressed); + itemSelected |= series->selectItemsUnderMouse(pos, modifier); // The user clicked in "empty" space. If there is a series supporting lasso-select, // got into lasso mode. For now, we only support a rectangular lasso. @@ -98,8 +99,8 @@ void StatsView::mousePressEvent(QMouseEvent *event) deleteChartItem(selectionRect); // Ooops. Already a selection in place. dragStartMouse = pos; selectionRect = createChartItem(ChartZValue::Selection, selectionLassoColor, selectionLassoWidth); - shiftSelection = shiftPressed; - oldSelection = shiftPressed ? getDiveSelection() : std::vector(); + selectionModifier = modifier; + oldSelection = modifier.ctrl ? getDiveSelection() : std::vector(); grabMouse(); setKeepMouseGrab(true); // don't allow Qt to steal the grab update(); @@ -400,7 +401,7 @@ void StatsView::mouseMoveEvent(QMouseEvent *event) fabs(p2.x() - p1.x()), fabs(p2.y() - p1.y())); for (auto &series: series) { if (series->supportsLassoSelection()) - series->selectItemsInRect(rect, shiftSelection, oldSelection); + series->selectItemsInRect(rect, selectionModifier, oldSelection); } update(); } diff --git a/stats/statsview.h b/stats/statsview.h index 279889104..6e0fe8967 100644 --- a/stats/statsview.h +++ b/stats/statsview.h @@ -4,6 +4,7 @@ #include "statsstate.h" #include "statshelper.h" +#include "statsselection.h" #include #include #include @@ -145,7 +146,7 @@ private: ChartItemPtr regressionItem; ChartItemPtr selectionRect; QPointF dragStartMouse, dragStartItem; - bool shiftSelection; + SelectionModifier selectionModifier; std::vector oldSelection; void hoverEnterEvent(QHoverEvent *event) override; -- cgit v1.2.3-70-g09d2