mirror of
https://github.com/subsurface/subsurface.git
synced 2025-02-19 22:16:15 +00:00
core: turn trip-table into our own sorted_owning_table
Since the sorted_owning_table depends on the fact that different elements never compare as equal, make the comparison function safer in that respect. If all failes, compare the pointers. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
parent
1cebafb08f
commit
eacad89531
21 changed files with 217 additions and 305 deletions
|
@ -14,11 +14,12 @@
|
||||||
namespace Command {
|
namespace Command {
|
||||||
|
|
||||||
// Helper function that takes care to unselect trips that are removed from the backend
|
// Helper function that takes care to unselect trips that are removed from the backend
|
||||||
static void remove_trip_from_backend(dive_trip *trip)
|
static std::unique_ptr<dive_trip> remove_trip_from_backend(dive_trip *trip)
|
||||||
{
|
{
|
||||||
if (trip->selected)
|
if (trip->selected)
|
||||||
deselect_trip(trip);
|
deselect_trip(trip);
|
||||||
remove_trip(trip, divelog.trips.get()); // Remove trip from backend
|
auto [t, idx] = divelog.trips->pull(trip);
|
||||||
|
return std::move(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This helper function removes a dive, takes ownership of the dive and adds it to a DiveToAdd structure.
|
// This helper function removes a dive, takes ownership of the dive and adds it to a DiveToAdd structure.
|
||||||
|
@ -40,8 +41,9 @@ DiveToAdd DiveListBase::removeDive(struct dive *d, std::vector<std::unique_ptr<d
|
||||||
diveSiteCountChanged(d->dive_site);
|
diveSiteCountChanged(d->dive_site);
|
||||||
res.site = unregister_dive_from_dive_site(d);
|
res.site = unregister_dive_from_dive_site(d);
|
||||||
if (res.trip && res.trip->dives.nr == 0) {
|
if (res.trip && res.trip->dives.nr == 0) {
|
||||||
remove_trip_from_backend(res.trip); // Remove trip from backend
|
divelog.trips->sort(); // Removal of dives has changed order of trips! (TODO: remove this)
|
||||||
tripsToAdd.emplace_back(res.trip); // Take ownership of trip
|
auto trip = remove_trip_from_backend(res.trip); // Remove trip from backend
|
||||||
|
tripsToAdd.push_back(std::move(trip)); // Take ownership of trip
|
||||||
}
|
}
|
||||||
|
|
||||||
int idx = get_divenr(d);
|
int idx = get_divenr(d);
|
||||||
|
@ -210,8 +212,8 @@ DivesAndSitesToRemove DiveListBase::addDives(DivesAndTripsToAdd &toAdd)
|
||||||
std::vector<dive_trip *> addedTrips;
|
std::vector<dive_trip *> addedTrips;
|
||||||
addedTrips.reserve(toAdd.trips.size());
|
addedTrips.reserve(toAdd.trips.size());
|
||||||
for (std::unique_ptr<dive_trip> &trip: toAdd.trips) {
|
for (std::unique_ptr<dive_trip> &trip: toAdd.trips) {
|
||||||
addedTrips.push_back(trip.get());
|
auto [t, idx] = divelog.trips->put(std::move(trip)); // Return ownership to backend
|
||||||
insert_trip(trip.release(), divelog.trips.get()); // Return ownership to backend
|
addedTrips.push_back(t);
|
||||||
}
|
}
|
||||||
toAdd.trips.clear();
|
toAdd.trips.clear();
|
||||||
|
|
||||||
|
@ -271,10 +273,8 @@ static std::unique_ptr<dive_trip> moveDiveToTrip(DiveToTrip &diveToTrip)
|
||||||
|
|
||||||
// Remove dive from trip - if this is the last dive in the trip, remove the whole trip.
|
// Remove dive from trip - if this is the last dive in the trip, remove the whole trip.
|
||||||
dive_trip *trip = unregister_dive_from_trip(diveToTrip.dive);
|
dive_trip *trip = unregister_dive_from_trip(diveToTrip.dive);
|
||||||
if (trip && trip->dives.nr == 0) {
|
if (trip && trip->dives.nr == 0)
|
||||||
remove_trip_from_backend(trip); // Remove trip from backend
|
res = remove_trip_from_backend(trip); // Remove trip from backend
|
||||||
res.reset(trip);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Store old trip and get new trip we should associate this dive with
|
// Store old trip and get new trip we should associate this dive with
|
||||||
std::swap(trip, diveToTrip.trip);
|
std::swap(trip, diveToTrip.trip);
|
||||||
|
@ -299,9 +299,8 @@ static void moveDivesBetweenTrips(DivesToTrip &dives)
|
||||||
|
|
||||||
// First, bring back the trip(s)
|
// First, bring back the trip(s)
|
||||||
for (std::unique_ptr<dive_trip> &trip: dives.tripsToAdd) {
|
for (std::unique_ptr<dive_trip> &trip: dives.tripsToAdd) {
|
||||||
dive_trip *t = trip.release(); // Give up ownership
|
auto [t, idx] = divelog.trips->put(std::move(trip)); // Return ownership to backend
|
||||||
createdTrips.push_back(t);
|
createdTrips.push_back(t);
|
||||||
insert_trip(t, divelog.trips.get()); // Return ownership to backend
|
|
||||||
}
|
}
|
||||||
dives.tripsToAdd.clear();
|
dives.tripsToAdd.clear();
|
||||||
|
|
||||||
|
@ -425,10 +424,9 @@ AddDive::AddDive(dive *d, bool autogroup, bool newNumber)
|
||||||
divePtr->divetrip = nullptr;
|
divePtr->divetrip = nullptr;
|
||||||
divePtr->dive_site = nullptr;
|
divePtr->dive_site = nullptr;
|
||||||
if (!trip && autogroup) {
|
if (!trip && autogroup) {
|
||||||
bool alloc;
|
auto [t, allocated] = get_trip_for_new_dive(divePtr.get());
|
||||||
trip = get_trip_for_new_dive(divePtr.get(), &alloc);
|
trip = t;
|
||||||
if (alloc)
|
allocTrip = std::move(allocated);
|
||||||
allocTrip.reset(trip);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int idx = dive_table_get_insertion_index(divelog.dives.get(), divePtr.get());
|
int idx = dive_table_get_insertion_index(divelog.dives.get(), divePtr.get());
|
||||||
|
@ -452,7 +450,7 @@ void AddDive::redoit()
|
||||||
currentDive = current_dive;
|
currentDive = current_dive;
|
||||||
|
|
||||||
divesAndSitesToRemove = addDives(divesToAdd);
|
divesAndSitesToRemove = addDives(divesToAdd);
|
||||||
sort_trip_table(divelog.trips.get()); // Though unlikely, adding a dive may reorder trips
|
divelog.trips->sort(); // Though unlikely, adding a dive may reorder trips
|
||||||
|
|
||||||
// Select the newly added dive
|
// Select the newly added dive
|
||||||
setSelection(divesAndSitesToRemove.dives, divesAndSitesToRemove.dives[0], -1);
|
setSelection(divesAndSitesToRemove.dives, divesAndSitesToRemove.dives[0], -1);
|
||||||
|
@ -462,7 +460,7 @@ void AddDive::undoit()
|
||||||
{
|
{
|
||||||
// Simply remove the dive that was previously added...
|
// Simply remove the dive that was previously added...
|
||||||
divesToAdd = removeDives(divesAndSitesToRemove);
|
divesToAdd = removeDives(divesAndSitesToRemove);
|
||||||
sort_trip_table(divelog.trips.get()); // Though unlikely, removing a dive may reorder trips
|
divelog.trips->sort(); // Though unlikely, removing a dive may reorder trips
|
||||||
|
|
||||||
// ...and restore the selection
|
// ...and restore the selection
|
||||||
setSelection(selection, currentDive, -1);
|
setSelection(selection, currentDive, -1);
|
||||||
|
@ -477,16 +475,16 @@ ImportDives::ImportDives(struct divelog *log, int flags, const QString &source)
|
||||||
|
|
||||||
struct dive_table dives_to_add = empty_dive_table;
|
struct dive_table dives_to_add = empty_dive_table;
|
||||||
struct dive_table dives_to_remove = empty_dive_table;
|
struct dive_table dives_to_remove = empty_dive_table;
|
||||||
struct trip_table trips_to_add = empty_trip_table;
|
struct trip_table trips_to_add;
|
||||||
dive_site_table sites_to_add;
|
dive_site_table sites_to_add;
|
||||||
process_imported_dives(log, flags,
|
process_imported_dives(log, flags,
|
||||||
&dives_to_add, &dives_to_remove, &trips_to_add,
|
&dives_to_add, &dives_to_remove, trips_to_add,
|
||||||
sites_to_add, devicesToAddAndRemove);
|
sites_to_add, devicesToAddAndRemove);
|
||||||
|
|
||||||
// Add trips to the divesToAdd.trips structure
|
// Add trips to the divesToAdd.trips structure
|
||||||
divesToAdd.trips.reserve(trips_to_add.nr);
|
divesToAdd.trips.reserve(trips_to_add.size());
|
||||||
for (int i = 0; i < trips_to_add.nr; ++i)
|
for (auto &trip: trips_to_add)
|
||||||
divesToAdd.trips.emplace_back(trips_to_add.trips[i]);
|
divesToAdd.trips.push_back(std::move(trip));
|
||||||
|
|
||||||
// Add sites to the divesToAdd.sites structure
|
// Add sites to the divesToAdd.sites structure
|
||||||
divesToAdd.sites = std::move(sites_to_add);
|
divesToAdd.sites = std::move(sites_to_add);
|
||||||
|
@ -522,7 +520,6 @@ ImportDives::ImportDives(struct divelog *log, int flags, const QString &source)
|
||||||
|
|
||||||
free(dives_to_add.dives);
|
free(dives_to_add.dives);
|
||||||
free(dives_to_remove.dives);
|
free(dives_to_remove.dives);
|
||||||
free(trips_to_add.trips);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ImportDives::workToBeDone()
|
bool ImportDives::workToBeDone()
|
||||||
|
@ -606,7 +603,7 @@ bool DeleteDive::workToBeDone()
|
||||||
void DeleteDive::undoit()
|
void DeleteDive::undoit()
|
||||||
{
|
{
|
||||||
divesToDelete = addDives(divesToAdd);
|
divesToDelete = addDives(divesToAdd);
|
||||||
sort_trip_table(divelog.trips.get()); // Though unlikely, removing a dive may reorder trips
|
divelog.trips->sort(); // Though unlikely, removing a dive may reorder trips
|
||||||
|
|
||||||
// Select all re-added dives and make the first one current
|
// Select all re-added dives and make the first one current
|
||||||
dive *currentDive = !divesToDelete.dives.empty() ? divesToDelete.dives[0] : nullptr;
|
dive *currentDive = !divesToDelete.dives.empty() ? divesToDelete.dives[0] : nullptr;
|
||||||
|
@ -616,7 +613,7 @@ void DeleteDive::undoit()
|
||||||
void DeleteDive::redoit()
|
void DeleteDive::redoit()
|
||||||
{
|
{
|
||||||
divesToAdd = removeDives(divesToDelete);
|
divesToAdd = removeDives(divesToDelete);
|
||||||
sort_trip_table(divelog.trips.get()); // Though unlikely, adding a dive may reorder trips
|
divelog.trips->sort(); // Though unlikely, adding a dive may reorder trips
|
||||||
|
|
||||||
// Deselect all dives and select dive that was close to the first deleted dive
|
// Deselect all dives and select dive that was close to the first deleted dive
|
||||||
dive *newCurrent = nullptr;
|
dive *newCurrent = nullptr;
|
||||||
|
@ -645,7 +642,7 @@ void ShiftTime::redoit()
|
||||||
|
|
||||||
// Changing times may have unsorted the dive and trip tables
|
// Changing times may have unsorted the dive and trip tables
|
||||||
sort_dive_table(divelog.dives.get());
|
sort_dive_table(divelog.dives.get());
|
||||||
sort_trip_table(divelog.trips.get());
|
divelog.trips->sort();
|
||||||
for (dive_trip *trip: trips)
|
for (dive_trip *trip: trips)
|
||||||
sort_dive_table(&trip->dives); // Keep the trip-table in order
|
sort_dive_table(&trip->dives); // Keep the trip-table in order
|
||||||
|
|
||||||
|
@ -713,7 +710,7 @@ bool TripBase::workToBeDone()
|
||||||
void TripBase::redoit()
|
void TripBase::redoit()
|
||||||
{
|
{
|
||||||
moveDivesBetweenTrips(divesToMove);
|
moveDivesBetweenTrips(divesToMove);
|
||||||
sort_trip_table(divelog.trips.get()); // Though unlikely, moving dives may reorder trips
|
divelog.trips->sort(); // Though unlikely, moving dives may reorder trips
|
||||||
|
|
||||||
// Select the moved dives
|
// Select the moved dives
|
||||||
std::vector<dive *> dives;
|
std::vector<dive *> dives;
|
||||||
|
@ -773,25 +770,22 @@ CreateTrip::CreateTrip(const QVector<dive *> &divesToAddIn)
|
||||||
if (divesToAddIn.isEmpty())
|
if (divesToAddIn.isEmpty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
dive_trip *trip = create_trip_from_dive(divesToAddIn[0]);
|
auto trip = create_trip_from_dive(divesToAddIn[0]);
|
||||||
divesToMove.tripsToAdd.emplace_back(trip);
|
|
||||||
for (dive *d: divesToAddIn)
|
for (dive *d: divesToAddIn)
|
||||||
divesToMove.divesToMove.push_back( {d, trip} );
|
divesToMove.divesToMove.push_back( { d, trip.get() });
|
||||||
|
divesToMove.tripsToAdd.push_back(std::move(trip));
|
||||||
}
|
}
|
||||||
|
|
||||||
AutogroupDives::AutogroupDives()
|
AutogroupDives::AutogroupDives()
|
||||||
{
|
{
|
||||||
setText(Command::Base::tr("autogroup dives"));
|
setText(Command::Base::tr("autogroup dives"));
|
||||||
|
|
||||||
dive_trip *trip;
|
for (auto &entry: get_dives_to_autogroup(divelog.dives.get())) {
|
||||||
bool alloc;
|
|
||||||
int from, to;
|
|
||||||
for(int i = 0; (trip = get_dives_to_autogroup(divelog.dives.get(), i, &from, &to, &alloc)) != NULL; i = to) {
|
|
||||||
// If this is an allocated trip, take ownership
|
// If this is an allocated trip, take ownership
|
||||||
if (alloc)
|
if (entry.created_trip)
|
||||||
divesToMove.tripsToAdd.emplace_back(trip);
|
divesToMove.tripsToAdd.push_back(std::move(entry.created_trip));
|
||||||
for (int j = from; j < to; ++j)
|
for (int i = entry.from; i < entry.to; ++i)
|
||||||
divesToMove.divesToMove.push_back( { get_dive(j), trip } );
|
divesToMove.divesToMove.push_back( { divelog.dives->dives[i], entry.trip } );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -799,12 +793,12 @@ MergeTrips::MergeTrips(dive_trip *trip1, dive_trip *trip2)
|
||||||
{
|
{
|
||||||
if (trip1 == trip2)
|
if (trip1 == trip2)
|
||||||
return;
|
return;
|
||||||
dive_trip *newTrip = combine_trips(trip1, trip2);
|
std::unique_ptr<dive_trip> newTrip = combine_trips(trip1, trip2);
|
||||||
divesToMove.tripsToAdd.emplace_back(newTrip);
|
|
||||||
for (int i = 0; i < trip1->dives.nr; ++i)
|
for (int i = 0; i < trip1->dives.nr; ++i)
|
||||||
divesToMove.divesToMove.push_back( { trip1->dives.dives[i], newTrip } );
|
divesToMove.divesToMove.push_back( { trip1->dives.dives[i], newTrip.get() } );
|
||||||
for (int i = 0; i < trip2->dives.nr; ++i)
|
for (int i = 0; i < trip2->dives.nr; ++i)
|
||||||
divesToMove.divesToMove.push_back( { trip2->dives.dives[i], newTrip } );
|
divesToMove.divesToMove.push_back( { trip2->dives.dives[i], newTrip.get() } );
|
||||||
|
divesToMove.tripsToAdd.push_back(std::move(newTrip));
|
||||||
}
|
}
|
||||||
|
|
||||||
// std::array<dive *, 2> is the same as struct *dive[2], with the fundamental
|
// std::array<dive *, 2> is the same as struct *dive[2], with the fundamental
|
||||||
|
|
|
@ -1444,7 +1444,7 @@ void EditDive::exchangeDives()
|
||||||
timestamp_t delta = oldDive->when - newDive->when;
|
timestamp_t delta = oldDive->when - newDive->when;
|
||||||
if (delta != 0) {
|
if (delta != 0) {
|
||||||
sort_dive_table(divelog.dives.get());
|
sort_dive_table(divelog.dives.get());
|
||||||
sort_trip_table(divelog.trips.get());
|
divelog.trips->sort();
|
||||||
if (newDive->divetrip != oldDive->divetrip)
|
if (newDive->divetrip != oldDive->divetrip)
|
||||||
qWarning("Command::EditDive::redo(): This command does not support moving between trips!");
|
qWarning("Command::EditDive::redo(): This command does not support moving between trips!");
|
||||||
if (oldDive->divetrip)
|
if (oldDive->divetrip)
|
||||||
|
|
|
@ -638,6 +638,8 @@ static int comp_dc(const struct dive *d1, const struct dive *d2)
|
||||||
int comp_dives(const struct dive *a, const struct dive *b)
|
int comp_dives(const struct dive *a, const struct dive *b)
|
||||||
{
|
{
|
||||||
int cmp;
|
int cmp;
|
||||||
|
if (a == b)
|
||||||
|
return 0; /* reflexivity */
|
||||||
if (a->when < b->when)
|
if (a->when < b->when)
|
||||||
return -1;
|
return -1;
|
||||||
if (a->when > b->when)
|
if (a->when > b->when)
|
||||||
|
@ -647,9 +649,9 @@ int comp_dives(const struct dive *a, const struct dive *b)
|
||||||
return -1;
|
return -1;
|
||||||
if (!a->divetrip)
|
if (!a->divetrip)
|
||||||
return 1;
|
return 1;
|
||||||
if (trip_date(a->divetrip) < trip_date(b->divetrip))
|
if (trip_date(*a->divetrip) < trip_date(*b->divetrip))
|
||||||
return -1;
|
return -1;
|
||||||
if (trip_date(a->divetrip) > trip_date(b->divetrip))
|
if (trip_date(*a->divetrip) > trip_date(*b->divetrip))
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (a->number < b->number)
|
if (a->number < b->number)
|
||||||
|
@ -662,7 +664,7 @@ int comp_dives(const struct dive *a, const struct dive *b)
|
||||||
return -1;
|
return -1;
|
||||||
if (a->id > b->id)
|
if (a->id > b->id)
|
||||||
return 1;
|
return 1;
|
||||||
return 0; /* this should not happen for a != b */
|
return a < b ? -1 : 1; /* give up. */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Dive table functions */
|
/* Dive table functions */
|
||||||
|
@ -690,24 +692,19 @@ void insert_dive(struct dive_table *table, struct dive *d)
|
||||||
* Walk the dives from the oldest dive in the given table, and see if we
|
* Walk the dives from the oldest dive in the given table, and see if we
|
||||||
* can autogroup them. But only do this when the user selected autogrouping.
|
* can autogroup them. But only do this when the user selected autogrouping.
|
||||||
*/
|
*/
|
||||||
static void autogroup_dives(struct dive_table *table, struct trip_table *trip_table_arg)
|
static void autogroup_dives(struct dive_table *table, struct trip_table &trip_table)
|
||||||
{
|
{
|
||||||
int from, to;
|
|
||||||
dive_trip *trip;
|
|
||||||
int i, j;
|
|
||||||
bool alloc;
|
|
||||||
|
|
||||||
if (!divelog.autogroup)
|
if (!divelog.autogroup)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (i = 0; (trip = get_dives_to_autogroup(table, i, &from, &to, &alloc)) != NULL; i = to) {
|
for (auto &entry: get_dives_to_autogroup(table)) {
|
||||||
for (j = from; j < to; ++j)
|
for (int i = entry.from; i < entry.to; ++i)
|
||||||
add_dive_to_trip(table->dives[j], trip);
|
add_dive_to_trip(table->dives[i], entry.trip);
|
||||||
/* If this was newly allocated, add trip to list */
|
/* If this was newly allocated, add trip to list */
|
||||||
if (alloc)
|
if (entry.created_trip)
|
||||||
insert_trip(trip, trip_table_arg);
|
trip_table.put(std::move(entry.created_trip));
|
||||||
}
|
}
|
||||||
sort_trip_table(trip_table_arg);
|
trip_table.sort(); // Necessary?
|
||||||
#ifdef DEBUG_TRIP
|
#ifdef DEBUG_TRIP
|
||||||
dump_trip_list();
|
dump_trip_list();
|
||||||
#endif
|
#endif
|
||||||
|
@ -751,10 +748,10 @@ struct dive *unregister_dive(int idx)
|
||||||
void process_loaded_dives()
|
void process_loaded_dives()
|
||||||
{
|
{
|
||||||
sort_dive_table(divelog.dives.get());
|
sort_dive_table(divelog.dives.get());
|
||||||
sort_trip_table(divelog.trips.get());
|
divelog.trips->sort();
|
||||||
|
|
||||||
/* Autogroup dives if desired by user. */
|
/* Autogroup dives if desired by user. */
|
||||||
autogroup_dives(divelog.dives.get(), divelog.trips.get());
|
autogroup_dives(divelog.dives.get(), *divelog.trips);
|
||||||
|
|
||||||
fulltext_populate();
|
fulltext_populate();
|
||||||
|
|
||||||
|
@ -932,13 +929,13 @@ void add_imported_dives(struct divelog *import_log, int flags)
|
||||||
int i, idx;
|
int i, idx;
|
||||||
struct dive_table dives_to_add = empty_dive_table;
|
struct dive_table dives_to_add = empty_dive_table;
|
||||||
struct dive_table dives_to_remove = empty_dive_table;
|
struct dive_table dives_to_remove = empty_dive_table;
|
||||||
struct trip_table trips_to_add = empty_trip_table;
|
struct trip_table trips_to_add;
|
||||||
dive_site_table dive_sites_to_add;
|
dive_site_table dive_sites_to_add;
|
||||||
device_table devices_to_add;
|
device_table devices_to_add;
|
||||||
|
|
||||||
/* Process imported dives and generate lists of dives
|
/* Process imported dives and generate lists of dives
|
||||||
* to-be-added and to-be-removed */
|
* to-be-added and to-be-removed */
|
||||||
process_imported_dives(import_log, flags, &dives_to_add, &dives_to_remove, &trips_to_add,
|
process_imported_dives(import_log, flags, &dives_to_add, &dives_to_remove, trips_to_add,
|
||||||
dive_sites_to_add, devices_to_add);
|
dive_sites_to_add, devices_to_add);
|
||||||
|
|
||||||
/* Start by deselecting all dives, so that we don't end up with an invalid selection */
|
/* Start by deselecting all dives, so that we don't end up with an invalid selection */
|
||||||
|
@ -969,9 +966,9 @@ void add_imported_dives(struct divelog *import_log, int flags)
|
||||||
dives_to_add.nr = 0;
|
dives_to_add.nr = 0;
|
||||||
|
|
||||||
/* Add new trips */
|
/* Add new trips */
|
||||||
for (i = 0; i < trips_to_add.nr; i++)
|
for (auto &trip: trips_to_add)
|
||||||
insert_trip(trips_to_add.trips[i], divelog.trips.get());
|
divelog.trips->put(std::move(trip));
|
||||||
trips_to_add.nr = 0;
|
trips_to_add.clear();
|
||||||
|
|
||||||
/* Add new dive sites */
|
/* Add new dive sites */
|
||||||
for (auto &ds: dive_sites_to_add)
|
for (auto &ds: dive_sites_to_add)
|
||||||
|
@ -987,7 +984,6 @@ void add_imported_dives(struct divelog *import_log, int flags)
|
||||||
|
|
||||||
free(dives_to_add.dives);
|
free(dives_to_add.dives);
|
||||||
free(dives_to_remove.dives);
|
free(dives_to_remove.dives);
|
||||||
free(trips_to_add.trips);
|
|
||||||
|
|
||||||
/* Inform frontend of reset data. This should reset all the models. */
|
/* Inform frontend of reset data. This should reset all the models. */
|
||||||
emit_reset_signal();
|
emit_reset_signal();
|
||||||
|
@ -1003,22 +999,17 @@ void add_imported_dives(struct divelog *import_log, int flags)
|
||||||
* Returns true if trip was merged. In this case, the trip will be
|
* Returns true if trip was merged. In this case, the trip will be
|
||||||
* freed.
|
* freed.
|
||||||
*/
|
*/
|
||||||
static bool try_to_merge_trip(dive_trip *trip_import, struct dive_table *import_table, bool prefer_imported,
|
static bool try_to_merge_trip(dive_trip &trip_import, struct dive_table *import_table, bool prefer_imported,
|
||||||
/* output parameters: */
|
/* output parameters: */
|
||||||
struct dive_table *dives_to_add, struct dive_table *dives_to_remove,
|
struct dive_table *dives_to_add, struct dive_table *dives_to_remove,
|
||||||
bool *sequence_changed, int *start_renumbering_at)
|
bool *sequence_changed, int *start_renumbering_at)
|
||||||
{
|
{
|
||||||
int i;
|
for (auto &trip_old: *divelog.trips) {
|
||||||
struct dive_trip *trip_old;
|
if (trips_overlap(trip_import, *trip_old)) {
|
||||||
|
*sequence_changed |= merge_dive_tables(&trip_import.dives, import_table, &trip_old->dives,
|
||||||
for (i = 0; i < divelog.trips->nr; i++) {
|
prefer_imported, trip_old.get(),
|
||||||
trip_old = divelog.trips->trips[i];
|
|
||||||
if (trips_overlap(trip_import, trip_old)) {
|
|
||||||
*sequence_changed |= merge_dive_tables(&trip_import->dives, import_table, &trip_old->dives,
|
|
||||||
prefer_imported, trip_old,
|
|
||||||
dives_to_add, dives_to_remove,
|
dives_to_add, dives_to_remove,
|
||||||
start_renumbering_at);
|
start_renumbering_at);
|
||||||
free_trip(trip_import); /* All dives in trip have been consumed -> free */
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1062,11 +1053,10 @@ static bool try_to_merge_trip(dive_trip *trip_import, struct dive_table *import_
|
||||||
void process_imported_dives(struct divelog *import_log, int flags,
|
void process_imported_dives(struct divelog *import_log, int flags,
|
||||||
/* output parameters: */
|
/* output parameters: */
|
||||||
struct dive_table *dives_to_add, struct dive_table *dives_to_remove,
|
struct dive_table *dives_to_add, struct dive_table *dives_to_remove,
|
||||||
struct trip_table *trips_to_add, dive_site_table &sites_to_add,
|
struct trip_table &trips_to_add, dive_site_table &sites_to_add,
|
||||||
device_table &devices_to_add)
|
device_table &devices_to_add)
|
||||||
{
|
{
|
||||||
int i, j, nr, start_renumbering_at = 0;
|
int i, j, nr, start_renumbering_at = 0;
|
||||||
dive_trip *new_trip;
|
|
||||||
bool sequence_changed = false;
|
bool sequence_changed = false;
|
||||||
bool new_dive_has_number = false;
|
bool new_dive_has_number = false;
|
||||||
bool last_old_dive_is_numbered;
|
bool last_old_dive_is_numbered;
|
||||||
|
@ -1074,7 +1064,7 @@ void process_imported_dives(struct divelog *import_log, int flags,
|
||||||
/* Make sure that output parameters don't contain garbage */
|
/* Make sure that output parameters don't contain garbage */
|
||||||
clear_dive_table(dives_to_add);
|
clear_dive_table(dives_to_add);
|
||||||
clear_dive_table(dives_to_remove);
|
clear_dive_table(dives_to_remove);
|
||||||
clear_trip_table(trips_to_add);
|
trips_to_add.clear();
|
||||||
sites_to_add.clear();
|
sites_to_add.clear();
|
||||||
devices_to_add.clear();
|
devices_to_add.clear();
|
||||||
|
|
||||||
|
@ -1105,7 +1095,7 @@ void process_imported_dives(struct divelog *import_log, int flags,
|
||||||
/* Autogroup tripless dives if desired by user. But don't autogroup
|
/* Autogroup tripless dives if desired by user. But don't autogroup
|
||||||
* if tripless dives should be added to a new trip. */
|
* if tripless dives should be added to a new trip. */
|
||||||
if (!(flags & IMPORT_ADD_TO_NEW_TRIP))
|
if (!(flags & IMPORT_ADD_TO_NEW_TRIP))
|
||||||
autogroup_dives(import_log->dives.get(), import_log->trips.get());
|
autogroup_dives(import_log->dives.get(), *import_log->trips);
|
||||||
|
|
||||||
/* If dive sites already exist, use the existing versions. */
|
/* If dive sites already exist, use the existing versions. */
|
||||||
for (auto &new_ds: *import_log->sites) {
|
for (auto &new_ds: *import_log->sites) {
|
||||||
|
@ -1140,10 +1130,9 @@ void process_imported_dives(struct divelog *import_log, int flags,
|
||||||
* could be smarter here, but realistically not a whole lot of trips
|
* could be smarter here, but realistically not a whole lot of trips
|
||||||
* will be imported so do a simple n*m loop until someone complains.
|
* will be imported so do a simple n*m loop until someone complains.
|
||||||
*/
|
*/
|
||||||
for (i = 0; i < import_log->trips->nr; i++) {
|
for (auto &trip_import: *import_log->trips) {
|
||||||
dive_trip *trip_import = import_log->trips->trips[i];
|
|
||||||
if ((flags & IMPORT_MERGE_ALL_TRIPS) || trip_import->autogen) {
|
if ((flags & IMPORT_MERGE_ALL_TRIPS) || trip_import->autogen) {
|
||||||
if (try_to_merge_trip(trip_import, import_log->dives.get(), flags & IMPORT_PREFER_IMPORTED, dives_to_add, dives_to_remove,
|
if (try_to_merge_trip(*trip_import, import_log->dives.get(), flags & IMPORT_PREFER_IMPORTED, dives_to_add, dives_to_remove,
|
||||||
&sequence_changed, &start_renumbering_at))
|
&sequence_changed, &start_renumbering_at))
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -1160,16 +1149,18 @@ void process_imported_dives(struct divelog *import_log, int flags,
|
||||||
remove_dive(d, import_log->dives.get());
|
remove_dive(d, import_log->dives.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Then, add trip to list of trips to add */
|
|
||||||
insert_trip(trip_import, trips_to_add);
|
|
||||||
trip_import->dives.nr = 0; /* Caller is responsible for adding dives to trip */
|
trip_import->dives.nr = 0; /* Caller is responsible for adding dives to trip */
|
||||||
|
|
||||||
|
/* Finally, add trip to list of trips to add */
|
||||||
|
trips_to_add.put(std::move(trip_import));
|
||||||
}
|
}
|
||||||
import_log->trips->nr = 0; /* All trips were consumed */
|
import_log->trips->clear(); /* All trips were consumed */
|
||||||
|
|
||||||
if ((flags & IMPORT_ADD_TO_NEW_TRIP) && import_log->dives->nr > 0) {
|
if ((flags & IMPORT_ADD_TO_NEW_TRIP) && import_log->dives->nr > 0) {
|
||||||
/* Create a new trip for unassigned dives, if desired. */
|
/* Create a new trip for unassigned dives, if desired. */
|
||||||
new_trip = create_trip_from_dive(import_log->dives->dives[0]);
|
auto [new_trip, idx] = trips_to_add.put(
|
||||||
insert_trip(new_trip, trips_to_add);
|
create_trip_from_dive(import_log->dives->dives[0])
|
||||||
|
);
|
||||||
|
|
||||||
/* Add all remaining dives to this trip */
|
/* Add all remaining dives to this trip */
|
||||||
for (i = 0; i < import_log->dives->nr; i++) {
|
for (i = 0; i < import_log->dives->nr; i++) {
|
||||||
|
@ -1296,7 +1287,7 @@ static int comp_dive_or_trip(struct dive_or_trip a, struct dive_or_trip b)
|
||||||
if (a.dive && b.dive)
|
if (a.dive && b.dive)
|
||||||
return comp_dives(a.dive, b.dive);
|
return comp_dives(a.dive, b.dive);
|
||||||
if (a.trip && b.trip)
|
if (a.trip && b.trip)
|
||||||
return comp_trips(a.trip, b.trip);
|
return comp_trips(*a.trip, *b.trip);
|
||||||
if (a.dive)
|
if (a.dive)
|
||||||
return comp_dive_to_trip(a.dive, b.trip);
|
return comp_dive_to_trip(a.dive, b.trip);
|
||||||
else
|
else
|
||||||
|
|
|
@ -35,7 +35,7 @@ extern void process_loaded_dives();
|
||||||
extern void add_imported_dives(struct divelog *log, int flags);
|
extern void add_imported_dives(struct divelog *log, int flags);
|
||||||
extern void process_imported_dives(struct divelog *import_log, int flags,
|
extern void process_imported_dives(struct divelog *import_log, int flags,
|
||||||
struct dive_table *dives_to_add, struct dive_table *dives_to_remove,
|
struct dive_table *dives_to_add, struct dive_table *dives_to_remove,
|
||||||
struct trip_table *trips_to_add, dive_site_table &sites_to_add,
|
struct trip_table &trips_to_add, dive_site_table &sites_to_add,
|
||||||
std::vector<device> &devices_to_add);
|
std::vector<device> &devices_to_add);
|
||||||
|
|
||||||
extern int dive_table_get_insertion_index(struct dive_table *table, struct dive *dive);
|
extern int dive_table_get_insertion_index(struct dive_table *table, struct dive *dive);
|
||||||
|
|
|
@ -17,15 +17,12 @@ divelog::divelog() :
|
||||||
autogroup(false)
|
autogroup(false)
|
||||||
{
|
{
|
||||||
*dives = empty_dive_table;
|
*dives = empty_dive_table;
|
||||||
*trips = empty_trip_table;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
divelog::~divelog()
|
divelog::~divelog()
|
||||||
{
|
{
|
||||||
if (dives)
|
if (dives)
|
||||||
clear_dive_table(dives.get());
|
clear_dive_table(dives.get());
|
||||||
if (trips)
|
|
||||||
clear_trip_table(trips.get());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
divelog::divelog(divelog &&) = default;
|
divelog::divelog(divelog &&) = default;
|
||||||
|
@ -40,7 +37,14 @@ void divelog::delete_single_dive(int idx)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
struct dive *dive = dives->dives[idx];
|
struct dive *dive = dives->dives[idx];
|
||||||
remove_dive_from_trip(dive, trips.get());
|
struct dive_trip *trip = unregister_dive_from_trip(dive);
|
||||||
|
|
||||||
|
// Deleting a dive may change the order of trips!
|
||||||
|
if (trip)
|
||||||
|
trips->sort();
|
||||||
|
|
||||||
|
if (trip && trip->dives.nr == 0)
|
||||||
|
trips->pull(trip);
|
||||||
unregister_dive_from_dive_site(dive);
|
unregister_dive_from_dive_site(dive);
|
||||||
delete_dive_from_table(dives.get(), idx);
|
delete_dive_from_table(dives.get(), idx);
|
||||||
}
|
}
|
||||||
|
@ -48,12 +52,9 @@ void divelog::delete_single_dive(int idx)
|
||||||
void divelog::clear()
|
void divelog::clear()
|
||||||
{
|
{
|
||||||
while (dives->nr > 0)
|
while (dives->nr > 0)
|
||||||
delete_single_dive(dives->nr - 1);
|
delete_dive_from_table(dives.get(), dives->nr - 1);
|
||||||
sites->clear();
|
sites->clear();
|
||||||
if (trips->nr != 0) {
|
trips->clear();
|
||||||
report_info("Warning: trip table not empty in divelog::clear()!");
|
|
||||||
trips->nr = 0;
|
|
||||||
}
|
|
||||||
devices.clear();
|
devices.clear();
|
||||||
filter_presets->clear();
|
filter_presets->clear();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1384,7 +1384,7 @@ static void finish_active_trip(struct git_parser_state *state)
|
||||||
auto &trip = state->active_trip;
|
auto &trip = state->active_trip;
|
||||||
|
|
||||||
if (trip)
|
if (trip)
|
||||||
insert_trip(trip.release(), state->log->trips.get());
|
state->log->trips->put(std::move(trip));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void finish_active_dive(struct git_parser_state *state)
|
static void finish_active_dive(struct git_parser_state *state)
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0
|
|
||||||
// Convenience classes defining owning pointers to C-objects that
|
|
||||||
// automatically clean up the objects if the pointers go out of
|
|
||||||
// scope. Based on unique_ptr<>.
|
|
||||||
// In the future, we should replace these by real destructors.
|
|
||||||
#ifndef OWNING_PTR_H
|
|
||||||
#define OWNING_PTR_H
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <cstdlib>
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -140,6 +140,10 @@ public:
|
||||||
}
|
}
|
||||||
return it - this->begin();
|
return it - this->begin();
|
||||||
}
|
}
|
||||||
|
// Note: this is silly - finding the pointer by a linear search
|
||||||
|
// is probably significantly faster than doing a binary search.
|
||||||
|
// But it helps finding consistency problems for now. Remove in
|
||||||
|
// due course.
|
||||||
pull_result pull(const T *item) {
|
pull_result pull(const T *item) {
|
||||||
size_t idx = get_idx(item);
|
size_t idx = get_idx(item);
|
||||||
if (idx == std::string::npos) {
|
if (idx == std::string::npos) {
|
||||||
|
@ -148,6 +152,9 @@ public:
|
||||||
}
|
}
|
||||||
return { this->pull_at(idx), idx };
|
return { this->pull_at(idx), idx };
|
||||||
}
|
}
|
||||||
|
void sort() {
|
||||||
|
std::sort(this->begin(), this->end(), [](const auto &a, const auto &b) { return CMP(*a, *b) < 0; });
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -291,7 +291,7 @@ void trip_end(struct parser_state *state)
|
||||||
{
|
{
|
||||||
if (!state->cur_trip)
|
if (!state->cur_trip)
|
||||||
return;
|
return;
|
||||||
insert_trip(state->cur_trip.release(), state->log->trips.get());
|
state->log->trips->put(std::move(state->cur_trip));
|
||||||
}
|
}
|
||||||
|
|
||||||
void picture_start(struct parser_state *state)
|
void picture_start(struct parser_state *state)
|
||||||
|
|
|
@ -983,7 +983,6 @@ static int create_git_tree(git_repository *repo, struct dir *root, bool select_o
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
struct dive *dive;
|
struct dive *dive;
|
||||||
dive_trip *trip;
|
|
||||||
|
|
||||||
git_storage_update_progress(translate("gettextFromC", "Start saving data"));
|
git_storage_update_progress(translate("gettextFromC", "Start saving data"));
|
||||||
save_settings(repo, root);
|
save_settings(repo, root);
|
||||||
|
@ -991,8 +990,8 @@ static int create_git_tree(git_repository *repo, struct dir *root, bool select_o
|
||||||
save_divesites(repo, root);
|
save_divesites(repo, root);
|
||||||
save_filter_presets(repo, root);
|
save_filter_presets(repo, root);
|
||||||
|
|
||||||
for (i = 0; i < divelog.trips->nr; ++i)
|
for (auto &trip: *divelog.trips)
|
||||||
divelog.trips->trips[i]->saved = 0;
|
trip->saved = false;
|
||||||
|
|
||||||
/* save the dives */
|
/* save the dives */
|
||||||
git_storage_update_progress(translate("gettextFromC", "Start saving dives"));
|
git_storage_update_progress(translate("gettextFromC", "Start saving dives"));
|
||||||
|
@ -1000,7 +999,7 @@ static int create_git_tree(git_repository *repo, struct dir *root, bool select_o
|
||||||
struct tm tm;
|
struct tm tm;
|
||||||
struct dir *tree;
|
struct dir *tree;
|
||||||
|
|
||||||
trip = dive->divetrip;
|
dive_trip *trip = dive->divetrip;
|
||||||
|
|
||||||
if (select_only) {
|
if (select_only) {
|
||||||
if (!dive->selected)
|
if (!dive->selected)
|
||||||
|
@ -1010,7 +1009,7 @@ static int create_git_tree(git_repository *repo, struct dir *root, bool select_o
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create the date-based hierarchy */
|
/* Create the date-based hierarchy */
|
||||||
utc_mkdate(trip ? trip_date(trip) : dive->when, &tm);
|
utc_mkdate(trip ? trip_date(*trip) : dive->when, &tm);
|
||||||
tree = mktree(repo, root, "%04d", tm.tm_year);
|
tree = mktree(repo, root, "%04d", tm.tm_year);
|
||||||
tree = mktree(repo, tree, "%02d", tm.tm_mon + 1);
|
tree = mktree(repo, tree, "%02d", tm.tm_mon + 1);
|
||||||
|
|
||||||
|
|
|
@ -438,15 +438,14 @@ static void write_trips(struct membuffer *b, const char *photos_dir, bool select
|
||||||
{
|
{
|
||||||
int i, dive_no = 0;
|
int i, dive_no = 0;
|
||||||
const struct dive *dive;
|
const struct dive *dive;
|
||||||
dive_trip *trip;
|
|
||||||
char sep_ = ' ';
|
char sep_ = ' ';
|
||||||
char *sep = &sep_;
|
char *sep = &sep_;
|
||||||
|
|
||||||
for (i = 0; i < divelog.trips->nr; ++i)
|
for (auto &trip: *divelog.trips)
|
||||||
divelog.trips->trips[i]->saved = 0;
|
trip->saved = 0;
|
||||||
|
|
||||||
for_each_dive (i, dive) {
|
for_each_dive (i, dive) {
|
||||||
trip = dive->divetrip;
|
dive_trip *trip = dive->divetrip;
|
||||||
|
|
||||||
/*Continue if the dive have no trips or we have seen this trip before*/
|
/*Continue if the dive have no trips or we have seen this trip before*/
|
||||||
if (!trip || trip->saved)
|
if (!trip || trip->saved)
|
||||||
|
|
|
@ -543,16 +543,16 @@ int save_dive(FILE *f, struct dive *dive, bool anonymize)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void save_trip(struct membuffer *b, dive_trip *trip, bool anonymize)
|
static void save_trip(struct membuffer *b, dive_trip &trip, bool anonymize)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
struct dive *dive;
|
struct dive *dive;
|
||||||
|
|
||||||
put_format(b, "<trip");
|
put_format(b, "<trip");
|
||||||
show_date(b, trip_date(trip));
|
show_date(b, trip_date(trip));
|
||||||
show_utf8(b, trip->location.c_str(), " location=\'", "\'", 1);
|
show_utf8(b, trip.location.c_str(), " location=\'", "\'", 1);
|
||||||
put_format(b, ">\n");
|
put_format(b, ">\n");
|
||||||
show_utf8(b, trip->notes.c_str(), "<notes>", "</notes>\n", 0);
|
show_utf8(b, trip.notes.c_str(), "<notes>", "</notes>\n", 0);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Incredibly cheesy: we want to save the dives sorted, and they
|
* Incredibly cheesy: we want to save the dives sorted, and they
|
||||||
|
@ -561,7 +561,7 @@ static void save_trip(struct membuffer *b, dive_trip *trip, bool anonymize)
|
||||||
* check the divetrip pointer..
|
* check the divetrip pointer..
|
||||||
*/
|
*/
|
||||||
for_each_dive(i, dive) {
|
for_each_dive(i, dive) {
|
||||||
if (dive->divetrip == trip)
|
if (dive->divetrip == &trip)
|
||||||
save_one_dive_to_mb(b, dive, anonymize);
|
save_one_dive_to_mb(b, dive, anonymize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -642,7 +642,6 @@ static void save_dives_buffer(struct membuffer *b, bool select_only, bool anonym
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
struct dive *dive;
|
struct dive *dive;
|
||||||
dive_trip *trip;
|
|
||||||
|
|
||||||
put_format(b, "<divelog program='subsurface' version='%d'>\n<settings>\n", DATAFORMAT_VERSION);
|
put_format(b, "<divelog program='subsurface' version='%d'>\n<settings>\n", DATAFORMAT_VERSION);
|
||||||
|
|
||||||
|
@ -686,8 +685,8 @@ static void save_dives_buffer(struct membuffer *b, bool select_only, bool anonym
|
||||||
put_format(b, "</site>\n");
|
put_format(b, "</site>\n");
|
||||||
}
|
}
|
||||||
put_format(b, "</divesites>\n<dives>\n");
|
put_format(b, "</divesites>\n<dives>\n");
|
||||||
for (i = 0; i < divelog.trips->nr; ++i)
|
for (auto &trip: *divelog.trips)
|
||||||
divelog.trips->trips[i]->saved = 0;
|
trip->saved = 0;
|
||||||
|
|
||||||
/* save the filter presets */
|
/* save the filter presets */
|
||||||
save_filter_presets(b);
|
save_filter_presets(b);
|
||||||
|
@ -701,7 +700,7 @@ static void save_dives_buffer(struct membuffer *b, bool select_only, bool anonym
|
||||||
save_one_dive_to_mb(b, dive, anonymize);
|
save_one_dive_to_mb(b, dive, anonymize);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
trip = dive->divetrip;
|
dive_trip *trip = dive->divetrip;
|
||||||
|
|
||||||
/* Bare dive without a trip? */
|
/* Bare dive without a trip? */
|
||||||
if (!trip) {
|
if (!trip) {
|
||||||
|
@ -715,7 +714,7 @@ static void save_dives_buffer(struct membuffer *b, bool select_only, bool anonym
|
||||||
|
|
||||||
/* We haven't seen this trip before - save it and all dives */
|
/* We haven't seen this trip before - save it and all dives */
|
||||||
trip->saved = 1;
|
trip->saved = 1;
|
||||||
save_trip(b, trip, anonymize);
|
save_trip(b, *trip, anonymize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
put_format(b, "</dives>\n</divelog>\n");
|
put_format(b, "</dives>\n</divelog>\n");
|
||||||
|
|
|
@ -173,8 +173,8 @@ QVector<dive *> setSelectionCore(const std::vector<dive *> &selection, dive *cur
|
||||||
static void clear_trip_selection()
|
static void clear_trip_selection()
|
||||||
{
|
{
|
||||||
amount_trips_selected = 0;
|
amount_trips_selected = 0;
|
||||||
for (int i = 0; i < divelog.trips->nr; ++i)
|
for (auto &trip: *divelog.trips)
|
||||||
divelog.trips->trips[i]->selected = false;
|
trip->selected = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset the selection to the dives of the "selection" vector and send the appropriate signals.
|
// Reset the selection to the dives of the "selection" vector and send the appropriate signals.
|
||||||
|
@ -221,10 +221,8 @@ void setTripSelection(dive_trip *trip, dive *currentDive)
|
||||||
dive &d = *divelog.dives->dives[i];
|
dive &d = *divelog.dives->dives[i];
|
||||||
d.selected = d.divetrip == trip;
|
d.selected = d.divetrip == trip;
|
||||||
}
|
}
|
||||||
for (int i = 0; i < divelog.trips->nr; ++i) {
|
for (auto &t: *divelog.trips)
|
||||||
dive_trip *t = divelog.trips->trips[i];
|
t->selected = t.get() == trip;
|
||||||
t->selected = t == trip;
|
|
||||||
}
|
|
||||||
|
|
||||||
amount_selected = trip->dives.nr;
|
amount_selected = trip->dives.nr;
|
||||||
amount_trips_selected = 1;
|
amount_trips_selected = 1;
|
||||||
|
@ -315,9 +313,9 @@ struct dive_trip *single_selected_trip()
|
||||||
{
|
{
|
||||||
if (amount_trips_selected != 1)
|
if (amount_trips_selected != 1)
|
||||||
return NULL;
|
return NULL;
|
||||||
for (int i = 0; i < divelog.trips->nr; ++i) {
|
for (auto &trip: *divelog.trips) {
|
||||||
if (divelog.trips->trips[i]->selected)
|
if (trip->selected)
|
||||||
return divelog.trips->trips[i];
|
return trip.get();
|
||||||
}
|
}
|
||||||
report_info("warning: found no selected trip even though one should be selected");
|
report_info("warning: found no selected trip even though one should be selected");
|
||||||
return NULL; // shouldn't happen
|
return NULL; // shouldn't happen
|
||||||
|
|
|
@ -299,26 +299,23 @@ QString formatMinutes(int seconds)
|
||||||
return QString::asprintf("%d:%.2d", FRACTION_TUPLE(seconds, 60));
|
return QString::asprintf("%d:%.2d", FRACTION_TUPLE(seconds, 60));
|
||||||
}
|
}
|
||||||
|
|
||||||
QString formatTripTitle(const dive_trip *trip)
|
QString formatTripTitle(const dive_trip &trip)
|
||||||
{
|
{
|
||||||
if (!trip)
|
|
||||||
return QString();
|
|
||||||
|
|
||||||
timestamp_t when = trip_date(trip);
|
timestamp_t when = trip_date(trip);
|
||||||
bool getday = trip_is_single_day(trip);
|
bool getday = trip_is_single_day(trip);
|
||||||
|
|
||||||
QDateTime localTime = timestampToDateTime(when);
|
QDateTime localTime = timestampToDateTime(when);
|
||||||
|
|
||||||
QString prefix = !trip->location.empty() ? QString::fromStdString(trip->location) + ", " : QString();
|
QString prefix = !trip.location.empty() ? QString::fromStdString(trip.location) + ", " : QString();
|
||||||
if (getday)
|
if (getday)
|
||||||
return prefix + loc.toString(localTime, prefs.date_format);
|
return prefix + loc.toString(localTime, prefs.date_format);
|
||||||
else
|
else
|
||||||
return prefix + loc.toString(localTime, "MMM yyyy");
|
return prefix + loc.toString(localTime, "MMM yyyy");
|
||||||
}
|
}
|
||||||
|
|
||||||
QString formatTripTitleWithDives(const dive_trip *trip)
|
QString formatTripTitleWithDives(const dive_trip &trip)
|
||||||
{
|
{
|
||||||
int nr = trip->dives.nr;
|
int nr = trip.dives.nr;
|
||||||
return formatTripTitle(trip) + " " +
|
return formatTripTitle(trip) + " " +
|
||||||
gettextFromC::tr("(%n dive(s))", "", nr);
|
gettextFromC::tr("(%n dive(s))", "", nr);
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@ QString formatDiveDateTime(const dive *d);
|
||||||
QString formatDiveGasString(const dive *d);
|
QString formatDiveGasString(const dive *d);
|
||||||
QString formatDayOfWeek(int day);
|
QString formatDayOfWeek(int day);
|
||||||
QString formatMinutes(int seconds);
|
QString formatMinutes(int seconds);
|
||||||
QString formatTripTitle(const dive_trip *trip);
|
QString formatTripTitle(const dive_trip &trip);
|
||||||
QString formatTripTitleWithDives(const dive_trip *trip);
|
QString formatTripTitleWithDives(const dive_trip &trip);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
177
core/trip.cpp
177
core/trip.cpp
|
@ -12,22 +12,19 @@
|
||||||
#ifdef DEBUG_TRIP
|
#ifdef DEBUG_TRIP
|
||||||
void dump_trip_list()
|
void dump_trip_list()
|
||||||
{
|
{
|
||||||
dive_trip *trip;
|
|
||||||
int i = 0;
|
|
||||||
timestamp_t last_time = 0;
|
timestamp_t last_time = 0;
|
||||||
|
|
||||||
for (i = 0; i < divelog.trips->nr; ++i) {
|
for (auto &trip: divelog.trips) {
|
||||||
struct tm tm;
|
struct tm tm;
|
||||||
trip = divelog.trips->trips[i];
|
utc_mkdate(trip_date(*trip), &tm);
|
||||||
utc_mkdate(trip_date(trip), &tm);
|
if (trip_date(*trip) < last_time)
|
||||||
if (trip_date(trip) < last_time)
|
|
||||||
printf("\n\ntrip_table OUT OF ORDER!!!\n\n\n");
|
printf("\n\ntrip_table OUT OF ORDER!!!\n\n\n");
|
||||||
printf("%s trip %d to \"%s\" on %04u-%02u-%02u %02u:%02u:%02u (%d dives - %p)\n",
|
printf("%s trip %d to \"%s\" on %04u-%02u-%02u %02u:%02u:%02u (%d dives - %p)\n",
|
||||||
trip->autogen ? "autogen " : "",
|
trip->autogen ? "autogen " : "",
|
||||||
i + 1, trip->location.c_str(),
|
i + 1, trip->location.c_str(),
|
||||||
tm.tm_year, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec,
|
tm.tm_year, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec,
|
||||||
trip->dives.nr, trip);
|
trip->dives.nr, trip.get());
|
||||||
last_time = trip_date(trip);
|
last_time = trip_date(*trip);
|
||||||
}
|
}
|
||||||
printf("-----\n");
|
printf("-----\n");
|
||||||
}
|
}
|
||||||
|
@ -42,35 +39,18 @@ dive_trip::~dive_trip()
|
||||||
free(dives.dives);
|
free(dives.dives);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* free resources associated with a trip structure */
|
timestamp_t trip_date(const struct dive_trip &trip)
|
||||||
void free_trip(dive_trip *trip)
|
|
||||||
{
|
{
|
||||||
delete trip;
|
if (trip.dives.nr == 0)
|
||||||
|
return 0;
|
||||||
|
return trip.dives.dives[0]->when;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Trip table functions */
|
static timestamp_t trip_enddate(const struct dive_trip &trip)
|
||||||
static MAKE_GET_IDX(trip_table, struct dive_trip *, trips)
|
|
||||||
static MAKE_GROW_TABLE(trip_table, struct dive_trip *, trips)
|
|
||||||
static MAKE_GET_INSERTION_INDEX(trip_table, struct dive_trip *, trips, trip_less_than)
|
|
||||||
static MAKE_ADD_TO(trip_table, struct dive_trip *, trips)
|
|
||||||
static MAKE_REMOVE_FROM(trip_table, trips)
|
|
||||||
MAKE_SORT(trip_table, struct dive_trip *, trips, comp_trips)
|
|
||||||
MAKE_REMOVE(trip_table, struct dive_trip *, trip)
|
|
||||||
MAKE_CLEAR_TABLE(trip_table, trips, trip)
|
|
||||||
MAKE_MOVE_TABLE(trip_table, trips)
|
|
||||||
|
|
||||||
timestamp_t trip_date(const struct dive_trip *trip)
|
|
||||||
{
|
{
|
||||||
if (!trip || trip->dives.nr == 0)
|
if (trip.dives.nr == 0)
|
||||||
return 0;
|
return 0;
|
||||||
return trip->dives.dives[0]->when;
|
return dive_endtime(trip.dives.dives[trip.dives.nr - 1]);
|
||||||
}
|
|
||||||
|
|
||||||
timestamp_t trip_enddate(const struct dive_trip *trip)
|
|
||||||
{
|
|
||||||
if (!trip || trip->dives.nr == 0)
|
|
||||||
return 0;
|
|
||||||
return dive_endtime(trip->dives.dives[trip->dives.nr - 1]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check if we have a trip right before / after this dive */
|
/* check if we have a trip right before / after this dive */
|
||||||
|
@ -117,39 +97,9 @@ struct dive_trip *unregister_dive_from_trip(struct dive *dive)
|
||||||
return trip;
|
return trip;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void delete_trip(dive_trip *trip, struct trip_table *trip_table_arg)
|
std::unique_ptr<dive_trip> create_trip_from_dive(const struct dive *dive)
|
||||||
{
|
{
|
||||||
remove_trip(trip, trip_table_arg);
|
auto trip = std::make_unique<dive_trip>();
|
||||||
free_trip(trip);
|
|
||||||
}
|
|
||||||
|
|
||||||
void remove_dive_from_trip(struct dive *dive, struct trip_table *trip_table_arg)
|
|
||||||
{
|
|
||||||
struct dive_trip *trip = unregister_dive_from_trip(dive);
|
|
||||||
if (trip && trip->dives.nr == 0)
|
|
||||||
delete_trip(trip, trip_table_arg);
|
|
||||||
}
|
|
||||||
|
|
||||||
dive_trip *alloc_trip()
|
|
||||||
{
|
|
||||||
return new dive_trip;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* insert the trip into the trip table */
|
|
||||||
void insert_trip(struct dive_trip *dive_trip, struct trip_table *trip_table_arg)
|
|
||||||
{
|
|
||||||
int idx = trip_table_get_insertion_index(trip_table_arg, dive_trip);
|
|
||||||
add_to_trip_table(trip_table_arg, idx, dive_trip);
|
|
||||||
#ifdef DEBUG_TRIP
|
|
||||||
dump_trip_list();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
dive_trip *create_trip_from_dive(struct dive *dive)
|
|
||||||
{
|
|
||||||
dive_trip *trip;
|
|
||||||
|
|
||||||
trip = alloc_trip();
|
|
||||||
trip->location = get_dive_location(dive);
|
trip->location = get_dive_location(dive);
|
||||||
|
|
||||||
return trip;
|
return trip;
|
||||||
|
@ -162,13 +112,12 @@ dive_trip *create_trip_from_dive(struct dive *dive)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Find a trip a new dive should be autogrouped with. If no such trips
|
* Find a trip a new dive should be autogrouped with. If no such trips
|
||||||
* exist, allocate a new trip. The bool "*allocated" is set to true
|
* exist, allocate a new trip. A unique_ptr is returned if a new trip
|
||||||
* if a new trip was allocated.
|
* was allocated. The caller has to store it.
|
||||||
*/
|
*/
|
||||||
dive_trip *get_trip_for_new_dive(struct dive *new_dive, bool *allocated)
|
std::pair<dive_trip *, std::unique_ptr<dive_trip>> get_trip_for_new_dive(const struct dive *new_dive)
|
||||||
{
|
{
|
||||||
struct dive *d;
|
dive *d;
|
||||||
dive_trip *trip;
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* Find dive that is within TRIP_THRESHOLD of current dive */
|
/* Find dive that is within TRIP_THRESHOLD of current dive */
|
||||||
|
@ -177,35 +126,30 @@ dive_trip *get_trip_for_new_dive(struct dive *new_dive, bool *allocated)
|
||||||
if (d->when >= new_dive->when + TRIP_THRESHOLD)
|
if (d->when >= new_dive->when + TRIP_THRESHOLD)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (d->when + TRIP_THRESHOLD >= new_dive->when && d->divetrip) {
|
if (d->when + TRIP_THRESHOLD >= new_dive->when && d->divetrip)
|
||||||
/* Found a dive with trip in the range */
|
return { d->divetrip, nullptr }; /* Found a dive with trip in the range */
|
||||||
*allocated = false;
|
|
||||||
return d->divetrip;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Didn't find a trip -> allocate a new one */
|
/* Didn't find a trip -> allocate a new one */
|
||||||
trip = create_trip_from_dive(new_dive);
|
auto trip = create_trip_from_dive(new_dive);
|
||||||
trip->autogen = true;
|
trip->autogen = true;
|
||||||
*allocated = true;
|
auto t = trip.get();
|
||||||
return trip;
|
return { t, std::move(trip) };
|
||||||
}
|
}
|
||||||
|
|
||||||
/* lookup of trip in main trip_table based on its id */
|
/* lookup of trip in main trip_table based on its id */
|
||||||
dive_trip *get_trip_by_uniq_id(int tripId)
|
dive_trip *get_trip_by_uniq_id(int tripId)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < divelog.trips->nr; i++) {
|
auto it = std::find_if(divelog.trips->begin(), divelog.trips->end(),
|
||||||
if (divelog.trips->trips[i]->id == tripId)
|
[tripId](auto &t) { return t->id == tripId; });
|
||||||
return divelog.trips->trips[i];
|
return it != divelog.trips->end() ? it->get() : nullptr;
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if two trips overlap time-wise up to trip threshold. */
|
/* Check if two trips overlap time-wise up to trip threshold. */
|
||||||
bool trips_overlap(const struct dive_trip *t1, const struct dive_trip *t2)
|
bool trips_overlap(const struct dive_trip &t1, const struct dive_trip &t2)
|
||||||
{
|
{
|
||||||
/* First, handle the empty-trip cases. */
|
/* First, handle the empty-trip cases. */
|
||||||
if (t1->dives.nr == 0 || t2->dives.nr == 0)
|
if (t1.dives.nr == 0 || t2.dives.nr == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (trip_date(t1) < trip_date(t2))
|
if (trip_date(t1) < trip_date(t2))
|
||||||
|
@ -217,21 +161,22 @@ bool trips_overlap(const struct dive_trip *t1, const struct dive_trip *t2)
|
||||||
/*
|
/*
|
||||||
* Collect dives for auto-grouping. Pass in first dive which should be checked.
|
* Collect dives for auto-grouping. Pass in first dive which should be checked.
|
||||||
* Returns range of dives that should be autogrouped and trip it should be
|
* Returns range of dives that should be autogrouped and trip it should be
|
||||||
* associated to. If the returned trip was newly allocated, the last bool
|
* associated to. If the returned trip was newly allocated, a std::unique_ptr<>
|
||||||
|
* to the trip is returned.
|
||||||
* is set to true. Caller still has to register it in the system. Note
|
* is set to true. Caller still has to register it in the system. Note
|
||||||
* whereas this looks complicated - it is needed by the undo-system, which
|
* whereas this looks complicated - it is needed by the undo-system, which
|
||||||
* manually injects the new trips. If there are no dives to be autogrouped,
|
* manually injects the new trips. If there are no dives to be autogrouped,
|
||||||
* return NULL.
|
* return NULL.
|
||||||
*/
|
*/
|
||||||
dive_trip *get_dives_to_autogroup(struct dive_table *table, int start, int *from, int *to, bool *allocated)
|
std::vector<dives_to_autogroup_result> get_dives_to_autogroup(struct dive_table *table)
|
||||||
{
|
{
|
||||||
int i;
|
std::vector<dives_to_autogroup_result> res;
|
||||||
struct dive *lastdive = NULL;
|
struct dive *lastdive = NULL;
|
||||||
|
|
||||||
/* Find first dive that should be merged and remember any previous
|
/* Find first dive that should be merged and remember any previous
|
||||||
* dive that could be merged into.
|
* dive that could be merged into.
|
||||||
*/
|
*/
|
||||||
for (i = start; i < table->nr; i++) {
|
for (int i = 0; i < table->nr; ++i) {
|
||||||
struct dive *dive = table->dives[i];
|
struct dive *dive = table->dives[i];
|
||||||
dive_trip *trip;
|
dive_trip *trip;
|
||||||
|
|
||||||
|
@ -248,22 +193,22 @@ dive_trip *get_dives_to_autogroup(struct dive_table *table, int start, int *from
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We found a dive, let's see if we have to allocate a new trip */
|
/* We found a dive, let's see if we have to allocate a new trip */
|
||||||
|
std::unique_ptr<dive_trip> allocated;
|
||||||
if (!lastdive || dive->when >= lastdive->when + TRIP_THRESHOLD) {
|
if (!lastdive || dive->when >= lastdive->when + TRIP_THRESHOLD) {
|
||||||
/* allocate new trip */
|
/* allocate new trip */
|
||||||
trip = create_trip_from_dive(dive);
|
allocated = create_trip_from_dive(dive);
|
||||||
trip->autogen = true;
|
allocated->autogen = true;
|
||||||
*allocated = true;
|
trip = allocated.get();
|
||||||
} else {
|
} else {
|
||||||
/* use trip of previous dive */
|
/* use trip of previous dive */
|
||||||
trip = lastdive->divetrip;
|
trip = lastdive->divetrip;
|
||||||
*allocated = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now, find all dives that will be added to this trip
|
// Now, find all dives that will be added to this trip
|
||||||
lastdive = dive;
|
lastdive = dive;
|
||||||
*from = i;
|
int to;
|
||||||
for (*to = *from + 1; *to < table->nr; (*to)++) {
|
for (to = i + 1; to < table->nr; to++) {
|
||||||
dive = table->dives[*to];
|
dive = table->dives[to];
|
||||||
if (dive->divetrip || dive->notrip ||
|
if (dive->divetrip || dive->notrip ||
|
||||||
dive->when >= lastdive->when + TRIP_THRESHOLD)
|
dive->when >= lastdive->when + TRIP_THRESHOLD)
|
||||||
break;
|
break;
|
||||||
|
@ -271,11 +216,11 @@ dive_trip *get_dives_to_autogroup(struct dive_table *table, int start, int *from
|
||||||
trip->location = get_dive_location(dive);
|
trip->location = get_dive_location(dive);
|
||||||
lastdive = dive;
|
lastdive = dive;
|
||||||
}
|
}
|
||||||
return trip;
|
res.push_back({ i, to, trip, std::move(allocated) });
|
||||||
|
i = to - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Did not find anyhting - mark as end */
|
return res;
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Out of two strings, get the string that is not empty (if any). */
|
/* Out of two strings, get the string that is not empty (if any). */
|
||||||
|
@ -286,11 +231,10 @@ static std::string non_empty_string(const std::string &a, const std::string &b)
|
||||||
|
|
||||||
/* This combines the information of two trips, generating a
|
/* This combines the information of two trips, generating a
|
||||||
* new trip. To support undo, we have to preserve the old trips. */
|
* new trip. To support undo, we have to preserve the old trips. */
|
||||||
dive_trip *combine_trips(struct dive_trip *trip_a, struct dive_trip *trip_b)
|
std::unique_ptr<dive_trip> combine_trips(struct dive_trip *trip_a, struct dive_trip *trip_b)
|
||||||
{
|
{
|
||||||
dive_trip *trip;
|
auto trip = std::make_unique<dive_trip>();
|
||||||
|
|
||||||
trip = alloc_trip();
|
|
||||||
trip->location = non_empty_string(trip_a->location, trip_b->location);
|
trip->location = non_empty_string(trip_a->location, trip_b->location);
|
||||||
trip->notes = non_empty_string(trip_a->notes, trip_b->notes);
|
trip->notes = non_empty_string(trip_a->notes, trip_b->notes);
|
||||||
|
|
||||||
|
@ -298,20 +242,19 @@ dive_trip *combine_trips(struct dive_trip *trip_a, struct dive_trip *trip_b)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Trips are compared according to the first dive in the trip. */
|
/* Trips are compared according to the first dive in the trip. */
|
||||||
int comp_trips(const struct dive_trip *a, const struct dive_trip *b)
|
int comp_trips(const struct dive_trip &a, const struct dive_trip &b)
|
||||||
{
|
{
|
||||||
/* This should never happen, nevertheless don't crash on trips
|
// To make sure that trips never compare equal, compare by
|
||||||
* with no (or worse a negative number of) dives. */
|
// address if both are empty.
|
||||||
if (a->dives.nr <= 0)
|
if (&a == &b)
|
||||||
return b->dives.nr <= 0 ? 0 : -1;
|
return 0; // reflexivity. shouldn't happen.
|
||||||
if (b->dives.nr <= 0)
|
if (a.dives.nr <= 0 && b.dives.nr <= 0)
|
||||||
|
return &a < &b ? -1 : 1;
|
||||||
|
if (a.dives.nr <= 0)
|
||||||
|
return -1;
|
||||||
|
if (b.dives.nr <= 0)
|
||||||
return 1;
|
return 1;
|
||||||
return comp_dives(a->dives.dives[0], b->dives.dives[0]);
|
return comp_dives(a.dives.dives[0], b.dives.dives[0]);
|
||||||
}
|
|
||||||
|
|
||||||
bool trip_less_than(const struct dive_trip *a, const struct dive_trip *b)
|
|
||||||
{
|
|
||||||
return comp_trips(a, b) < 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool is_same_day(timestamp_t trip_when, timestamp_t dive_when)
|
static bool is_same_day(timestamp_t trip_when, timestamp_t dive_when)
|
||||||
|
@ -330,12 +273,12 @@ static bool is_same_day(timestamp_t trip_when, timestamp_t dive_when)
|
||||||
return (tmd.tm_mday == tmt.tm_mday) && (tmd.tm_mon == tmt.tm_mon) && (tmd.tm_year == tmt.tm_year);
|
return (tmd.tm_mday == tmt.tm_mday) && (tmd.tm_mon == tmt.tm_mon) && (tmd.tm_year == tmt.tm_year);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool trip_is_single_day(const struct dive_trip *trip)
|
bool trip_is_single_day(const struct dive_trip &trip)
|
||||||
{
|
{
|
||||||
if (trip->dives.nr <= 1)
|
if (trip.dives.nr <= 1)
|
||||||
return true;
|
return true;
|
||||||
return is_same_day(trip->dives.dives[0]->when,
|
return is_same_day(trip.dives.dives[0]->when,
|
||||||
trip->dives.dives[trip->dives.nr - 1]->when);
|
trip.dives.dives[trip.dives.nr - 1]->when);
|
||||||
}
|
}
|
||||||
|
|
||||||
int trip_shown_dives(const struct dive_trip *trip)
|
int trip_shown_dives(const struct dive_trip *trip)
|
||||||
|
|
46
core/trip.h
46
core/trip.h
|
@ -3,6 +3,7 @@
|
||||||
#define TRIP_H
|
#define TRIP_H
|
||||||
|
|
||||||
#include "divelist.h"
|
#include "divelist.h"
|
||||||
|
#include "owning_table.h"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
@ -21,42 +22,37 @@ struct dive_trip
|
||||||
~dive_trip();
|
~dive_trip();
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct trip_table {
|
int comp_trips(const dive_trip &t1, const dive_trip &t2);
|
||||||
int nr, allocated;
|
|
||||||
struct dive_trip **trips;
|
|
||||||
} trip_table_t;
|
|
||||||
|
|
||||||
static const trip_table_t empty_trip_table = { 0, 0, (struct dive_trip **)0 };
|
struct trip_table : public sorted_owning_table<dive_trip, &comp_trips> {
|
||||||
|
};
|
||||||
|
|
||||||
extern void add_dive_to_trip(struct dive *, dive_trip *);
|
extern void add_dive_to_trip(struct dive *, dive_trip *);
|
||||||
extern struct dive_trip *unregister_dive_from_trip(struct dive *dive);
|
extern struct dive_trip *unregister_dive_from_trip(struct dive *dive);
|
||||||
extern void remove_dive_from_trip(struct dive *dive, struct trip_table *trip_table_arg);
|
|
||||||
|
|
||||||
extern void insert_trip(dive_trip *trip, struct trip_table *trip_table_arg);
|
extern timestamp_t trip_date(const struct dive_trip &trip);
|
||||||
extern int remove_trip(const dive_trip *trip, struct trip_table *trip_table_arg);
|
|
||||||
extern void free_trip(dive_trip *trip);
|
|
||||||
extern timestamp_t trip_date(const struct dive_trip *trip);
|
|
||||||
extern timestamp_t trip_enddate(const struct dive_trip *trip);
|
|
||||||
|
|
||||||
extern bool trip_less_than(const struct dive_trip *a, const struct dive_trip *b);
|
extern std::unique_ptr<dive_trip> create_trip_from_dive(const struct dive *dive);
|
||||||
extern int comp_trips(const struct dive_trip *a, const struct dive_trip *b);
|
extern dive_trip *create_and_hookup_trip_from_dive(const struct dive *dive, struct trip_table &trip_table_arg);
|
||||||
extern void sort_trip_table(struct trip_table *table);
|
|
||||||
|
|
||||||
extern dive_trip *alloc_trip();
|
// Result item of get_dives_to_autogroup()
|
||||||
extern dive_trip *create_trip_from_dive(struct dive *dive);
|
struct dives_to_autogroup_result {
|
||||||
extern dive_trip *get_dives_to_autogroup(struct dive_table *table, int start, int *from, int *to, bool *allocated);
|
int from, to; // Group dives in the range [from, to)
|
||||||
extern dive_trip *get_trip_for_new_dive(struct dive *new_dive, bool *allocated);
|
dive_trip *trip; // Pointer to trip
|
||||||
|
std::unique_ptr<dive_trip> created_trip;
|
||||||
|
// Is set if the trip was newly created - caller has to store it.
|
||||||
|
};
|
||||||
|
|
||||||
|
extern std::vector<dives_to_autogroup_result> get_dives_to_autogroup(struct dive_table *table);
|
||||||
|
extern std::pair<dive_trip *, std::unique_ptr<dive_trip>> get_trip_for_new_dive(const struct dive *new_dive);
|
||||||
extern dive_trip *get_trip_by_uniq_id(int tripId);
|
extern dive_trip *get_trip_by_uniq_id(int tripId);
|
||||||
extern bool trips_overlap(const struct dive_trip *t1, const struct dive_trip *t2);
|
extern bool trips_overlap(const struct dive_trip &t1, const struct dive_trip &t2);
|
||||||
|
|
||||||
extern dive_trip *combine_trips(struct dive_trip *trip_a, struct dive_trip *trip_b);
|
extern std::unique_ptr<dive_trip> combine_trips(struct dive_trip *trip_a, struct dive_trip *trip_b);
|
||||||
extern bool is_trip_before_after(const struct dive *dive, bool before);
|
extern bool is_trip_before_after(const struct dive *dive, bool before);
|
||||||
extern bool trip_is_single_day(const struct dive_trip *trip);
|
extern bool trip_is_single_day(const struct dive_trip &trip);
|
||||||
extern int trip_shown_dives(const struct dive_trip *trip);
|
extern int trip_shown_dives(const struct dive_trip *trip);
|
||||||
|
|
||||||
void move_trip_table(struct trip_table *src, struct trip_table *dst);
|
|
||||||
void clear_trip_table(struct trip_table *table);
|
|
||||||
|
|
||||||
#ifdef DEBUG_TRIP
|
#ifdef DEBUG_TRIP
|
||||||
extern void dump_trip_list();
|
extern void dump_trip_list();
|
||||||
#endif
|
#endif
|
||||||
|
@ -65,6 +61,6 @@ extern void dump_trip_list();
|
||||||
* passed through QVariants and through QML. See comment in dive.h. */
|
* passed through QVariants and through QML. See comment in dive.h. */
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
Q_DECLARE_METATYPE(struct dive_trip *);
|
Q_DECLARE_METATYPE(struct dive_trip *);
|
||||||
Q_DECLARE_METATYPE(trip_table_t *);
|
Q_DECLARE_METATYPE(trip_table *);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -169,7 +169,7 @@ void TabDiveNotes::updateDateTime(const struct dive *d)
|
||||||
|
|
||||||
void TabDiveNotes::updateTripDate(const struct dive_trip *t)
|
void TabDiveNotes::updateTripDate(const struct dive_trip *t)
|
||||||
{
|
{
|
||||||
QDateTime localTime = timestampToDateTime(trip_date(t));
|
QDateTime localTime = timestampToDateTime(trip_date(*t));
|
||||||
ui.dateEdit->setDate(localTime.date());
|
ui.dateEdit->setDate(localTime.date());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,9 +18,9 @@ TripSelectionDialog::TripSelectionDialog(QWidget *parent) : QDialog(parent)
|
||||||
|
|
||||||
// We could use a model, but it seems barely worth the hassle.
|
// We could use a model, but it seems barely worth the hassle.
|
||||||
QStringList list;
|
QStringList list;
|
||||||
list.reserve(divelog.trips->nr);
|
list.reserve(divelog.trips->size());
|
||||||
for (int i = 0; i < divelog.trips->nr; ++i)
|
for (auto &trip: *divelog.trips)
|
||||||
list.push_back(formatTripTitleWithDives(divelog.trips->trips[i]));
|
list.push_back(formatTripTitleWithDives(*trip));
|
||||||
ui.trips->addItems(list);
|
ui.trips->addItems(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,9 +37,9 @@ dive_trip *TripSelectionDialog::selectedTrip() const
|
||||||
if (rows.size() != 1)
|
if (rows.size() != 1)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
int idx = rows[0].row();
|
int idx = rows[0].row();
|
||||||
if (idx < 0 || idx >= divelog.trips->nr)
|
if (idx < 0 || static_cast<size_t>(idx) >= divelog.trips->size())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
return divelog.trips->trips[idx];
|
return (*divelog.trips)[idx].get();
|
||||||
}
|
}
|
||||||
|
|
||||||
dive_trip *TripSelectionDialog::getTrip()
|
dive_trip *TripSelectionDialog::getTrip()
|
||||||
|
|
|
@ -69,7 +69,7 @@ QString DiveTripModelBase::tripShortDate(const dive_trip *trip)
|
||||||
{
|
{
|
||||||
if (!trip)
|
if (!trip)
|
||||||
return QString();
|
return QString();
|
||||||
QDateTime firstTime = timestampToDateTime(trip_date(trip));
|
QDateTime firstTime = timestampToDateTime(trip_date(*trip));
|
||||||
QString firstMonth = firstTime.toString("MMM");
|
QString firstMonth = firstTime.toString("MMM");
|
||||||
return QStringLiteral("%1\n'%2").arg(firstMonth,firstTime.toString("yy"));
|
return QStringLiteral("%1\n'%2").arg(firstMonth,firstTime.toString("yy"));
|
||||||
}
|
}
|
||||||
|
@ -85,7 +85,7 @@ QString DiveTripModelBase::tripTitle(const dive_trip *trip)
|
||||||
|
|
||||||
if (title.isEmpty()) {
|
if (title.isEmpty()) {
|
||||||
// so use the date range
|
// so use the date range
|
||||||
QDateTime firstTime = timestampToDateTime(trip_date(trip));
|
QDateTime firstTime = timestampToDateTime(trip_date(*trip));
|
||||||
QString firstMonth = firstTime.toString("MMM");
|
QString firstMonth = firstTime.toString("MMM");
|
||||||
QString firstYear = firstTime.toString("yyyy");
|
QString firstYear = firstTime.toString("yyyy");
|
||||||
QDateTime lastTime = timestampToDateTime(trip->dives.dives[0]->when);
|
QDateTime lastTime = timestampToDateTime(trip->dives.dives[0]->when);
|
||||||
|
@ -128,7 +128,7 @@ QVariant DiveTripModelBase::tripData(const dive_trip *trip, int column, int role
|
||||||
int countShown = trip_shown_dives(trip);
|
int countShown = trip_shown_dives(trip);
|
||||||
if (countShown < trip->dives.nr)
|
if (countShown < trip->dives.nr)
|
||||||
shownText = tr("(%1 shown)").arg(countShown);
|
shownText = tr("(%1 shown)").arg(countShown);
|
||||||
return formatTripTitleWithDives(trip) + " " + shownText;
|
return formatTripTitleWithDives(*trip) + " " + shownText;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -817,7 +817,7 @@ dive *DiveTripModelTree::Item::getDive() const
|
||||||
|
|
||||||
timestamp_t DiveTripModelTree::Item::when() const
|
timestamp_t DiveTripModelTree::Item::when() const
|
||||||
{
|
{
|
||||||
return d_or_t.trip ? trip_date(d_or_t.trip) : d_or_t.dive->when;
|
return d_or_t.trip ? trip_date(*d_or_t.trip) : d_or_t.dive->when;
|
||||||
}
|
}
|
||||||
|
|
||||||
dive_or_trip DiveTripModelTree::tripOrDive(const QModelIndex &index) const
|
dive_or_trip DiveTripModelTree::tripOrDive(const QModelIndex &index) const
|
||||||
|
|
|
@ -74,8 +74,8 @@ struct TripWrapper {
|
||||||
QString name;
|
QString name;
|
||||||
timestamp_t date;
|
timestamp_t date;
|
||||||
TripWrapper(const dive_trip *t) : t(t),
|
TripWrapper(const dive_trip *t) : t(t),
|
||||||
name(formatTripTitle(t)), // safe to pass null
|
name(t ? formatTripTitle(*t) : QString()),
|
||||||
date(trip_date(t)) // safe to pass null
|
date(t ? trip_date(*t) : 0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
bool operator<(const TripWrapper &t2) const {
|
bool operator<(const TripWrapper &t2) const {
|
||||||
|
@ -1868,7 +1868,7 @@ struct TripVariable : public StatsVariableTemplate<StatsVariable::Type::Discrete
|
||||||
return StatsTranslations::tr("Dive trip");
|
return StatsTranslations::tr("Dive trip");
|
||||||
}
|
}
|
||||||
QString diveCategories(const dive *d) const override {
|
QString diveCategories(const dive *d) const override {
|
||||||
return formatTripTitle(d->divetrip);
|
return d->divetrip ? formatTripTitle(*d->divetrip) : QString();
|
||||||
}
|
}
|
||||||
std::vector<const StatsBinner *> binners() const override {
|
std::vector<const StatsBinner *> binners() const override {
|
||||||
return { &trip_binner };
|
return { &trip_binner };
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue