summaryrefslogtreecommitdiffstats
path: root/desktop-widgets/command_private.h
blob: a75ff9bba1c2656a5bdaa85ecb650f7a42b51d98 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
// SPDX-License-Identifier: GPL-2.0
// Private definitions for the command-objects

#ifndef COMMAND_PRIVATE_H
#define COMMAND_PRIVATE_H

#include "core/dive.h"

#include <vector>
#include <utility>
#include <QVector>

namespace Command {

// Generally, signals are sent in batches per trip. To avoid writing the same loop
// again and again, this template takes a vector of trip / dive pairs, sorts it
// by trip and then calls a function-object with trip and a QVector of dives in that trip.
// Input parameters:
//	- dives: a vector of trip,dive pairs, which will be sorted and processed in batches by trip.
//	- action: a function object, taking a trip-pointer and a QVector of dives, which will be called for each batch.
template<typename Function>
void processByTrip(std::vector<std::pair<dive_trip *, dive *>> &dives, Function action)
{
	// Use std::tie for lexicographical sorting of trip, then start-time
	std::sort(dives.begin(), dives.end(),
		  [](const std::pair<dive_trip *, dive *> &e1, const std::pair<dive_trip *, dive *> &e2)
		  { return std::tie(e1.first, e1.second->when) < std::tie(e2.first, e2.second->when); });

	// Then, process the dives in batches by trip
	size_t i, j; // Begin and end of batch
	for (i = 0; i < dives.size(); i = j) {
		dive_trip *trip = dives[i].first;
		for (j = i + 1; j < dives.size() && dives[j].first == trip; ++j)
			; // pass
		// Copy dives into a QVector. Some sort of "range_view" would be ideal, but Qt doesn't work this way.
		QVector<dive *> divesInTrip(j - i);
		for (size_t k = i; k < j; ++k)
			divesInTrip[k - i] = dives[k].second;

		// Finally, emit the signal
		action(trip, divesInTrip);
	}
}

// The processByTrip() function above takes a vector if (trip, dive) pairs.
// This overload takes a vector of dives.
template<typename Vector, typename Function>
void processByTrip(Vector &divesIn, Function action)
{
	std::vector<std::pair<dive_trip *, dive *>> dives;
	dives.reserve(divesIn.size());
	for (dive *d: divesIn)
		dives.push_back({ d->divetrip, d });
	processByTrip(dives, action);

}

// 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.
bool setSelection(const std::vector<dive *> &selection, dive *currentDive);

// Get currently selectd dives
std::vector<dive *> getDiveSelection();

} // namespace Command

#endif // COMMAND_PRIVATE_H