aboutsummaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
authorGravatar Berthold Stoeger <bstoeger@mail.tuwien.ac.at>2019-11-24 13:26:29 +0100
committerGravatar bstoeger <32835590+bstoeger@users.noreply.github.com>2019-12-04 13:00:23 +0100
commit7787bfbf9e39595d98c459e4af121f3174762c7d (patch)
tree6791a300e342ad9b87edcb4781f56f9712e411f3 /core
parentd0b3a06e036cf5523cf03c22ec698742bd01048a (diff)
downloadsubsurface-7787bfbf9e39595d98c459e4af121f3174762c7d.tar.gz
Selection: move commands/command_private.* to core/selection.*
The file command_private.cpp had functions concerning selections only. To make these functions accessible from outside the undo machinery, turn it into a part of the core-library. Currently, only C++ functions are exported. We might think about also exporting a C interface. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Diffstat (limited to 'core')
-rw-r--r--core/CMakeLists.txt2
-rw-r--r--core/selection.cpp106
-rw-r--r--core/selection.h24
3 files changed, 132 insertions, 0 deletions
diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt
index 0c8f88141..0622a859a 100644
--- a/core/CMakeLists.txt
+++ b/core/CMakeLists.txt
@@ -139,6 +139,8 @@ set(SUBSURFACE_CORE_LIB_SRCS
save-html.h
save-profiledata.c
save-xml.c
+ selection.cpp
+ selection.h
sha1.c
sha1.h
ssrf.h
diff --git a/core/selection.cpp b/core/selection.cpp
new file mode 100644
index 000000000..ce0b0aa42
--- /dev/null
+++ b/core/selection.cpp
@@ -0,0 +1,106 @@
+// SPDX-License-Identifier: GPL-2.0
+// Helper functions for the undo-commands
+
+#include "selection.h"
+#include "divelist.h"
+#include "display.h" // for amount_selected
+#include "subsurface-qt/DiveListNotifier.h"
+
+#include <QVector>
+
+// Set the current dive either from a list of selected dives,
+// or a newly selected dive. In both cases, try to select the
+// dive that is newer that is newer than the given date.
+// This mimics the old behavior when the current dive changed.
+static void setClosestCurrentDive(timestamp_t when, const std::vector<dive *> &selection)
+{
+ // Start from back until we get the first dive that is before
+ // the supposed-to-be selected dive. (Note: this mimics the
+ // old behavior when the current dive changed).
+ for (auto it = selection.rbegin(); it < selection.rend(); ++it) {
+ if ((*it)->when > when && !(*it)->hidden_by_filter) {
+ current_dive = *it;
+ return;
+ }
+ }
+
+ // We didn't find a more recent selected dive -> try to
+ // find *any* visible selected dive.
+ for (dive *d: selection) {
+ if (!d->hidden_by_filter) {
+ current_dive = d;
+ return;
+ }
+ }
+
+ // No selected dive is visible! Take the closest dive. Note, this might
+ // return null, but that just means unsetting the current dive (as no
+ // dive is visible anyway).
+ current_dive = find_next_visible_dive(when);
+}
+
+// Reset the selection to the dives of the "selection" vector and send the appropriate signals.
+// Set the current dive to "currentDive". "currentDive" must be an element of "selection" (or
+// null if "seletion" is empty). Return true if the selection or current dive changed.
+void setSelection(const std::vector<dive *> &selection, dive *currentDive)
+{
+ // To do so, generate vectors of dives to be selected and deselected.
+ // We send signals batched by trip, so keep track of trip/dive pairs.
+ QVector<dive *> divesToSelect;
+ divesToSelect.reserve(selection.size());
+
+ // TODO: We might want to keep track of selected dives in a more efficient way!
+ int i;
+ dive *d;
+ amount_selected = 0; // We recalculate amount_selected
+ for_each_dive(i, d) {
+ // We only modify dives that are currently visible.
+ if (d->hidden_by_filter) {
+ d->selected = false; // Note, not necessary, just to be sure
+ // that we get amount_selected right
+ continue;
+ }
+
+ // Search the dive in the list of selected dives.
+ // TODO: By sorting the list in the same way as the backend, this could be made more efficient.
+ bool newState = std::find(selection.begin(), selection.end(), d) != selection.end();
+
+ if (newState) {
+ ++amount_selected;
+ divesToSelect.push_back(d);
+ }
+ // TODO: Instead of using select_dive() and deselect_dive(), we set selected directly.
+ // The reason is that deselect() automatically sets a new current dive, which we
+ // don't want, as we set it later anyway.
+ // There is other parts of the C++ code that touches the innards directly, but
+ // ultimately this should be pushed down to C.
+ d->selected = newState;
+ }
+
+ // We cannot simply change the current dive to the given dive.
+ // It might be hidden by a filter and thus not be selected.
+ current_dive = currentDive;
+ if (current_dive && !currentDive->selected) {
+ // Current not visible -> find a different dive.
+ setClosestCurrentDive(currentDive->when, selection);
+ }
+
+ // Send the new selection
+ emit diveListNotifier.divesSelected(divesToSelect, current_dive);
+}
+
+// Turn current selection into a vector.
+// TODO: This could be made much more efficient if we kept a sorted list of selected dives!
+std::vector<dive *> getDiveSelection()
+{
+ std::vector<dive *> res;
+ res.reserve(amount_selected);
+
+ int i;
+ dive *d;
+ for_each_dive(i, d) {
+ if (d->selected)
+ res.push_back(d);
+ }
+ return res;
+}
diff --git a/core/selection.h b/core/selection.h
new file mode 100644
index 000000000..0fb226949
--- /dev/null
+++ b/core/selection.h
@@ -0,0 +1,24 @@
+// SPDX-License-Identifier: GPL-2.0
+// Selection related functions
+
+#ifndef SELECTION_H
+#define SELECTION_H
+
+/*** C++-only functions ***/
+
+#ifdef __cplusplus
+#include <vector>
+
+struct dive;
+
+// Reset the selection to the dives of the "selection" vector and send the appropriate signals.
+// Set the current dive to "currentDive". "currentDive" must be an element of "selection" (or
+// null if "seletion" is empty).
+void setSelection(const std::vector<dive *> &selection, dive *currentDive);
+
+// Get currently selectd dives
+std::vector<dive *> getDiveSelection();
+
+#endif // __cplusplus
+
+#endif // SELECTION_H