mirror of
https://github.com/subsurface/subsurface.git
synced 2024-11-27 20:58:47 +00:00
core: turn C dive-table into an owning table
This is a humongous commit, because it touches all parts of the code. It removes the last user of our horrible TABLE macros, which simulate std::vector<> in a very clumsy way. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
parent
f00c30ad4a
commit
b95ac3f79c
73 changed files with 1030 additions and 1230 deletions
|
@ -10,7 +10,7 @@ ColumnLimit: 0
|
|||
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||
ConstructorInitializerIndentWidth: 8
|
||||
ContinuationIndentWidth: 8
|
||||
ForEachMacros: [ 'for_each_dive', 'for_each_line' ]
|
||||
ForEachMacros: [ 'for_each_line' ]
|
||||
IndentFunctionDeclarationAfterType: false #personal taste, good for long methods
|
||||
IndentWidth: 8
|
||||
MaxEmptyLinesToKeep: 2
|
||||
|
|
|
@ -217,6 +217,7 @@ HEADERS += \
|
|||
core/picture.h \
|
||||
core/planner.h \
|
||||
core/divesite.h \
|
||||
core/divesitetable.h \
|
||||
core/checkcloudconnection.h \
|
||||
core/cochran.h \
|
||||
core/color.h \
|
||||
|
@ -246,6 +247,8 @@ HEADERS += \
|
|||
core/subsurfacestartup.h \
|
||||
core/subsurfacesysinfo.h \
|
||||
core/taxonomy.h \
|
||||
core/trip.h \
|
||||
core/triptable.h \
|
||||
core/uemis.h \
|
||||
core/webservice.h \
|
||||
core/windowtitleupdate.h \
|
||||
|
|
|
@ -41,12 +41,12 @@ static constexpr int profileScale = 4;
|
|||
static constexpr int profileWidth = 800 * profileScale;
|
||||
static constexpr int profileHeight = 600 * profileScale;
|
||||
|
||||
static void exportProfile(ProfileScene *profile, const struct dive *dive, const QString &filename)
|
||||
static void exportProfile(ProfileScene &profile, const struct dive &dive, const QString &filename)
|
||||
{
|
||||
QImage image = QImage(QSize(profileWidth, profileHeight), QImage::Format_RGB32);
|
||||
QPainter paint;
|
||||
paint.begin(&image);
|
||||
profile->draw(&paint, QRect(0, 0, profileWidth, profileHeight), dive, 0, nullptr, false);
|
||||
profile.draw(&paint, QRect(0, 0, profileWidth, profileHeight), &dive, 0, nullptr, false);
|
||||
image.save(filename);
|
||||
}
|
||||
|
||||
|
@ -57,17 +57,15 @@ static std::unique_ptr<ProfileScene> getPrintProfile()
|
|||
|
||||
void exportProfile(QString filename, bool selected_only, ExportCallback &cb)
|
||||
{
|
||||
struct dive *dive;
|
||||
int i;
|
||||
int count = 0;
|
||||
if (!filename.endsWith(".png", Qt::CaseInsensitive))
|
||||
filename = filename.append(".png");
|
||||
QFileInfo fi(filename);
|
||||
|
||||
int todo = selected_only ? amount_selected : divelog.dives->nr;
|
||||
int todo = selected_only ? amount_selected : static_cast<int>(divelog.dives.size());
|
||||
int done = 0;
|
||||
auto profile = getPrintProfile();
|
||||
for_each_dive (i, dive) {
|
||||
for (auto &dive: divelog.dives) {
|
||||
if (cb.canceled())
|
||||
return;
|
||||
if (selected_only && !dive->selected)
|
||||
|
@ -75,7 +73,7 @@ void exportProfile(QString filename, bool selected_only, ExportCallback &cb)
|
|||
cb.setProgress(done++ * 1000 / todo);
|
||||
QString fn = count ? fi.path() + QDir::separator() + fi.completeBaseName().append(QString("-%1.").arg(count)) + fi.suffix()
|
||||
: filename;
|
||||
exportProfile(profile.get(), dive, fn);
|
||||
exportProfile(*profile, *dive, fn);
|
||||
++count;
|
||||
}
|
||||
}
|
||||
|
@ -84,11 +82,9 @@ void export_TeX(const char *filename, bool selected_only, bool plain, ExportCall
|
|||
{
|
||||
FILE *f;
|
||||
QDir texdir = QFileInfo(filename).dir();
|
||||
struct dive *dive;
|
||||
const struct units *units = get_units();
|
||||
const char *unit;
|
||||
const char *ssrf;
|
||||
int i;
|
||||
bool need_pagebreak = false;
|
||||
|
||||
membuffer buf;
|
||||
|
@ -133,16 +129,16 @@ void export_TeX(const char *filename, bool selected_only, bool plain, ExportCall
|
|||
|
||||
put_format(&buf, "\n%%%%%%%%%% Begin Dive Data: %%%%%%%%%%\n");
|
||||
|
||||
int todo = selected_only ? amount_selected : divelog.dives->nr;
|
||||
int todo = selected_only ? amount_selected : static_cast<int>(divelog.dives.size());
|
||||
int done = 0;
|
||||
auto profile = getPrintProfile();
|
||||
for_each_dive (i, dive) {
|
||||
for (auto &dive: divelog.dives) {
|
||||
if (cb.canceled())
|
||||
return;
|
||||
if (selected_only && !dive->selected)
|
||||
continue;
|
||||
cb.setProgress(done++ * 1000 / todo);
|
||||
exportProfile(profile.get(), dive, texdir.filePath(QString("profile%1.png").arg(dive->number)));
|
||||
exportProfile(*profile, *dive, texdir.filePath(QString("profile%1.png").arg(dive->number)));
|
||||
struct tm tm;
|
||||
utc_mkdate(dive->when, &tm);
|
||||
|
||||
|
@ -150,7 +146,7 @@ void export_TeX(const char *filename, bool selected_only, bool plain, ExportCall
|
|||
dive_site *site = dive->dive_site;
|
||||
if (site)
|
||||
country = taxonomy_get_country(site->taxonomy);
|
||||
pressure_t delta_p = {.mbar = 0};
|
||||
pressure_t delta_p;
|
||||
|
||||
QString star = "*";
|
||||
QString viz = star.repeated(dive->visibility);
|
||||
|
@ -201,9 +197,8 @@ void export_TeX(const char *filename, bool selected_only, bool plain, ExportCall
|
|||
// Print cylinder data
|
||||
put_format(&buf, "\n%% Gas use information:\n");
|
||||
int qty_cyl = 0;
|
||||
for (int i = 0; i < static_cast<int>(dive->cylinders.size()); i++){
|
||||
const cylinder_t &cyl = dive->cylinders[i];
|
||||
if (is_cylinder_used(dive, i) || (prefs.include_unused_tanks && !cyl.type.description.empty())){
|
||||
for (auto [i, cyl]: enumerated_range(dive->cylinders)) {
|
||||
if (is_cylinder_used(dive.get(), i) || (prefs.include_unused_tanks && !cyl.type.description.empty())){
|
||||
put_format(&buf, "\\def\\%scyl%cdescription{%s}\n", ssrf, 'a' + i, cyl.type.description.c_str());
|
||||
put_format(&buf, "\\def\\%scyl%cgasname{%s}\n", ssrf, 'a' + i, gasname(cyl.gasmix));
|
||||
put_format(&buf, "\\def\\%scyl%cmixO2{%.1f\\%%}\n", ssrf, 'a' + i, get_o2(cyl.gasmix)/10.0);
|
||||
|
@ -270,13 +265,11 @@ void export_TeX(const char *filename, bool selected_only, bool plain, ExportCall
|
|||
void export_depths(const char *filename, bool selected_only)
|
||||
{
|
||||
FILE *f;
|
||||
struct dive *dive;
|
||||
int i;
|
||||
const char *unit = NULL;
|
||||
|
||||
membuffer buf;
|
||||
|
||||
for_each_dive (i, dive) {
|
||||
for (auto &dive: divelog.dives) {
|
||||
if (selected_only && !dive->selected)
|
||||
continue;
|
||||
|
||||
|
|
|
@ -66,7 +66,7 @@ QString diveNumberOrDate(struct dive *d)
|
|||
QString getListOfDives(const std::vector<struct dive*> &dives)
|
||||
{
|
||||
QString listOfDives;
|
||||
if ((int)dives.size() == divelog.dives->nr)
|
||||
if (dives.size() == divelog.dives.size())
|
||||
return Base::tr("all dives");
|
||||
int i = 0;
|
||||
for (dive *d: dives) {
|
||||
|
|
|
@ -44,13 +44,13 @@ DiveToAdd DiveListBase::removeDive(struct dive *d, std::vector<std::unique_ptr<d
|
|||
tripsToAdd.push_back(std::move(trip)); // Take ownership of trip
|
||||
}
|
||||
|
||||
int idx = get_divenr(d);
|
||||
if (idx < 0)
|
||||
size_t idx = divelog.dives.get_idx(d);
|
||||
if (idx == std::string::npos)
|
||||
qWarning("Deletion of unknown dive!");
|
||||
|
||||
DiveFilter::instance()->diveRemoved(d);
|
||||
|
||||
res.dive.reset(unregister_dive(idx)); // Remove dive from backend
|
||||
res.dive = divelog.dives.unregister_dive(idx); // Remove dive from backend
|
||||
|
||||
return res;
|
||||
}
|
||||
|
@ -88,7 +88,7 @@ void processByTrip(std::vector<std::pair<dive_trip *, dive *>> &dives, Function
|
|||
// Sort lexicographically by trip then according to the dive_less_than() function.
|
||||
std::sort(dives.begin(), dives.end(),
|
||||
[](const std::pair<dive_trip *, dive *> &e1, const std::pair<dive_trip *, dive *> &e2)
|
||||
{ return e1.first == e2.first ? dive_less_than(e1.second, e2.second) : e1.first < e2.first; });
|
||||
{ return e1.first == e2.first ? dive_less_than(*e1.second, *e2.second) : e1.first < e2.first; });
|
||||
|
||||
// Then, process the dives in batches by trip
|
||||
size_t i, j; // Begin and end of batch
|
||||
|
@ -124,7 +124,8 @@ DivesAndTripsToAdd DiveListBase::removeDives(DivesAndSitesToRemove &divesAndSite
|
|||
// Make sure that the dive list is sorted. The added dives will be sent in a signal
|
||||
// and the recipients assume that the dives are sorted the same way as they are
|
||||
// in the core list.
|
||||
std::sort(divesAndSitesToDelete.dives.begin(), divesAndSitesToDelete.dives.end(), dive_less_than);
|
||||
std::sort(divesAndSitesToDelete.dives.begin(), divesAndSitesToDelete.dives.end(),
|
||||
[](const dive *d1, const dive *d2) { return dive_less_than(*d1, *d2); });
|
||||
|
||||
for (dive *d: divesAndSitesToDelete.dives)
|
||||
divesToAdd.push_back(removeDive(d, tripsToAdd));
|
||||
|
@ -177,7 +178,7 @@ DivesAndSitesToRemove DiveListBase::addDives(DivesAndTripsToAdd &toAdd)
|
|||
// in the core list.
|
||||
std::sort(toAdd.dives.begin(), toAdd.dives.end(),
|
||||
[](const DiveToAdd &d, const DiveToAdd &d2)
|
||||
{ return dive_less_than(d.dive.get(), d2.dive.get()); });
|
||||
{ return dive_less_than(*d.dive, *d2.dive); });
|
||||
|
||||
// Now, add the dives
|
||||
// Note: the idiomatic STL-way would be std::transform, but let's use a loop since
|
||||
|
@ -411,12 +412,12 @@ AddDive::AddDive(dive *d, bool autogroup, bool newNumber)
|
|||
divePtr->divetrip = nullptr;
|
||||
divePtr->dive_site = nullptr;
|
||||
if (!trip && autogroup) {
|
||||
auto [t, allocated] = get_trip_for_new_dive(divePtr.get());
|
||||
auto [t, allocated] = get_trip_for_new_dive(divelog, divePtr.get());
|
||||
trip = t;
|
||||
allocTrip = std::move(allocated);
|
||||
}
|
||||
|
||||
int idx = dive_table_get_insertion_index(divelog.dives.get(), divePtr.get());
|
||||
int idx = divelog.dives.get_insertion_index(divePtr.get());
|
||||
if (newNumber)
|
||||
divePtr->number = get_dive_nr_at_idx(idx);
|
||||
|
||||
|
@ -455,18 +456,16 @@ void AddDive::undoit()
|
|||
|
||||
ImportDives::ImportDives(struct divelog *log, int flags, const QString &source)
|
||||
{
|
||||
setText(Command::Base::tr("import %n dive(s) from %1", "", log->dives->nr).arg(source));
|
||||
setText(Command::Base::tr("import %n dive(s) from %1", "", log->dives.size()).arg(source));
|
||||
|
||||
// this only matters if undoit were called before redoit
|
||||
currentDive = nullptr;
|
||||
|
||||
struct dive_table dives_to_add = empty_dive_table;
|
||||
struct dive_table dives_to_remove = empty_dive_table;
|
||||
struct trip_table trips_to_add;
|
||||
dive_site_table sites_to_add;
|
||||
process_imported_dives(log, flags,
|
||||
&dives_to_add, &dives_to_remove, trips_to_add,
|
||||
sites_to_add, devicesToAddAndRemove);
|
||||
auto [dives_to_add, dives_to_remove, trips_to_add, sites_to_add, devices_to_add] =
|
||||
process_imported_dives(*log, flags);
|
||||
|
||||
// Add devices to devicesToAddAndRemove structure
|
||||
devicesToAddAndRemove = std::move(devices_to_add);
|
||||
|
||||
// Add trips to the divesToAdd.trips structure
|
||||
divesToAdd.trips.reserve(trips_to_add.size());
|
||||
|
@ -477,9 +476,8 @@ ImportDives::ImportDives(struct divelog *log, int flags, const QString &source)
|
|||
divesToAdd.sites = std::move(sites_to_add);
|
||||
|
||||
// Add dives to the divesToAdd.dives structure
|
||||
divesToAdd.dives.reserve(dives_to_add.nr);
|
||||
for (int i = 0; i < dives_to_add.nr; ++i) {
|
||||
std::unique_ptr<dive> divePtr(dives_to_add.dives[i]);
|
||||
divesToAdd.dives.reserve(dives_to_add.size());
|
||||
for (auto &divePtr: dives_to_add) {
|
||||
divePtr->selected = false; // See above in AddDive::AddDive()
|
||||
dive_trip *trip = divePtr->divetrip;
|
||||
divePtr->divetrip = nullptr; // See above in AddDive::AddDive()
|
||||
|
@ -490,9 +488,7 @@ ImportDives::ImportDives(struct divelog *log, int flags, const QString &source)
|
|||
}
|
||||
|
||||
// Add dive to be deleted to the divesToRemove structure
|
||||
divesAndSitesToRemove.dives.reserve(dives_to_remove.nr);
|
||||
for (int i = 0; i < dives_to_remove.nr; ++i)
|
||||
divesAndSitesToRemove.dives.push_back(dives_to_remove.dives[i]);
|
||||
divesAndSitesToRemove.dives = std::move(dives_to_remove);
|
||||
|
||||
// When encountering filter presets with equal names, check whether they are
|
||||
// the same. If they are, ignore them.
|
||||
|
@ -504,9 +500,6 @@ ImportDives::ImportDives(struct divelog *log, int flags, const QString &source)
|
|||
continue;
|
||||
filterPresetsToAdd.emplace_back(preset.name, preset.data);
|
||||
}
|
||||
|
||||
free(dives_to_add.dives);
|
||||
free(dives_to_remove.dives);
|
||||
}
|
||||
|
||||
bool ImportDives::workToBeDone()
|
||||
|
@ -628,7 +621,7 @@ void ShiftTime::redoit()
|
|||
}
|
||||
|
||||
// Changing times may have unsorted the dive and trip tables
|
||||
sort_dive_table(divelog.dives.get());
|
||||
divelog.dives.sort();
|
||||
divelog.trips->sort();
|
||||
for (dive_trip *trip: trips)
|
||||
trip->sort_dives();
|
||||
|
@ -735,11 +728,9 @@ RemoveAutogenTrips::RemoveAutogenTrips()
|
|||
{
|
||||
setText(Command::Base::tr("remove autogenerated trips"));
|
||||
// TODO: don't touch core-innards directly
|
||||
int i;
|
||||
struct dive *dive;
|
||||
for_each_dive(i, dive) {
|
||||
if (dive->divetrip && dive->divetrip->autogen)
|
||||
divesToMove.divesToMove.push_back( {dive, nullptr} );
|
||||
for (auto &d: divelog.dives) {
|
||||
if (d->divetrip && d->divetrip->autogen)
|
||||
divesToMove.divesToMove.push_back( {d.get(), nullptr} );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -767,12 +758,12 @@ AutogroupDives::AutogroupDives()
|
|||
{
|
||||
setText(Command::Base::tr("autogroup dives"));
|
||||
|
||||
for (auto &entry: get_dives_to_autogroup(divelog.dives.get())) {
|
||||
for (auto &entry: get_dives_to_autogroup(divelog.dives)) {
|
||||
// If this is an allocated trip, take ownership
|
||||
if (entry.created_trip)
|
||||
divesToMove.tripsToAdd.push_back(std::move(entry.created_trip));
|
||||
for (int i = entry.from; i < entry.to; ++i)
|
||||
divesToMove.divesToMove.push_back( { divelog.dives->dives[i], entry.trip } );
|
||||
for (auto it = divelog.dives.begin() + entry.from; it != divelog.dives.begin() + entry.to; ++it)
|
||||
divesToMove.divesToMove.push_back( { it->get(), entry.trip } );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -960,9 +951,9 @@ MergeDives::MergeDives(const QVector <dive *> &dives)
|
|||
// We will only renumber the remaining dives if the joined dives are consecutive.
|
||||
// Otherwise all bets are off concerning what the user wanted and doing nothing seems
|
||||
// like the best option.
|
||||
int idx = get_divenr(dives[0]);
|
||||
int num = dives.count();
|
||||
if (idx < 0 || idx + num > divelog.dives->nr) {
|
||||
size_t idx = divelog.dives.get_idx(dives[0]);
|
||||
size_t num = dives.count();
|
||||
if (idx == std::string::npos) {
|
||||
// It was the callers responsibility to pass only known dives.
|
||||
// Something is seriously wrong - give up.
|
||||
qWarning("Merging unknown dives");
|
||||
|
@ -970,7 +961,8 @@ MergeDives::MergeDives(const QVector <dive *> &dives)
|
|||
}
|
||||
// std::equal compares two ranges. The parameters are (begin_range1, end_range1, begin_range2).
|
||||
// Here, we can compare C-arrays, because QVector guarantees contiguous storage.
|
||||
if (std::equal(&dives[0], &dives[0] + num, &divelog.dives->dives[idx]) &&
|
||||
if (std::equal(&dives[0], &dives[0] + num, divelog.dives.begin() + idx, [](dive *d1,
|
||||
const std::unique_ptr<dive> &d2) { return d1 == d2.get(); }) &&
|
||||
dives[0]->number && dives.last()->number && dives[0]->number < dives.last()->number) {
|
||||
// We have a consecutive set of dives. Rename all following dives according to the
|
||||
// number of erased dives. This considers that there might be missing numbers.
|
||||
|
@ -986,15 +978,14 @@ MergeDives::MergeDives(const QVector <dive *> &dives)
|
|||
// consecutive, and the difference will be 1, so the
|
||||
// above example is not supposed to be normal.
|
||||
int diff = dives.last()->number - dives[0]->number;
|
||||
divesToRenumber.reserve(divelog.dives->nr - idx - num);
|
||||
int previousnr = dives[0]->number;
|
||||
for (int i = idx + num; i < divelog.dives->nr; ++i) {
|
||||
int newnr = divelog.dives->dives[i]->number - diff;
|
||||
for (size_t i = idx + num; i < divelog.dives.size(); ++i) {
|
||||
int newnr = divelog.dives[i]->number - diff;
|
||||
|
||||
// Stop renumbering if stuff isn't in order (see also core/divelist.c)
|
||||
if (newnr <= previousnr)
|
||||
break;
|
||||
divesToRenumber.append(QPair<dive *,int>(divelog.dives->dives[i], newnr));
|
||||
divesToRenumber.append(QPair<dive *,int>(divelog.dives[i].get(), newnr));
|
||||
previousnr = newnr;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -62,11 +62,9 @@ static std::vector<dive *> getDives(bool currentDiveOnly)
|
|||
: std::vector<dive *> { };
|
||||
|
||||
std::vector<dive *> res;
|
||||
struct dive *d;
|
||||
int i;
|
||||
for_each_dive (i, d) {
|
||||
for (auto &d: divelog.dives) {
|
||||
if (d->selected)
|
||||
res.push_back(d);
|
||||
res.push_back(d.get());
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
@ -1443,7 +1441,7 @@ void EditDive::exchangeDives()
|
|||
QVector<dive *> dives = { oldDive };
|
||||
timestamp_t delta = oldDive->when - newDive->when;
|
||||
if (delta != 0) {
|
||||
sort_dive_table(divelog.dives.get());
|
||||
divelog.dives.sort();
|
||||
divelog.trips->sort();
|
||||
if (newDive->divetrip != oldDive->divetrip)
|
||||
qWarning("Command::EditDive::redo(): This command does not support moving between trips!");
|
||||
|
|
|
@ -74,6 +74,7 @@ set(SUBSURFACE_CORE_LIB_SRCS
|
|||
divelogexportlogic.h
|
||||
divesite.cpp
|
||||
divesite.h
|
||||
divesitetable.h
|
||||
divesitehelpers.cpp
|
||||
divesitehelpers.h
|
||||
downloadfromdcthread.cpp
|
||||
|
@ -179,6 +180,7 @@ set(SUBSURFACE_CORE_LIB_SRCS
|
|||
time.cpp
|
||||
trip.cpp
|
||||
trip.h
|
||||
triptable.h
|
||||
uemis-downloader.cpp
|
||||
uemis.cpp
|
||||
uemis.h
|
||||
|
|
|
@ -601,7 +601,7 @@ static void cochran_parse_samples(struct dive *dive, const unsigned char *log,
|
|||
|
||||
static void cochran_parse_dive(const unsigned char *decode, unsigned mod,
|
||||
const unsigned char *in, unsigned size,
|
||||
struct dive_table *table)
|
||||
struct dive_table &table)
|
||||
{
|
||||
unsigned char *buf = (unsigned char *)malloc(size);
|
||||
struct divecomputer *dc;
|
||||
|
@ -784,7 +784,7 @@ static void cochran_parse_dive(const unsigned char *decode, unsigned mod,
|
|||
dc->duration.seconds = duration;
|
||||
}
|
||||
|
||||
record_dive_to_table(dive.release(), table);
|
||||
table.record_dive(std::move(dive));
|
||||
|
||||
free(buf);
|
||||
}
|
||||
|
@ -819,7 +819,7 @@ int try_to_open_cochran(const char *, std::string &mem, struct divelog *log)
|
|||
break;
|
||||
|
||||
cochran_parse_dive(decode, mod, (unsigned char *)mem.data() + dive1,
|
||||
dive2 - dive1, log->dives.get());
|
||||
dive2 - dive1, log->dives);
|
||||
}
|
||||
|
||||
return 1; // no further processing needed
|
||||
|
|
|
@ -698,12 +698,12 @@ int datatrak_import(std::string &mem, std::string &wl_mem, struct divelog *log)
|
|||
rc = 1;
|
||||
goto out;
|
||||
} else {
|
||||
record_dive_to_table(ptdive.release(), log->dives.get());
|
||||
log->dives.record_dive(std::move(ptdive));
|
||||
}
|
||||
i++;
|
||||
}
|
||||
out:
|
||||
sort_dive_table(log->dives.get());
|
||||
log->dives.sort();
|
||||
return rc;
|
||||
bail:
|
||||
return 1;
|
||||
|
|
|
@ -2376,10 +2376,10 @@ static void force_fixup_dive(struct dive *d)
|
|||
*/
|
||||
static std::array<std::unique_ptr<dive>, 2> split_dive_at(const struct dive &dive, int a, int b)
|
||||
{
|
||||
int nr = get_divenr(&dive);
|
||||
size_t nr = divelog.dives.get_idx(&dive);
|
||||
|
||||
/* if we can't find the dive in the dive list, don't bother */
|
||||
if (nr < 0)
|
||||
if (nr == std::string::npos)
|
||||
return {};
|
||||
|
||||
/* Splitting should leave at least 3 samples per dive */
|
||||
|
@ -2461,7 +2461,7 @@ static std::array<std::unique_ptr<dive>, 2> split_dive_at(const struct dive &div
|
|||
* Otherwise the tail is unnumbered.
|
||||
*/
|
||||
if (d2->number) {
|
||||
if (divelog.dives->nr == nr + 1)
|
||||
if (divelog.dives.size() == nr + 1)
|
||||
d2->number++;
|
||||
else
|
||||
d2->number = 0;
|
||||
|
@ -2893,9 +2893,9 @@ depth_t gas_mnd(struct gasmix mix, depth_t end, const struct dive *dive, int rou
|
|||
|
||||
struct dive *get_dive(int nr)
|
||||
{
|
||||
if (nr >= divelog.dives->nr || nr < 0)
|
||||
return NULL;
|
||||
return divelog.dives->dives[nr];
|
||||
if (nr < 0 || static_cast<size_t>(nr) >= divelog.dives.size())
|
||||
return nullptr;
|
||||
return divelog.dives[nr].get();
|
||||
}
|
||||
|
||||
struct dive_site *get_dive_site_for_dive(const struct dive *dive)
|
||||
|
@ -2933,42 +2933,6 @@ const struct divecomputer *get_dive_dc(const struct dive *dive, int nr)
|
|||
return get_dive_dc((struct dive *)dive, nr);
|
||||
}
|
||||
|
||||
struct dive *get_dive_by_uniq_id(int id)
|
||||
{
|
||||
int i;
|
||||
struct dive *dive = NULL;
|
||||
|
||||
for_each_dive (i, dive) {
|
||||
if (dive->id == id)
|
||||
break;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
if (dive == NULL) {
|
||||
report_info("Invalid id %x passed to get_dive_by_diveid, try to fix the code", id);
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
return dive;
|
||||
}
|
||||
|
||||
int get_idx_by_uniq_id(int id)
|
||||
{
|
||||
int i;
|
||||
struct dive *dive = NULL;
|
||||
|
||||
for_each_dive (i, dive) {
|
||||
if (dive->id == id)
|
||||
break;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
if (dive == NULL) {
|
||||
report_info("Invalid id %x passed to get_dive_by_diveid, try to fix the code", id);
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
return i;
|
||||
}
|
||||
|
||||
bool dive_site_has_gps_location(const struct dive_site *ds)
|
||||
{
|
||||
return ds && has_location(&ds->location);
|
||||
|
|
21
core/dive.h
21
core/dive.h
|
@ -139,7 +139,6 @@ extern depth_t gas_mod(struct gasmix mix, pressure_t po2_limit, const struct div
|
|||
extern depth_t gas_mnd(struct gasmix mix, depth_t end, const struct dive *dive, int roundto);
|
||||
|
||||
extern struct dive *get_dive(int nr);
|
||||
extern struct dive *get_dive_from_table(int nr, const struct dive_table *dt);
|
||||
extern struct dive_site *get_dive_site_for_dive(const struct dive *dive);
|
||||
extern std::string get_dive_country(const struct dive *dive);
|
||||
extern std::string get_dive_location(const struct dive *dive);
|
||||
|
@ -153,18 +152,6 @@ extern std::unique_ptr<dive> clone_make_first_dc(const struct dive &d, int dc_nu
|
|||
extern std::unique_ptr<dive> clone_delete_divecomputer(const struct dive &d, int dc_number);
|
||||
extern std::array<std::unique_ptr<dive>, 2> split_divecomputer(const struct dive &src, int num);
|
||||
|
||||
/*
|
||||
* Iterate over each dive, with the first parameter being the index
|
||||
* iterator variable, and the second one being the dive one.
|
||||
*
|
||||
* I don't think anybody really wants the index, and we could make
|
||||
* it local to the for-loop, but that would make us requires C99.
|
||||
*/
|
||||
#define for_each_dive(_i, _x) \
|
||||
for ((_i) = 0; ((_x) = get_dive(_i)) != NULL; (_i)++)
|
||||
|
||||
extern struct dive *get_dive_by_uniq_id(int id);
|
||||
extern int get_idx_by_uniq_id(int id);
|
||||
extern bool dive_site_has_gps_location(const struct dive_site *ds);
|
||||
extern int dive_has_gps_location(const struct dive *dive);
|
||||
extern location_t dive_get_gps_location(const struct dive *d);
|
||||
|
@ -173,19 +160,18 @@ extern bool time_during_dive_with_offset(const struct dive *dive, timestamp_t wh
|
|||
|
||||
extern int save_dives(const char *filename);
|
||||
extern int save_dives_logic(const char *filename, bool select_only, bool anonymize);
|
||||
extern int save_dive(FILE *f, struct dive *dive, bool anonymize);
|
||||
extern int save_dive(FILE *f, const struct dive &dive, bool anonymize);
|
||||
extern int export_dives_xslt(const char *filename, bool selected, const int units, const char *export_xslt, bool anonymize);
|
||||
|
||||
extern int save_dive_sites_logic(const char *filename, const struct dive_site *sites[], int nr_sites, bool anonymize);
|
||||
|
||||
struct membuffer;
|
||||
extern void save_one_dive_to_mb(struct membuffer *b, struct dive *dive, bool anonymize);
|
||||
extern void save_one_dive_to_mb(struct membuffer *b, const struct dive &dive, bool anonymize);
|
||||
|
||||
extern void subsurface_console_init();
|
||||
extern void subsurface_console_exit();
|
||||
extern bool subsurface_user_is_root();
|
||||
|
||||
extern void record_dive_to_table(struct dive *dive, struct dive_table *table);
|
||||
extern void clear_dive(struct dive *dive);
|
||||
extern void copy_dive(const struct dive *s, struct dive *d);
|
||||
extern void selective_copy_dive(const struct dive *s, struct dive *d, struct dive_components what, bool clear);
|
||||
|
@ -193,7 +179,8 @@ extern struct std::unique_ptr<dive> move_dive(struct dive *s);
|
|||
|
||||
extern int legacy_format_o2pressures(const struct dive *dive, const struct divecomputer *dc);
|
||||
|
||||
extern bool dive_less_than(const struct dive *a, const struct dive *b);
|
||||
extern bool dive_less_than(const struct dive &a, const struct dive &b);
|
||||
extern bool dive_less_than_ptr(const struct dive *a, const struct dive *b);
|
||||
extern bool dive_or_trip_less_than(struct dive_or_trip a, struct dive_or_trip b);
|
||||
extern struct dive *fixup_dive(struct dive *dive);
|
||||
extern pressure_t calculate_surface_pressure(const struct dive *dive);
|
||||
|
|
|
@ -74,10 +74,8 @@ ShownChange DiveFilter::update(const QVector<dive *> &dives) const
|
|||
|
||||
void DiveFilter::reset()
|
||||
{
|
||||
int i;
|
||||
dive *d;
|
||||
shown_dives = divelog.dives->nr;
|
||||
for_each_dive(i, d)
|
||||
shown_dives = static_cast<int>(divelog.dives.size());
|
||||
for (auto &d: divelog.dives)
|
||||
d->hidden_by_filter = false;
|
||||
updateAll();
|
||||
}
|
||||
|
@ -85,26 +83,24 @@ void DiveFilter::reset()
|
|||
ShownChange DiveFilter::updateAll() const
|
||||
{
|
||||
ShownChange res;
|
||||
int i;
|
||||
dive *d;
|
||||
std::vector<dive *> selection = getDiveSelection();
|
||||
std::vector<dive *> removeFromSelection;
|
||||
// There are three modes: divesite, fulltext, normal
|
||||
if (diveSiteMode()) {
|
||||
for_each_dive(i, d) {
|
||||
for (auto &d: divelog.dives) {
|
||||
bool newStatus = range_contains(dive_sites, d->dive_site);
|
||||
updateDiveStatus(d, newStatus, res, removeFromSelection);
|
||||
updateDiveStatus(d.get(), newStatus, res, removeFromSelection);
|
||||
}
|
||||
} else if (filterData.fullText.doit()) {
|
||||
FullTextResult ft = fulltext_find_dives(filterData.fullText, filterData.fulltextStringMode);
|
||||
for_each_dive(i, d) {
|
||||
bool newStatus = ft.dive_matches(d) && showDive(d);
|
||||
updateDiveStatus(d, newStatus, res, removeFromSelection);
|
||||
for (auto &d: divelog.dives) {
|
||||
bool newStatus = ft.dive_matches(d.get()) && showDive(d.get());
|
||||
updateDiveStatus(d.get(), newStatus, res, removeFromSelection);
|
||||
}
|
||||
} else {
|
||||
for_each_dive(i, d) {
|
||||
bool newStatus = showDive(d);
|
||||
updateDiveStatus(d, newStatus, res, removeFromSelection);
|
||||
for (auto &d: divelog.dives) {
|
||||
bool newStatus = showDive(d.get());
|
||||
updateDiveStatus(d.get(), newStatus, res, removeFromSelection);
|
||||
}
|
||||
}
|
||||
updateSelection(selection, std::vector<dive *>(), removeFromSelection);
|
||||
|
@ -204,7 +200,7 @@ bool DiveFilter::diveSiteMode() const
|
|||
|
||||
QString DiveFilter::shownText() const
|
||||
{
|
||||
int num = divelog.dives->nr;
|
||||
size_t num = divelog.dives.size();
|
||||
if (diveSiteMode() || filterData.validFilter())
|
||||
return gettextFromC::tr("%L1/%L2 shown").arg(shown_dives).arg(num);
|
||||
else
|
||||
|
@ -230,11 +226,9 @@ std::vector<dive *> DiveFilter::visibleDives() const
|
|||
std::vector<dive *> res;
|
||||
res.reserve(shown_dives);
|
||||
|
||||
int i;
|
||||
dive *d;
|
||||
for_each_dive(i, d) {
|
||||
for (auto &d: divelog.dives) {
|
||||
if (!d->hidden_by_filter)
|
||||
res.push_back(d);
|
||||
res.push_back(d.get());
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
|
|
@ -20,9 +20,14 @@
|
|||
#include "git-access.h"
|
||||
#include "selection.h"
|
||||
#include "sample.h"
|
||||
#include "table.h"
|
||||
#include "trip.h"
|
||||
|
||||
void dive_table::record_dive(std::unique_ptr<dive> d)
|
||||
{
|
||||
fixup_dive(d.get());
|
||||
put(std::move(d));
|
||||
}
|
||||
|
||||
/*
|
||||
* Get "maximal" dive gas for a dive.
|
||||
* Rules:
|
||||
|
@ -201,7 +206,6 @@ static double calculate_cns_dive(const struct dive *dive)
|
|||
* so we calculated it "by hand" */
|
||||
static int calculate_cns(struct dive *dive)
|
||||
{
|
||||
int i, divenr;
|
||||
double cns = 0.0;
|
||||
timestamp_t last_starttime, last_endtime = 0;
|
||||
|
||||
|
@ -209,16 +213,18 @@ static int calculate_cns(struct dive *dive)
|
|||
if (dive->cns)
|
||||
return dive->cns;
|
||||
|
||||
divenr = get_divenr(dive);
|
||||
i = divenr >= 0 ? divenr : divelog.dives->nr;
|
||||
size_t divenr = divelog.dives.get_idx(dive);
|
||||
int i = divenr != std::string::npos ? static_cast<int>(divenr)
|
||||
: static_cast<int>(divelog.dives.size());
|
||||
int nr_dives = static_cast<int>(divelog.dives.size());
|
||||
#if DECO_CALC_DEBUG & 2
|
||||
if (i >= 0 && i < dive_table.nr)
|
||||
printf("\n\n*** CNS for dive #%d %d\n", i, get_dive(i)->number);
|
||||
if (static_cast<size_t>(i) < divelog.table->size())
|
||||
printf("\n\n*** CNS for dive #%d %d\n", i, (*divelog.table)[i]->number);
|
||||
else
|
||||
printf("\n\n*** CNS for dive #%d\n", i);
|
||||
#endif
|
||||
/* Look at next dive in dive list table and correct i when needed */
|
||||
while (i < divelog.dives->nr - 1) {
|
||||
while (i < nr_dives - 1) {
|
||||
struct dive *pdive = get_dive(i);
|
||||
if (!pdive || pdive->when > dive->when)
|
||||
break;
|
||||
|
@ -237,7 +243,7 @@ static int calculate_cns(struct dive *dive)
|
|||
last_starttime = dive->when;
|
||||
/* Walk backwards to check previous dives - how far do we need to go back? */
|
||||
while (i--) {
|
||||
if (i == divenr && i > 0)
|
||||
if (static_cast<size_t>(i) == divenr && i > 0)
|
||||
i--;
|
||||
#if DECO_CALC_DEBUG & 2
|
||||
printf("Check if dive #%d %d has to be considered as prev dive: ", i, get_dive(i)->number);
|
||||
|
@ -263,7 +269,7 @@ static int calculate_cns(struct dive *dive)
|
|||
#endif
|
||||
}
|
||||
/* Walk forward and add dives and surface intervals to CNS */
|
||||
while (++i < divelog.dives->nr) {
|
||||
while (++i < nr_dives) {
|
||||
#if DECO_CALC_DEBUG & 2
|
||||
printf("Check if dive #%d %d will be really added to CNS calc: ", i, get_dive(i)->number);
|
||||
#endif
|
||||
|
@ -283,7 +289,7 @@ static int calculate_cns(struct dive *dive)
|
|||
break;
|
||||
}
|
||||
/* Don't add the copy of the dive itself */
|
||||
if (i == divenr) {
|
||||
if (static_cast<size_t>(i) == divenr) {
|
||||
#if DECO_CALC_DEBUG & 2
|
||||
printf("No - copy of dive\n");
|
||||
#endif
|
||||
|
@ -406,20 +412,6 @@ static void add_dive_to_deco(struct deco_state *ds, struct dive *dive, bool in_p
|
|||
}
|
||||
}
|
||||
|
||||
int get_divenr(const struct dive *dive)
|
||||
{
|
||||
int i;
|
||||
const struct dive *d;
|
||||
// tempting as it may be, don't die when called with dive=NULL
|
||||
if (dive) {
|
||||
for_each_dive(i, d) {
|
||||
if (d->id == dive->id) // don't compare pointers, we could be passing in a copy of the dive
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* take into account previous dives until there is a 48h gap between dives */
|
||||
/* return last surface time before this dive or dummy value of 48h */
|
||||
/* return negative surface time if dives are overlapping */
|
||||
|
@ -427,7 +419,6 @@ int get_divenr(const struct dive *dive)
|
|||
* to create the deco_state */
|
||||
int init_decompression(struct deco_state *ds, const struct dive *dive, bool in_planner)
|
||||
{
|
||||
int i, divenr = -1;
|
||||
int surface_time = 48 * 60 * 60;
|
||||
timestamp_t last_endtime = 0, last_starttime = 0;
|
||||
bool deco_init = false;
|
||||
|
@ -436,16 +427,18 @@ int init_decompression(struct deco_state *ds, const struct dive *dive, bool in_p
|
|||
if (!dive)
|
||||
return false;
|
||||
|
||||
divenr = get_divenr(dive);
|
||||
i = divenr >= 0 ? divenr : divelog.dives->nr;
|
||||
int nr_dives = static_cast<int>(divelog.dives.size());
|
||||
size_t divenr = divelog.dives.get_idx(dive);
|
||||
int i = divenr != std::string::npos ? static_cast<int>(divenr)
|
||||
: static_cast<int>(divelog.dives.size());
|
||||
#if DECO_CALC_DEBUG & 2
|
||||
if (i >= 0 && i < dive_table.nr)
|
||||
if (i < dive_table.nr)
|
||||
printf("\n\n*** Init deco for dive #%d %d\n", i, get_dive(i)->number);
|
||||
else
|
||||
printf("\n\n*** Init deco for dive #%d\n", i);
|
||||
#endif
|
||||
/* Look at next dive in dive list table and correct i when needed */
|
||||
while (i < divelog.dives->nr - 1) {
|
||||
while (i + 1 < nr_dives) {
|
||||
struct dive *pdive = get_dive(i);
|
||||
if (!pdive || pdive->when > dive->when)
|
||||
break;
|
||||
|
@ -464,7 +457,7 @@ int init_decompression(struct deco_state *ds, const struct dive *dive, bool in_p
|
|||
last_starttime = dive->when;
|
||||
/* Walk backwards to check previous dives - how far do we need to go back? */
|
||||
while (i--) {
|
||||
if (i == divenr && i > 0)
|
||||
if (static_cast<size_t>(i) == divenr && i > 0)
|
||||
i--;
|
||||
#if DECO_CALC_DEBUG & 2
|
||||
printf("Check if dive #%d %d has to be considered as prev dive: ", i, get_dive(i)->number);
|
||||
|
@ -490,7 +483,7 @@ int init_decompression(struct deco_state *ds, const struct dive *dive, bool in_p
|
|||
#endif
|
||||
}
|
||||
/* Walk forward an add dives and surface intervals to deco */
|
||||
while (++i < divelog.dives->nr) {
|
||||
while (++i < nr_dives) {
|
||||
#if DECO_CALC_DEBUG & 2
|
||||
printf("Check if dive #%d %d will be really added to deco calc: ", i, get_dive(i)->number);
|
||||
#endif
|
||||
|
@ -510,7 +503,7 @@ int init_decompression(struct deco_state *ds, const struct dive *dive, bool in_p
|
|||
break;
|
||||
}
|
||||
/* Don't add the copy of the dive itself */
|
||||
if (i == divenr) {
|
||||
if (static_cast<size_t>(i) == divenr) {
|
||||
#if DECO_CALC_DEBUG & 2
|
||||
printf("No - copy of dive\n");
|
||||
#endif
|
||||
|
@ -635,71 +628,55 @@ static int comp_dc(const struct dive *d1, const struct dive *d2)
|
|||
* We might also consider sorting by end-time and other criteria,
|
||||
* but see the caveat above (editing means reordering of the dives).
|
||||
*/
|
||||
int comp_dives(const struct dive *a, const struct dive *b)
|
||||
int comp_dives(const struct dive &a, const struct dive &b)
|
||||
{
|
||||
int cmp;
|
||||
if (a == b)
|
||||
if (&a == &b)
|
||||
return 0; /* reflexivity */
|
||||
if (a->when < b->when)
|
||||
if (a.when < b.when)
|
||||
return -1;
|
||||
if (a->when > b->when)
|
||||
if (a.when > b.when)
|
||||
return 1;
|
||||
if (a->divetrip != b->divetrip) {
|
||||
if (!b->divetrip)
|
||||
if (a.divetrip != b.divetrip) {
|
||||
if (!b.divetrip)
|
||||
return -1;
|
||||
if (!a->divetrip)
|
||||
if (!a.divetrip)
|
||||
return 1;
|
||||
if (trip_date(*a->divetrip) < trip_date(*b->divetrip))
|
||||
if (trip_date(*a.divetrip) < trip_date(*b.divetrip))
|
||||
return -1;
|
||||
if (trip_date(*a->divetrip) > trip_date(*b->divetrip))
|
||||
if (trip_date(*a.divetrip) > trip_date(*b.divetrip))
|
||||
return 1;
|
||||
}
|
||||
if (a->number < b->number)
|
||||
if (a.number < b.number)
|
||||
return -1;
|
||||
if (a->number > b->number)
|
||||
if (a.number > b.number)
|
||||
return 1;
|
||||
if ((cmp = comp_dc(a, b)) != 0)
|
||||
if ((cmp = comp_dc(&a, &b)) != 0)
|
||||
return cmp;
|
||||
if (a->id < b->id)
|
||||
if (a.id < b.id)
|
||||
return -1;
|
||||
if (a->id > b->id)
|
||||
if (a.id > b.id)
|
||||
return 1;
|
||||
return a < b ? -1 : 1; /* give up. */
|
||||
return &a < &b ? -1 : 1; /* give up. */
|
||||
}
|
||||
|
||||
/* Dive table functions */
|
||||
static void free_dive(dive *d)
|
||||
int comp_dives_ptr(const struct dive *a, const struct dive *b)
|
||||
{
|
||||
delete d;
|
||||
}
|
||||
static MAKE_GROW_TABLE(dive_table, struct dive *, dives)
|
||||
MAKE_GET_INSERTION_INDEX(dive_table, struct dive *, dives, dive_less_than)
|
||||
MAKE_ADD_TO(dive_table, struct dive *, dives)
|
||||
static MAKE_REMOVE_FROM(dive_table, dives)
|
||||
static MAKE_GET_IDX(dive_table, struct dive *, dives)
|
||||
MAKE_SORT(dive_table, struct dive *, dives, comp_dives)
|
||||
MAKE_REMOVE(dive_table, struct dive *, dive)
|
||||
MAKE_CLEAR_TABLE(dive_table, dives, dive)
|
||||
MAKE_MOVE_TABLE(dive_table, dives)
|
||||
|
||||
void insert_dive(struct dive_table *table, struct dive *d)
|
||||
{
|
||||
int idx = dive_table_get_insertion_index(table, d);
|
||||
add_to_dive_table(table, idx, d);
|
||||
return comp_dives(*a, *b);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
static void autogroup_dives(struct dive_table *table, struct trip_table &trip_table)
|
||||
static void autogroup_dives(struct dive_table &table, struct trip_table &trip_table)
|
||||
{
|
||||
if (!divelog.autogroup)
|
||||
return;
|
||||
|
||||
for (auto &entry: get_dives_to_autogroup(table)) {
|
||||
for (int i = entry.from; i < entry.to; ++i)
|
||||
add_dive_to_trip(table->dives[i], entry.trip);
|
||||
for (auto it = table.begin() + entry.from; it != table.begin() + entry.to; ++it)
|
||||
add_dive_to_trip(it->get(), entry.trip);
|
||||
/* If this was newly allocated, add trip to list */
|
||||
if (entry.created_trip)
|
||||
trip_table.put(std::move(entry.created_trip));
|
||||
|
@ -710,35 +687,20 @@ static void autogroup_dives(struct dive_table *table, struct trip_table &trip_ta
|
|||
#endif
|
||||
}
|
||||
|
||||
/* Remove a dive from a dive table. This assumes that the
|
||||
* dive was already removed from any trip and deselected.
|
||||
* It simply shrinks the table and frees the trip */
|
||||
void delete_dive_from_table(struct dive_table *table, int idx)
|
||||
{
|
||||
delete table->dives[idx];
|
||||
remove_from_dive_table(table, idx);
|
||||
}
|
||||
|
||||
struct dive *get_dive_from_table(int nr, const struct dive_table *dt)
|
||||
{
|
||||
if (nr >= dt->nr || nr < 0)
|
||||
return NULL;
|
||||
return dt->dives[nr];
|
||||
}
|
||||
|
||||
/* This removes a dive from the global dive table but doesn't free the
|
||||
* resources associated with the dive. The caller must removed the dive
|
||||
* from the trip-list. Returns a pointer to the unregistered dive.
|
||||
* The unregistered dive has the selection- and hidden-flags cleared. */
|
||||
struct dive *unregister_dive(int idx)
|
||||
std::unique_ptr<dive> dive_table::unregister_dive(int idx)
|
||||
{
|
||||
struct dive *dive = get_dive(idx);
|
||||
if (!dive)
|
||||
return NULL; /* this should never happen */
|
||||
if (idx < 0 || static_cast<size_t>(idx) >= size())
|
||||
return {}; /* this should never happen */
|
||||
|
||||
auto dive = pull_at(idx);
|
||||
|
||||
/* When removing a dive from the global dive table,
|
||||
* we also have to unregister its fulltext cache. */
|
||||
fulltext_unregister(dive);
|
||||
remove_from_dive_table(divelog.dives.get(), idx);
|
||||
fulltext_unregister(dive.get());
|
||||
if (dive->selected)
|
||||
amount_selected--;
|
||||
dive->selected = false;
|
||||
|
@ -755,21 +717,20 @@ struct dive *register_dive(std::unique_ptr<dive> d)
|
|||
// dives have been added, their status will be updated.
|
||||
d->hidden_by_filter = true;
|
||||
|
||||
int idx = dive_table_get_insertion_index(divelog.dives.get(), d.get());
|
||||
fulltext_register(d.get()); // Register the dive's fulltext cache
|
||||
invalidate_dive_cache(d.get()); // Ensure that dive is written in git_save()
|
||||
add_to_dive_table(divelog.dives.get(), idx, d.get());
|
||||
auto [res, idx] = divelog.dives.put(std::move(d));
|
||||
|
||||
return d.release();
|
||||
return res;
|
||||
}
|
||||
|
||||
void process_loaded_dives()
|
||||
{
|
||||
sort_dive_table(divelog.dives.get());
|
||||
divelog.dives.sort();
|
||||
divelog.trips->sort();
|
||||
|
||||
/* Autogroup dives if desired by user. */
|
||||
autogroup_dives(divelog.dives.get(), *divelog.trips);
|
||||
autogroup_dives(divelog.dives, *divelog.trips);
|
||||
|
||||
fulltext_populate();
|
||||
|
||||
|
@ -785,13 +746,11 @@ void process_loaded_dives()
|
|||
* that the dives are neither selected, not part of a trip, as
|
||||
* is the case of freshly imported dives.
|
||||
*/
|
||||
static void merge_imported_dives(struct dive_table *table)
|
||||
static void merge_imported_dives(struct dive_table &table)
|
||||
{
|
||||
int i;
|
||||
for (i = 1; i < table->nr; i++) {
|
||||
struct dive *prev = table->dives[i - 1];
|
||||
struct dive *dive = table->dives[i];
|
||||
struct dive_site *ds;
|
||||
for (size_t i = 1; i < table.size(); i++) {
|
||||
auto &prev = table[i - 1];
|
||||
auto &dive = table[i];
|
||||
|
||||
/* only try to merge overlapping dives - or if one of the dives has
|
||||
* zero duration (that might be a gps marker from the webservice) */
|
||||
|
@ -804,20 +763,19 @@ static void merge_imported_dives(struct dive_table *table)
|
|||
continue;
|
||||
|
||||
/* Add dive to dive site; try_to_merge() does not do that! */
|
||||
ds = merged->dive_site;
|
||||
struct dive_site *ds = merged->dive_site;
|
||||
if (ds) {
|
||||
merged->dive_site = NULL;
|
||||
ds->add_dive(merged.get());
|
||||
}
|
||||
unregister_dive_from_dive_site(prev);
|
||||
unregister_dive_from_dive_site(dive);
|
||||
unregister_dive_from_trip(prev);
|
||||
unregister_dive_from_trip(dive);
|
||||
unregister_dive_from_dive_site(prev.get());
|
||||
unregister_dive_from_dive_site(dive.get());
|
||||
unregister_dive_from_trip(prev.get());
|
||||
unregister_dive_from_trip(dive.get());
|
||||
|
||||
/* Overwrite the first of the two dives and remove the second */
|
||||
delete prev;
|
||||
table->dives[i - 1] = merged.release();
|
||||
delete_dive_from_table(table, i);
|
||||
table[i - 1] = std::move(merged);
|
||||
table.erase(table.begin() + i);
|
||||
|
||||
/* Redo the new 'i'th dive */
|
||||
i--;
|
||||
|
@ -831,45 +789,46 @@ static void merge_imported_dives(struct dive_table *table)
|
|||
* table. On failure everything stays unchanged.
|
||||
* If "prefer_imported" is true, use data of the new dive.
|
||||
*/
|
||||
static bool try_to_merge_into(struct dive &dive_to_add, struct dive &old_dive, bool prefer_imported,
|
||||
static bool try_to_merge_into(struct dive &dive_to_add, struct dive *old_dive, bool prefer_imported,
|
||||
/* output parameters: */
|
||||
struct dive_table *dives_to_add, struct dive_table *dives_to_remove)
|
||||
struct dive_table &dives_to_add, struct std::vector<dive *> &dives_to_remove)
|
||||
{
|
||||
auto merged = try_to_merge(old_dive, dive_to_add, prefer_imported);
|
||||
auto merged = try_to_merge(*old_dive, dive_to_add, prefer_imported);
|
||||
if (!merged)
|
||||
return false;
|
||||
|
||||
merged->divetrip = old_dive.divetrip;
|
||||
insert_dive(dives_to_remove, &old_dive);
|
||||
insert_dive(dives_to_add, merged.release());
|
||||
merged->divetrip = old_dive->divetrip;
|
||||
range_insert_sorted(dives_to_remove, old_dive, comp_dives_ptr);
|
||||
dives_to_add.put(std::move(merged));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Check if a dive is ranked after the last dive of the global dive list */
|
||||
static bool dive_is_after_last(struct dive *d)
|
||||
static bool dive_is_after_last(const struct dive &d)
|
||||
{
|
||||
if (divelog.dives->nr == 0)
|
||||
if (divelog.dives.empty())
|
||||
return true;
|
||||
return dive_less_than(divelog.dives->dives[divelog.dives->nr - 1], d);
|
||||
return dive_less_than(*divelog.dives.back(), d);
|
||||
}
|
||||
|
||||
/* Merge dives from "dives_from" into "dives_to". Overlapping dives will be merged,
|
||||
* non-overlapping dives will be moved. The results will be added to the "dives_to_add"
|
||||
* table. Dives that were merged are added to the "dives_to_remove" table.
|
||||
* Any newly added (not merged) dive will be assigned to the trip of the "trip"
|
||||
* paremeter. If "delete_from" is non-null dives will be removed from this table.
|
||||
/* Merge dives from "dives_from", owned by "delete" into the owned by "dives_to".
|
||||
* Overlapping dives will be merged, non-overlapping dives will be moved. The results
|
||||
* will be added to the "dives_to_add" table. Dives that were merged are added to
|
||||
* the "dives_to_remove" table. Any newly added (not merged) dive will be assigned
|
||||
* to the trip of the "trip" paremeter. If "delete_from" is non-null dives will be
|
||||
* removed from this table.
|
||||
* This function supposes that all input tables are sorted.
|
||||
* Returns true if any dive was added (not merged) that is not past the
|
||||
* last dive of the global dive list (i.e. the sequence will change).
|
||||
* The integer pointed to by "num_merged" will be increased for every
|
||||
* The integer referenced by "num_merged" will be increased for every
|
||||
* merged dive that is added to "dives_to_add" */
|
||||
static bool merge_dive_tables(const std::vector<dive *> &dives_from, struct dive_table *delete_from,
|
||||
static bool merge_dive_tables(const std::vector<dive *> &dives_from, struct dive_table &delete_from,
|
||||
const std::vector<dive *> &dives_to,
|
||||
bool prefer_imported, struct dive_trip *trip,
|
||||
/* output parameters: */
|
||||
struct dive_table *dives_to_add, struct dive_table *dives_to_remove,
|
||||
int *num_merged)
|
||||
struct dive_table &dives_to_add, struct std::vector<dive *> &dives_to_remove,
|
||||
int &num_merged)
|
||||
{
|
||||
bool sequence_changed = false;
|
||||
|
||||
|
@ -884,11 +843,18 @@ static bool merge_dive_tables(const std::vector<dive *> &dives_from, struct dive
|
|||
*/
|
||||
size_t j = 0; /* Index in dives_to */
|
||||
size_t last_merged_into = std::string::npos;
|
||||
for (auto dive_to_add: dives_from) {
|
||||
remove_dive(dive_to_add, delete_from);
|
||||
for (dive *add: dives_from) {
|
||||
/* This gets an owning pointer to the dive to add and removes it from
|
||||
* the delete_from table. If the dive is not explicitly stored, it will
|
||||
* be automatically deleting when ending the loop iteration */
|
||||
auto [dive_to_add, idx] = delete_from.pull(add);
|
||||
if (!dive_to_add) {
|
||||
report_info("merging unknown dives!");
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Find insertion point. */
|
||||
while (j < dives_to.size() && dive_less_than(dives_to[j], dive_to_add))
|
||||
while (j < dives_to.size() && dive_less_than(*dives_to[j], *dive_to_add))
|
||||
j++;
|
||||
|
||||
/* Try to merge into previous dive.
|
||||
|
@ -899,11 +865,10 @@ static bool merge_dive_tables(const std::vector<dive *> &dives_from, struct dive
|
|||
* transitive. But let's just go *completely* sure for the odd corner-case. */
|
||||
if (j > 0 && (last_merged_into == std::string::npos || j > last_merged_into + 1) &&
|
||||
dives_to[j - 1]->endtime() > dive_to_add->when) {
|
||||
if (try_to_merge_into(*dive_to_add, *dives_to[j - 1], prefer_imported,
|
||||
if (try_to_merge_into(*dive_to_add, dives_to[j - 1], prefer_imported,
|
||||
dives_to_add, dives_to_remove)) {
|
||||
delete dive_to_add;
|
||||
last_merged_into = j - 1;
|
||||
(*num_merged)++;
|
||||
num_merged++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
@ -912,19 +877,16 @@ static bool merge_dive_tables(const std::vector<dive *> &dives_from, struct dive
|
|||
* Try to merge into next dive. */
|
||||
if (j < dives_to.size() && (last_merged_into == std::string::npos || j > last_merged_into) &&
|
||||
dive_to_add->endtime() > dives_to[j]->when) {
|
||||
if (try_to_merge_into(*dive_to_add, *dives_to[j], prefer_imported,
|
||||
if (try_to_merge_into(*dive_to_add, dives_to[j], prefer_imported,
|
||||
dives_to_add, dives_to_remove)) {
|
||||
delete dive_to_add;
|
||||
last_merged_into = j;
|
||||
(*num_merged)++;
|
||||
num_merged++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* We couldnt merge dives, simply add to list of dives to-be-added. */
|
||||
insert_dive(dives_to_add, dive_to_add);
|
||||
sequence_changed |= !dive_is_after_last(dive_to_add);
|
||||
dive_to_add->divetrip = trip;
|
||||
sequence_changed |= !dive_is_after_last(*dive_to_add);
|
||||
dives_to_add.put(std::move(dive_to_add));
|
||||
}
|
||||
|
||||
return sequence_changed;
|
||||
|
@ -933,46 +895,34 @@ static bool merge_dive_tables(const std::vector<dive *> &dives_from, struct dive
|
|||
/* Merge the dives of the trip "from" and the dive_table "dives_from" into the trip "to"
|
||||
* and dive_table "dives_to". If "prefer_imported" is true, dive data of "from" takes
|
||||
* precedence */
|
||||
void add_imported_dives(struct divelog *import_log, int flags)
|
||||
void add_imported_dives(struct divelog &import_log, int flags)
|
||||
{
|
||||
int i, idx;
|
||||
struct dive_table dives_to_add = empty_dive_table;
|
||||
struct dive_table dives_to_remove = empty_dive_table;
|
||||
struct trip_table trips_to_add;
|
||||
dive_site_table dive_sites_to_add;
|
||||
device_table devices_to_add;
|
||||
|
||||
/* Process imported dives and generate lists of dives
|
||||
* to-be-added and to-be-removed */
|
||||
process_imported_dives(import_log, flags, &dives_to_add, &dives_to_remove, trips_to_add,
|
||||
dive_sites_to_add, devices_to_add);
|
||||
auto [dives_to_add, dives_to_remove, trips_to_add, dive_sites_to_add, devices_to_add] =
|
||||
process_imported_dives(import_log, flags);
|
||||
|
||||
/* Start by deselecting all dives, so that we don't end up with an invalid selection */
|
||||
select_single_dive(NULL);
|
||||
|
||||
/* Add new dives to trip and site to get reference count correct. */
|
||||
for (i = 0; i < dives_to_add.nr; i++) {
|
||||
struct dive *d = dives_to_add.dives[i];
|
||||
for (auto &d: dives_to_add) {
|
||||
struct dive_trip *trip = d->divetrip;
|
||||
struct dive_site *site = d->dive_site;
|
||||
d->divetrip = NULL;
|
||||
d->dive_site = NULL;
|
||||
add_dive_to_trip(d, trip);
|
||||
add_dive_to_trip(d.get(), trip);
|
||||
if (site)
|
||||
site->add_dive(d);
|
||||
site->add_dive(d.get());
|
||||
}
|
||||
|
||||
/* Remove old dives */
|
||||
for (i = 0; i < dives_to_remove.nr; i++) {
|
||||
idx = get_divenr(dives_to_remove.dives[i]);
|
||||
divelog.delete_single_dive(idx);
|
||||
}
|
||||
dives_to_remove.nr = 0;
|
||||
divelog.delete_multiple_dives(dives_to_remove);
|
||||
|
||||
/* Add new dives */
|
||||
for (i = 0; i < dives_to_add.nr; i++)
|
||||
insert_dive(divelog.dives.get(), dives_to_add.dives[i]);
|
||||
dives_to_add.nr = 0;
|
||||
for (auto &d: dives_to_add)
|
||||
divelog.dives.put(std::move(d));
|
||||
dives_to_add.clear();
|
||||
|
||||
/* Add new trips */
|
||||
for (auto &trip: trips_to_add)
|
||||
|
@ -989,10 +939,7 @@ void add_imported_dives(struct divelog *import_log, int flags)
|
|||
|
||||
/* We might have deleted the old selected dive.
|
||||
* Choose the newest dive as selected (if any) */
|
||||
current_dive = divelog.dives->nr > 0 ? divelog.dives->dives[divelog.dives->nr - 1] : NULL;
|
||||
|
||||
free(dives_to_add.dives);
|
||||
free(dives_to_remove.dives);
|
||||
current_dive = !divelog.dives.empty() ? divelog.dives.back().get() : nullptr;
|
||||
|
||||
/* Inform frontend of reset data. This should reset all the models. */
|
||||
emit_reset_signal();
|
||||
|
@ -1008,14 +955,14 @@ void add_imported_dives(struct divelog *import_log, int flags)
|
|||
* Returns true if trip was merged. In this case, the trip will be
|
||||
* 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: */
|
||||
struct dive_table *dives_to_add, struct dive_table *dives_to_remove,
|
||||
bool *sequence_changed, int *start_renumbering_at)
|
||||
struct dive_table &dives_to_add, std::vector<dive *> &dives_to_remove,
|
||||
bool &sequence_changed, int &start_renumbering_at)
|
||||
{
|
||||
for (auto &trip_old: *divelog.trips) {
|
||||
if (trips_overlap(trip_import, *trip_old)) {
|
||||
*sequence_changed |= merge_dive_tables(trip_import.dives, import_table, trip_old->dives,
|
||||
sequence_changed |= merge_dive_tables(trip_import.dives, import_table, trip_old->dives,
|
||||
prefer_imported, trip_old.get(),
|
||||
dives_to_add, dives_to_remove,
|
||||
start_renumbering_at);
|
||||
|
@ -1033,27 +980,21 @@ static bool try_to_merge_trip(dive_trip &trip_import, struct dive_table *import_
|
|||
static std::vector<dive *> dive_table_to_non_owning(const dive_table &dives)
|
||||
{
|
||||
std::vector<dive *> res;
|
||||
res.reserve(dives.nr);
|
||||
for (int i = 0; i < dives.nr; ++i)
|
||||
res.push_back(dives.dives[i]);
|
||||
res.reserve(dives.size());
|
||||
for (auto &d: dives)
|
||||
res.push_back(d.get());
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Process imported dives: take a table of dives to be imported and
|
||||
* generate five lists:
|
||||
* 1) Dives to be added
|
||||
* 2) Dives to be removed
|
||||
* 3) Trips to be added
|
||||
* 4) Dive sites to be added
|
||||
* 5) Devices to be added
|
||||
* The dives to be added are owning (i.e. the caller is responsible
|
||||
* for freeing them).
|
||||
* The dives, trips and sites in "import_table", "import_trip_table"
|
||||
* and "import_sites_table" are consumed. On return, the tables have
|
||||
* size 0. "import_trip_table" may be NULL if all dives are not associated
|
||||
* with a trip.
|
||||
* The output tables should be empty - if not, their content
|
||||
* will be cleared!
|
||||
* 1) Dives to be added (newly created, owned)
|
||||
* 2) Dives to be removed (old, non-owned, references global divelog)
|
||||
* 3) Trips to be added (newly created, owned)
|
||||
* 4) Dive sites to be added (newly created, owned)
|
||||
* 5) Devices to be added (newly created, owned)
|
||||
* The dives, trips and sites in import_log are consumed.
|
||||
* On return, the tables have * size 0.
|
||||
*
|
||||
* Note: The new dives will have their divetrip- and divesites-fields
|
||||
* set, but will *not* be part of the trip and site. The caller has to
|
||||
|
@ -1072,90 +1013,70 @@ static std::vector<dive *> dive_table_to_non_owning(const dive_table &dives)
|
|||
* - If IMPORT_ADD_TO_NEW_TRIP is true, dives that are not assigned
|
||||
* to a trip will be added to a newly generated trip.
|
||||
*/
|
||||
void process_imported_dives(struct divelog *import_log, int flags,
|
||||
/* output parameters: */
|
||||
struct dive_table *dives_to_add, struct dive_table *dives_to_remove,
|
||||
struct trip_table &trips_to_add, dive_site_table &sites_to_add,
|
||||
device_table &devices_to_add)
|
||||
process_imported_dives_result process_imported_dives(struct divelog &import_log, int flags)
|
||||
{
|
||||
int i, j, nr, start_renumbering_at = 0;
|
||||
int start_renumbering_at = 0;
|
||||
bool sequence_changed = false;
|
||||
bool new_dive_has_number = false;
|
||||
bool last_old_dive_is_numbered;
|
||||
|
||||
/* Make sure that output parameters don't contain garbage */
|
||||
clear_dive_table(dives_to_add);
|
||||
clear_dive_table(dives_to_remove);
|
||||
trips_to_add.clear();
|
||||
sites_to_add.clear();
|
||||
devices_to_add.clear();
|
||||
process_imported_dives_result res;
|
||||
|
||||
/* If no dives were imported, don't bother doing anything */
|
||||
if (import_log.dives.empty())
|
||||
return res;
|
||||
|
||||
/* Check if any of the new dives has a number. This will be
|
||||
* important later to decide if we want to renumber the added
|
||||
* dives */
|
||||
for (int i = 0; i < import_log->dives->nr; i++) {
|
||||
if (import_log->dives->dives[i]->number > 0) {
|
||||
new_dive_has_number = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* If no dives were imported, don't bother doing anything */
|
||||
if (!import_log->dives->nr)
|
||||
return;
|
||||
bool new_dive_has_number = std::any_of(import_log.dives.begin(), import_log.dives.end(),
|
||||
[](auto &d) { return d->number > 0; });
|
||||
|
||||
/* Add only the devices that we don't know about yet. */
|
||||
for (auto &dev: import_log->devices) {
|
||||
for (auto &dev: import_log.devices) {
|
||||
if (!device_exists(divelog.devices, dev))
|
||||
add_to_device_table(devices_to_add, dev);
|
||||
add_to_device_table(res.devices_to_add, dev);
|
||||
}
|
||||
|
||||
/* Sort the table of dives to be imported and combine mergable dives */
|
||||
sort_dive_table(import_log->dives.get());
|
||||
merge_imported_dives(import_log->dives.get());
|
||||
import_log.dives.sort();
|
||||
merge_imported_dives(import_log.dives);
|
||||
|
||||
/* Autogroup tripless dives if desired by user. But don't autogroup
|
||||
* if tripless dives should be added to a new trip. */
|
||||
if (!(flags & IMPORT_ADD_TO_NEW_TRIP))
|
||||
autogroup_dives(import_log->dives.get(), *import_log->trips);
|
||||
autogroup_dives(import_log.dives, *import_log.trips);
|
||||
|
||||
/* If dive sites already exist, use the existing versions. */
|
||||
for (auto &new_ds: *import_log->sites) {
|
||||
struct dive_site *old_ds = divelog.sites->get_same(*new_ds);
|
||||
|
||||
for (auto &new_ds: *import_log.sites) {
|
||||
/* Check if it dive site is actually used by new dives. */
|
||||
for (j = 0; j < import_log->dives->nr; j++) {
|
||||
if (import_log->dives->dives[j]->dive_site == new_ds.get())
|
||||
break;
|
||||
}
|
||||
|
||||
if (j == import_log->dives->nr) {
|
||||
/* Dive site not even used. */
|
||||
if (std::none_of(import_log.dives.begin(), import_log.dives.end(), [ds=new_ds.get()]
|
||||
(auto &d) { return d->dive_site == ds; }))
|
||||
continue;
|
||||
}
|
||||
|
||||
struct dive_site *old_ds = divelog.sites->get_same(*new_ds);
|
||||
if (!old_ds) {
|
||||
/* Dive site doesn't exist. Add it to list of dive sites to be added. */
|
||||
new_ds->dives.clear(); /* Caller is responsible for adding dives to site */
|
||||
sites_to_add.put(std::move(new_ds));
|
||||
res.sites_to_add.put(std::move(new_ds));
|
||||
} else {
|
||||
/* Dive site already exists - use the old one. */
|
||||
for (j = 0; j < import_log->dives->nr; j++) {
|
||||
if (import_log->dives->dives[j]->dive_site == new_ds.get())
|
||||
import_log->dives->dives[j]->dive_site = old_ds;
|
||||
for (auto &d: import_log.dives) {
|
||||
if (d->dive_site == new_ds.get())
|
||||
d->dive_site = old_ds;
|
||||
}
|
||||
}
|
||||
}
|
||||
import_log->sites->clear();
|
||||
import_log.sites->clear();
|
||||
|
||||
/* Merge overlapping trips. Since both trip tables are sorted, we
|
||||
* 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.
|
||||
*/
|
||||
for (auto &trip_import: *import_log->trips) {
|
||||
for (auto &trip_import: *import_log.trips) {
|
||||
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,
|
||||
&sequence_changed, &start_renumbering_at))
|
||||
if (try_to_merge_trip(*trip_import, import_log.dives, flags & IMPORT_PREFER_IMPORTED,
|
||||
res.dives_to_add, res.dives_to_remove,
|
||||
sequence_changed, start_renumbering_at))
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -1163,43 +1084,43 @@ void process_imported_dives(struct divelog *import_log, int flags,
|
|||
* First, add dives to list of dives to add */
|
||||
for (struct dive *d: trip_import->dives) {
|
||||
/* Add dive to list of dives to-be-added. */
|
||||
insert_dive(dives_to_add, d);
|
||||
sequence_changed |= !dive_is_after_last(d);
|
||||
|
||||
remove_dive(d, import_log->dives.get());
|
||||
auto [owned, idx] = import_log.dives.pull(d);
|
||||
if (!owned)
|
||||
continue;
|
||||
sequence_changed |= !dive_is_after_last(*owned);
|
||||
res.dives_to_add.put(std::move(owned));
|
||||
}
|
||||
|
||||
trip_import->dives.clear(); /* 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));
|
||||
res.trips_to_add.put(std::move(trip_import));
|
||||
}
|
||||
import_log->trips->clear(); /* 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.empty()) {
|
||||
/* Create a new trip for unassigned dives, if desired. */
|
||||
auto [new_trip, idx] = trips_to_add.put(
|
||||
create_trip_from_dive(import_log->dives->dives[0])
|
||||
auto [new_trip, idx] = res.trips_to_add.put(
|
||||
create_trip_from_dive(import_log.dives.front().get())
|
||||
);
|
||||
|
||||
/* Add all remaining dives to this trip */
|
||||
for (i = 0; i < import_log->dives->nr; i++) {
|
||||
struct dive *d = import_log->dives->dives[i];
|
||||
for (auto &d: import_log.dives) {
|
||||
sequence_changed |= !dive_is_after_last(*d);
|
||||
d->divetrip = new_trip;
|
||||
insert_dive(dives_to_add, d);
|
||||
sequence_changed |= !dive_is_after_last(d);
|
||||
res.dives_to_add.put(std::move(d));
|
||||
}
|
||||
|
||||
import_log->dives->nr = 0; /* All dives were consumed */
|
||||
} else if (import_log->dives->nr > 0) {
|
||||
/* The remaining dives in import_log->dives are those that don't belong to
|
||||
import_log.dives.clear(); /* All dives were consumed */
|
||||
} else if (!import_log.dives.empty()) {
|
||||
/* The remaining dives in import_log.dives are those that don't belong to
|
||||
* a trip and the caller does not want them to be associated to a
|
||||
* new trip. Merge them into the global table. */
|
||||
sequence_changed |= merge_dive_tables(dive_table_to_non_owning(*import_log->dives),
|
||||
import_log->dives.get(),
|
||||
dive_table_to_non_owning(*divelog.dives),
|
||||
sequence_changed |= merge_dive_tables(dive_table_to_non_owning(import_log.dives),
|
||||
import_log.dives,
|
||||
dive_table_to_non_owning(divelog.dives),
|
||||
flags & IMPORT_PREFER_IMPORTED, NULL,
|
||||
dives_to_add, dives_to_remove, &start_renumbering_at);
|
||||
res.dives_to_add, res.dives_to_remove, start_renumbering_at);
|
||||
}
|
||||
|
||||
/* If new dives were only added at the end, renumber the added dives.
|
||||
|
@ -1207,26 +1128,25 @@ void process_imported_dives(struct divelog *import_log, int flags,
|
|||
* - The last dive in the old dive table had a number itself (if there is a last dive).
|
||||
* - None of the new dives has a number.
|
||||
*/
|
||||
last_old_dive_is_numbered = divelog.dives->nr == 0 || divelog.dives->dives[divelog.dives->nr - 1]->number > 0;
|
||||
last_old_dive_is_numbered = divelog.dives.empty() || divelog.dives.back()->number > 0;
|
||||
|
||||
/* We counted the number of merged dives that were added to dives_to_add.
|
||||
* Skip those. Since sequence_changed is false all added dives are *after*
|
||||
* all merged dives. */
|
||||
if (!sequence_changed && last_old_dive_is_numbered && !new_dive_has_number) {
|
||||
nr = divelog.dives->nr > 0 ? divelog.dives->dives[divelog.dives->nr - 1]->number : 0;
|
||||
for (i = start_renumbering_at; i < dives_to_add->nr; i++)
|
||||
dives_to_add->dives[i]->number = ++nr;
|
||||
int nr = !divelog.dives.empty() ? divelog.dives.back()->number : 0;
|
||||
for (auto it = res.dives_to_add.begin() + start_renumbering_at; it < res.dives_to_add.end(); ++it)
|
||||
(*it)->number = ++nr;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static struct dive *get_last_valid_dive()
|
||||
{
|
||||
int i;
|
||||
for (i = divelog.dives->nr - 1; i >= 0; i--) {
|
||||
if (!divelog.dives->dives[i]->invalid)
|
||||
return divelog.dives->dives[i];
|
||||
}
|
||||
return NULL;
|
||||
auto it = std::find_if(divelog.dives.rbegin(), divelog.dives.rend(),
|
||||
[](auto &d) { return !d->invalid; });
|
||||
return it != divelog.dives.rend() ? it->get() : nullptr;
|
||||
}
|
||||
|
||||
/* return the number a dive gets when inserted at the given index.
|
||||
|
@ -1238,7 +1158,7 @@ static struct dive *get_last_valid_dive()
|
|||
*/
|
||||
int get_dive_nr_at_idx(int idx)
|
||||
{
|
||||
if (idx < divelog.dives->nr)
|
||||
if (static_cast<size_t>(idx) < divelog.dives.size())
|
||||
return 0;
|
||||
struct dive *last_dive = get_last_valid_dive();
|
||||
if (!last_dive)
|
||||
|
@ -1246,6 +1166,19 @@ int get_dive_nr_at_idx(int idx)
|
|||
return last_dive->number ? last_dive->number + 1 : 0;
|
||||
}
|
||||
|
||||
/* lookup of trip in main trip_table based on its id */
|
||||
dive *dive_table::get_by_uniq_id(int id) const
|
||||
{
|
||||
auto it = std::find_if(begin(), end(), [id](auto &d) { return d->id == id; });
|
||||
#ifdef DEBUG
|
||||
if (it == end()) {
|
||||
report_info("Invalid id %x passed to get_dive_by_diveid, try to fix the code", id);
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
return it != end() ? it->get() : nullptr;
|
||||
}
|
||||
|
||||
static int min_datafile_version;
|
||||
|
||||
int get_min_datafile_version()
|
||||
|
@ -1278,11 +1211,16 @@ void clear_dive_file_data()
|
|||
emit_reset_signal();
|
||||
}
|
||||
|
||||
bool dive_less_than(const struct dive *a, const struct dive *b)
|
||||
bool dive_less_than(const struct dive &a, const struct dive &b)
|
||||
{
|
||||
return comp_dives(a, b) < 0;
|
||||
}
|
||||
|
||||
bool dive_less_than_ptr(const struct dive *a, const struct dive *b)
|
||||
{
|
||||
return comp_dives(*a, *b) < 0;
|
||||
}
|
||||
|
||||
/* When comparing a dive to a trip, use the first dive of the trip. */
|
||||
static int comp_dive_to_trip(struct dive *a, struct dive_trip *b)
|
||||
{
|
||||
|
@ -1290,7 +1228,7 @@ static int comp_dive_to_trip(struct dive *a, struct dive_trip *b)
|
|||
* with no (or worse a negative number of) dives. */
|
||||
if (!b || b->dives.empty())
|
||||
return -1;
|
||||
return comp_dives(a, b->dives[0]);
|
||||
return comp_dives(*a, *b->dives[0]);
|
||||
}
|
||||
|
||||
static int comp_dive_or_trip(struct dive_or_trip a, struct dive_or_trip b)
|
||||
|
@ -1308,7 +1246,7 @@ static int comp_dive_or_trip(struct dive_or_trip a, struct dive_or_trip b)
|
|||
if (!b.dive && !b.trip)
|
||||
return 1;
|
||||
if (a.dive && b.dive)
|
||||
return comp_dives(a.dive, b.dive);
|
||||
return comp_dives(*a.dive, *b.dive);
|
||||
if (a.trip && b.trip)
|
||||
return comp_trips(*a.trip, *b.trip);
|
||||
if (a.dive)
|
||||
|
@ -1334,18 +1272,15 @@ bool dive_or_trip_less_than(struct dive_or_trip a, struct dive_or_trip b)
|
|||
*/
|
||||
timestamp_t get_surface_interval(timestamp_t when)
|
||||
{
|
||||
int i;
|
||||
timestamp_t prev_end;
|
||||
|
||||
/* find previous dive. might want to use a binary search. */
|
||||
for (i = divelog.dives->nr - 1; i >= 0; --i) {
|
||||
if (divelog.dives->dives[i]->when < when)
|
||||
break;
|
||||
}
|
||||
if (i < 0)
|
||||
auto it = std::find_if(divelog.dives.rbegin(), divelog.dives.rend(),
|
||||
[when] (auto &d) { return d->when < when; });
|
||||
if (it == divelog.dives.rend())
|
||||
return -1;
|
||||
|
||||
prev_end = divelog.dives->dives[i]->endtime();
|
||||
prev_end = (*it)->endtime();
|
||||
if (prev_end > when)
|
||||
return 0;
|
||||
return when - prev_end;
|
||||
|
@ -1355,43 +1290,31 @@ timestamp_t get_surface_interval(timestamp_t when)
|
|||
* then newer dives. */
|
||||
struct dive *find_next_visible_dive(timestamp_t when)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
if (!divelog.dives->nr)
|
||||
return NULL;
|
||||
if (divelog.dives.empty())
|
||||
return nullptr;
|
||||
|
||||
/* we might want to use binary search here */
|
||||
for (i = 0; i < divelog.dives->nr; i++) {
|
||||
if (when <= get_dive(i)->when)
|
||||
break;
|
||||
auto it = std::find_if(divelog.dives.begin(), divelog.dives.end(),
|
||||
[when] (auto &d) { return d->when <= when; });
|
||||
|
||||
for (auto it2 = it; it2 != divelog.dives.begin(); --it2) {
|
||||
if (!(*std::prev(it2))->hidden_by_filter)
|
||||
return it2->get();
|
||||
}
|
||||
|
||||
for (j = i - 1; j > 0; j--) {
|
||||
if (!get_dive(j)->hidden_by_filter)
|
||||
return get_dive(j);
|
||||
for (auto it2 = it; it2 != divelog.dives.end(); ++it2) {
|
||||
if (!(*it2)->hidden_by_filter)
|
||||
return it2->get();
|
||||
}
|
||||
|
||||
for (j = i; j < divelog.dives->nr; j++) {
|
||||
if (!get_dive(j)->hidden_by_filter)
|
||||
return get_dive(j);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool has_dive(unsigned int deviceid, unsigned int diveid)
|
||||
{
|
||||
int i;
|
||||
struct dive *dive;
|
||||
|
||||
for_each_dive (i, dive) {
|
||||
for (auto &dc: dive->dcs) {
|
||||
if (dc.deviceid != deviceid)
|
||||
continue;
|
||||
if (dc.diveid != diveid)
|
||||
continue;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return std::any_of(divelog.dives.begin(), divelog.dives.end(), [deviceid,diveid] (auto &d) {
|
||||
return std::any_of(d->dcs.begin(), d->dcs.end(), [deviceid,diveid] (auto &dc) {
|
||||
return dc.deviceid == deviceid && dc.diveid == diveid;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -2,27 +2,29 @@
|
|||
#ifndef DIVELIST_H
|
||||
#define DIVELIST_H
|
||||
|
||||
#include "triptable.h"
|
||||
#include "divesitetable.h"
|
||||
#include "units.h"
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
struct dive;
|
||||
struct divelog;
|
||||
struct trip_table;
|
||||
class dive_site_table;
|
||||
struct device;
|
||||
struct deco_state;
|
||||
|
||||
struct dive_table {
|
||||
int nr, allocated;
|
||||
struct dive **dives;
|
||||
int comp_dives(const struct dive &a, const struct dive &b);
|
||||
int comp_dives_ptr(const struct dive *a, const struct dive *b);
|
||||
|
||||
struct dive_table : public sorted_owning_table<dive, &comp_dives> {
|
||||
dive *get_by_uniq_id(int id) const;
|
||||
void record_dive(std::unique_ptr<dive> d); // call fixup_dive() before adding dive to table.
|
||||
std::unique_ptr<dive> unregister_dive(int idx);
|
||||
};
|
||||
static const struct dive_table empty_dive_table = { 0, 0, (struct dive **)0 };
|
||||
|
||||
/* this is used for both git and xml format */
|
||||
#define DATAFORMAT_VERSION 3
|
||||
|
||||
extern void sort_dive_table(struct dive_table *table);
|
||||
extern void update_cylinder_related_info(struct dive *);
|
||||
extern int init_decompression(struct deco_state *ds, const struct dive *dive, bool in_planner);
|
||||
|
||||
|
@ -33,30 +35,26 @@ extern void process_loaded_dives();
|
|||
#define IMPORT_IS_DOWNLOADED (1 << 1)
|
||||
#define IMPORT_MERGE_ALL_TRIPS (1 << 2)
|
||||
#define IMPORT_ADD_TO_NEW_TRIP (1 << 3)
|
||||
extern void add_imported_dives(struct divelog *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 trip_table &trips_to_add, dive_site_table &sites_to_add,
|
||||
std::vector<device> &devices_to_add);
|
||||
extern void add_imported_dives(struct divelog &log, int flags);
|
||||
|
||||
struct process_imported_dives_result {
|
||||
dive_table dives_to_add;
|
||||
std::vector<dive *> dives_to_remove;
|
||||
trip_table trips_to_add;
|
||||
dive_site_table sites_to_add;
|
||||
std::vector<device> devices_to_add;
|
||||
};
|
||||
|
||||
extern process_imported_dives_result process_imported_dives(struct divelog &import_log, int flags);
|
||||
|
||||
extern int dive_table_get_insertion_index(struct dive_table *table, struct dive *dive);
|
||||
extern void add_to_dive_table(struct dive_table *table, int idx, struct dive *dive);
|
||||
extern void insert_dive(struct dive_table *table, struct dive *d);
|
||||
extern void get_dive_gas(const struct dive *dive, int *o2_p, int *he_p, int *o2low_p);
|
||||
extern int get_divenr(const struct dive *dive);
|
||||
extern int remove_dive(const struct dive *dive, struct dive_table *table);
|
||||
extern int get_dive_nr_at_idx(int idx);
|
||||
extern timestamp_t get_surface_interval(timestamp_t when);
|
||||
extern void delete_dive_from_table(struct dive_table *table, int idx);
|
||||
extern struct dive *find_next_visible_dive(timestamp_t when);
|
||||
|
||||
extern int comp_dives(const struct dive *a, const struct dive *b);
|
||||
|
||||
int get_min_datafile_version();
|
||||
void report_datafile_version(int version);
|
||||
void clear_dive_file_data();
|
||||
void clear_dive_table(struct dive_table *table);
|
||||
struct dive *unregister_dive(int idx);
|
||||
struct dive *register_dive(std::unique_ptr<dive> d);
|
||||
extern bool has_dive(unsigned int deviceid, unsigned int diveid);
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include "divelist.h"
|
||||
#include "divesite.h"
|
||||
#include "device.h"
|
||||
#include "dive.h"
|
||||
#include "errorhelper.h"
|
||||
#include "filterpreset.h"
|
||||
#include "trip.h"
|
||||
|
@ -10,21 +11,14 @@
|
|||
struct divelog divelog;
|
||||
|
||||
divelog::divelog() :
|
||||
dives(std::make_unique<dive_table>()),
|
||||
trips(std::make_unique<trip_table>()),
|
||||
sites(std::make_unique<dive_site_table>()),
|
||||
filter_presets(std::make_unique<filter_preset_table>()),
|
||||
autogroup(false)
|
||||
{
|
||||
*dives = empty_dive_table;
|
||||
}
|
||||
|
||||
divelog::~divelog()
|
||||
{
|
||||
if (dives)
|
||||
clear_dive_table(dives.get());
|
||||
}
|
||||
|
||||
divelog::~divelog() = default;
|
||||
divelog::divelog(divelog &&) = default;
|
||||
struct divelog &divelog::operator=(divelog &&) = default;
|
||||
|
||||
|
@ -32,11 +26,11 @@ struct divelog &divelog::operator=(divelog &&) = default;
|
|||
* dive log and the trip, but doesn't deal with updating dive trips, etc */
|
||||
void divelog::delete_single_dive(int idx)
|
||||
{
|
||||
if (idx < 0 || idx > dives->nr) {
|
||||
report_info("Warning: deleting unexisting dive with index %d", idx);
|
||||
if (idx < 0 || static_cast<size_t>(idx) >= dives.size()) {
|
||||
report_info("Warning: deleting non-existing dive with index %d", idx);
|
||||
return;
|
||||
}
|
||||
struct dive *dive = dives->dives[idx];
|
||||
struct dive *dive = dives[idx].get();
|
||||
struct dive_trip *trip = unregister_dive_from_trip(dive);
|
||||
|
||||
// Deleting a dive may change the order of trips!
|
||||
|
@ -46,15 +40,58 @@ void divelog::delete_single_dive(int idx)
|
|||
if (trip && trip->dives.empty())
|
||||
trips->pull(trip);
|
||||
unregister_dive_from_dive_site(dive);
|
||||
delete_dive_from_table(dives.get(), idx);
|
||||
dives.erase(dives.begin() + idx);
|
||||
}
|
||||
|
||||
void divelog::delete_multiple_dives(const std::vector<dive *> &dives_to_delete)
|
||||
{
|
||||
bool trips_changed = false;
|
||||
|
||||
for (dive *d: dives_to_delete) {
|
||||
// Delete dive from trip and delete trip if empty
|
||||
struct dive_trip *trip = unregister_dive_from_trip(d);
|
||||
if (trip && trip->dives.empty()) {
|
||||
trips_changed = true;
|
||||
trips->pull(trip);
|
||||
}
|
||||
|
||||
unregister_dive_from_dive_site(d);
|
||||
dives.pull(d);
|
||||
}
|
||||
|
||||
// Deleting a dive may change the order of trips!
|
||||
if (trips_changed)
|
||||
trips->sort();
|
||||
}
|
||||
|
||||
void divelog::clear()
|
||||
{
|
||||
while (dives->nr > 0)
|
||||
delete_dive_from_table(dives.get(), dives->nr - 1);
|
||||
dives.clear();
|
||||
sites->clear();
|
||||
trips->clear();
|
||||
devices.clear();
|
||||
filter_presets->clear();
|
||||
}
|
||||
|
||||
/* check if we have a trip right before / after this dive */
|
||||
bool divelog::is_trip_before_after(const struct dive *dive, bool before) const
|
||||
{
|
||||
auto it = std::find_if(dives.begin(), dives.end(),
|
||||
[dive](auto &d) { return d.get() == dive; });
|
||||
if (it == dives.end())
|
||||
return false;
|
||||
|
||||
if (before) {
|
||||
do {
|
||||
if (it == dives.begin())
|
||||
return false;
|
||||
--it;
|
||||
} while ((*it)->invalid);
|
||||
return (*it)->divetrip != nullptr;
|
||||
} else {
|
||||
++it;
|
||||
while (it != dives.end() && (*it)->invalid)
|
||||
++it;
|
||||
return it != dives.end() && (*it)->divetrip != nullptr;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,17 +3,18 @@
|
|||
#ifndef DIVELOG_H
|
||||
#define DIVELOG_H
|
||||
|
||||
#include "divelist.h"
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
struct dive_table;
|
||||
struct trip_table;
|
||||
class dive_site_table;
|
||||
struct device;
|
||||
struct filter_preset_table;
|
||||
|
||||
struct divelog {
|
||||
std::unique_ptr<dive_table> dives;
|
||||
dive_table dives;
|
||||
std::unique_ptr<trip_table> trips;
|
||||
std::unique_ptr<dive_site_table> sites;
|
||||
std::vector<device> devices;
|
||||
|
@ -26,7 +27,9 @@ struct divelog {
|
|||
divelog &operator=(divelog &&); // move assignment (argument is consumed).
|
||||
|
||||
void delete_single_dive(int idx);
|
||||
void delete_multiple_dives(const std::vector<dive *> &dives);
|
||||
void clear();
|
||||
bool is_trip_before_after(const struct dive *dive, bool before) const;
|
||||
};
|
||||
|
||||
extern struct divelog divelog;
|
||||
|
|
|
@ -11,6 +11,13 @@
|
|||
|
||||
#include <math.h>
|
||||
|
||||
int divesite_comp_uuid(const dive_site &ds1, const dive_site &ds2)
|
||||
{
|
||||
if (ds1.uuid == ds2.uuid)
|
||||
return 0;
|
||||
return ds1.uuid < ds2.uuid ? -1 : 1;
|
||||
}
|
||||
|
||||
template <typename PRED>
|
||||
dive_site *get_by_predicate(const dive_site_table &ds_table, PRED pred)
|
||||
{
|
||||
|
|
|
@ -3,13 +3,10 @@
|
|||
#define DIVESITE_H
|
||||
|
||||
#include "divelist.h"
|
||||
#include "owning_table.h"
|
||||
#include "taxonomy.h"
|
||||
#include "units.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <QObject>
|
||||
|
||||
struct dive_site
|
||||
{
|
||||
uint32_t uuid = 0;
|
||||
|
@ -33,32 +30,11 @@ struct dive_site
|
|||
void add_dive(struct dive *d);
|
||||
};
|
||||
|
||||
inline int divesite_comp_uuid(const dive_site &ds1, const dive_site &ds2)
|
||||
{
|
||||
if (ds1.uuid == ds2.uuid)
|
||||
return 0;
|
||||
return ds1.uuid < ds2.uuid ? -1 : 1;
|
||||
}
|
||||
|
||||
class dive_site_table : public sorted_owning_table<dive_site, &divesite_comp_uuid> {
|
||||
public:
|
||||
put_result register_site(std::unique_ptr<dive_site> site); // Creates or changes UUID if duplicate
|
||||
dive_site *get_by_uuid(uint32_t uuid) const;
|
||||
dive_site *alloc_or_get(uint32_t uuid);
|
||||
dive_site *create(const std::string &name);
|
||||
dive_site *create(const std::string &name, const location_t);
|
||||
dive_site *find_or_create(const std::string &name);
|
||||
dive_site *get_by_name(const std::string &name) const;
|
||||
dive_site *get_by_gps(const location_t *) const;
|
||||
dive_site *get_by_gps_and_name(const std::string &name, const location_t) const;
|
||||
dive_site *get_by_gps_proximity(location_t, int distance) const;
|
||||
dive_site *get_same(const struct dive_site &) const;
|
||||
void purge_empty();
|
||||
};
|
||||
|
||||
struct dive_site *unregister_dive_from_dive_site(struct dive *d);
|
||||
int divesite_comp_uuid(const dive_site &ds1, const dive_site &ds2);
|
||||
|
||||
/* Make pointer-to-dive_site a "Qt metatype" so that we can pass it through QVariants */
|
||||
#include <QObject>
|
||||
Q_DECLARE_METATYPE(dive_site *);
|
||||
|
||||
#endif // DIVESITE_H
|
||||
|
|
27
core/divesitetable.h
Normal file
27
core/divesitetable.h
Normal file
|
@ -0,0 +1,27 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
#ifndef DIVESITETABLE_H
|
||||
#define DIVESITETABLE_H
|
||||
|
||||
#include "owning_table.h"
|
||||
#include "units.h"
|
||||
|
||||
struct dive_site;
|
||||
int divesite_comp_uuid(const dive_site &ds1, const dive_site &ds2);
|
||||
|
||||
class dive_site_table : public sorted_owning_table<dive_site, &divesite_comp_uuid> {
|
||||
public:
|
||||
put_result register_site(std::unique_ptr<dive_site> site); // Creates or changes UUID if duplicate
|
||||
dive_site *get_by_uuid(uint32_t uuid) const;
|
||||
dive_site *alloc_or_get(uint32_t uuid);
|
||||
dive_site *create(const std::string &name);
|
||||
dive_site *create(const std::string &name, const location_t);
|
||||
dive_site *find_or_create(const std::string &name);
|
||||
dive_site *get_by_name(const std::string &name) const;
|
||||
dive_site *get_by_gps(const location_t *) const;
|
||||
dive_site *get_by_gps_and_name(const std::string &name, const location_t) const;
|
||||
dive_site *get_by_gps_proximity(location_t, int distance) const;
|
||||
dive_site *get_same(const struct dive_site &) const;
|
||||
void purge_empty();
|
||||
};
|
||||
|
||||
#endif // DIVESITETABLE_H
|
|
@ -112,9 +112,9 @@ void DownloadThread::run()
|
|||
internalData->vendor.c_str(), internalData->product.c_str());
|
||||
report_info("Finishing download thread: %s", error.c_str());
|
||||
} else {
|
||||
if (!log.dives->nr)
|
||||
if (log.dives.empty())
|
||||
error = tr("No new dives downloaded from dive computer").toStdString();
|
||||
report_info("Finishing download thread: %d dives downloaded", log.dives->nr);
|
||||
report_info("Finishing download thread: %d dives downloaded", static_cast<int>(log.dives.size()));
|
||||
}
|
||||
qPrefDiveComputer::set_vendor(internalData->vendor.c_str());
|
||||
qPrefDiveComputer::set_product(internalData->product.c_str());
|
||||
|
|
|
@ -284,8 +284,7 @@ void reset_tank_info_table(std::vector<tank_info> &table)
|
|||
add_default_tank_infos(table);
|
||||
|
||||
/* Add cylinders from dive list */
|
||||
for (int i = 0; i < divelog.dives->nr; ++i) {
|
||||
const struct dive *dive = divelog.dives->dives[i];
|
||||
for (auto &dive: divelog.dives) {
|
||||
for (auto &cyl: dive->cylinders)
|
||||
add_cylinder_description(cyl.type);
|
||||
}
|
||||
|
|
|
@ -143,11 +143,9 @@ void FullText::populate()
|
|||
// we want this to be two calls as the second text is overwritten below by the lines starting with "\r"
|
||||
uiNotification(QObject::tr("Create full text index"));
|
||||
uiNotification(QObject::tr("start processing"));
|
||||
int i;
|
||||
dive *d;
|
||||
for_each_dive(i, d)
|
||||
registerDive(d);
|
||||
uiNotification(QObject::tr("%1 dives processed").arg(divelog.dives->nr));
|
||||
for (auto &d: divelog.dives)
|
||||
registerDive(d.get());
|
||||
uiNotification(QObject::tr("%1 dives processed").arg(divelog.dives.size()));
|
||||
}
|
||||
|
||||
void FullText::registerDive(struct dive *d)
|
||||
|
@ -170,9 +168,7 @@ void FullText::unregisterDive(struct dive *d)
|
|||
|
||||
void FullText::unregisterAll()
|
||||
{
|
||||
int i;
|
||||
dive *d;
|
||||
for_each_dive(i, d)
|
||||
for (auto &d: divelog.dives)
|
||||
d->full_text.reset();
|
||||
words.clear();
|
||||
}
|
||||
|
|
|
@ -443,7 +443,7 @@ int try_to_open_csv(std::string &mem, enum csv_format type, struct divelog *log)
|
|||
break;
|
||||
p = end + 1;
|
||||
}
|
||||
record_dive_to_table(dive.release(), log->dives.get());
|
||||
log->dives.record_dive(std::move(dive));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -749,7 +749,7 @@ int parse_txt_file(const char *filename, const char *csv, struct divelog *log)
|
|||
if (!lineptr || !*lineptr)
|
||||
break;
|
||||
}
|
||||
record_dive_to_table(dive.release(), log->dives.get());
|
||||
log->dives.record_dive(std::move(dive));
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
|
|
|
@ -537,7 +537,7 @@ static int might_be_same_dc(const struct divecomputer &a, const struct divecompu
|
|||
return a.deviceid == b.deviceid;
|
||||
}
|
||||
|
||||
static bool match_one_dive(const struct divecomputer &a, struct dive *dive)
|
||||
static bool match_one_dive(const struct divecomputer &a, const struct dive &dive)
|
||||
{
|
||||
/*
|
||||
* Walk the existing dive computer data,
|
||||
|
@ -545,13 +545,13 @@ static bool match_one_dive(const struct divecomputer &a, struct dive *dive)
|
|||
* the same dive computer but a different
|
||||
* dive ID).
|
||||
*/
|
||||
for (auto &b: dive->dcs) {
|
||||
for (auto &b: dive.dcs) {
|
||||
if (match_one_dc(a, b) > 0)
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Ok, no exact dive computer match. Does the date match? */
|
||||
for (auto &b: dive->dcs) {
|
||||
for (auto &b: dive.dcs) {
|
||||
if (a.when == b.when && might_be_same_dc(a, b))
|
||||
return true;
|
||||
}
|
||||
|
@ -562,17 +562,10 @@ static bool match_one_dive(const struct divecomputer &a, struct dive *dive)
|
|||
/*
|
||||
* Check if this dive already existed before the import
|
||||
*/
|
||||
static int find_dive(const struct divecomputer &match)
|
||||
static bool find_dive(const struct divecomputer &match)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = divelog.dives->nr - 1; i >= 0; i--) {
|
||||
struct dive *old = divelog.dives->dives[i];
|
||||
|
||||
if (match_one_dive(match, old))
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
return std::any_of(divelog.dives.rbegin(), divelog.dives.rend(),
|
||||
[&match] (auto &old) { return match_one_dive(match, *old);} );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -871,7 +864,7 @@ static int dive_cb(const unsigned char *data, unsigned int size,
|
|||
dive->dcs[0].samples[1].temperature.mkelvin > dive->dcs[0].samples[0].temperature.mkelvin)
|
||||
dive->dcs[0].samples[0].temperature.mkelvin = dive->dcs[0].samples[1].temperature.mkelvin;
|
||||
|
||||
record_dive_to_table(dive.release(), devdata->log->dives.get());
|
||||
devdata->log->dives.record_dive(std::move(dive));
|
||||
return true;
|
||||
|
||||
error_exit:
|
||||
|
@ -1509,7 +1502,7 @@ std::string do_libdivecomputer_import(device_data_t *data)
|
|||
|
||||
dc_device_close(data->device);
|
||||
data->device = NULL;
|
||||
if (!data->log->dives->nr)
|
||||
if (data->log->dives.empty())
|
||||
dev_info(data, translate("gettextFromC", "No new dives downloaded from dive computer"));
|
||||
}
|
||||
dc_iostream_close(data->iostream);
|
||||
|
|
|
@ -131,7 +131,7 @@ static int handle_event_ver3(int code, const unsigned char *ps, unsigned int ps_
|
|||
return skip;
|
||||
}
|
||||
|
||||
static void parse_dives(int log_version, const unsigned char *buf, unsigned int buf_size, struct dive_table *table, dive_site_table &sites)
|
||||
static void parse_dives(int log_version, const unsigned char *buf, unsigned int buf_size, struct dive_table &table, dive_site_table &sites)
|
||||
{
|
||||
unsigned int ptr = 0;
|
||||
unsigned char model;
|
||||
|
@ -407,8 +407,7 @@ static void parse_dives(int log_version, const unsigned char *buf, unsigned int
|
|||
}
|
||||
|
||||
// End dive
|
||||
record_dive_to_table(dive.release(), table);
|
||||
dive = NULL;
|
||||
table.record_dive(std::move(dive));
|
||||
|
||||
// Advance ptr for next dive
|
||||
ptr += ps_ptr + 4;
|
||||
|
@ -438,7 +437,7 @@ int try_to_open_liquivision(const char *, std::string &mem, struct divelog *log)
|
|||
}
|
||||
ptr += 4;
|
||||
|
||||
parse_dives(log_version, buf + ptr, buf_size - ptr, log->dives.get(), *log->sites);
|
||||
parse_dives(log_version, buf + ptr, buf_size - ptr, log->dives, *log->sites);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -1390,7 +1390,7 @@ static void finish_active_trip(struct git_parser_state *state)
|
|||
static void finish_active_dive(struct git_parser_state *state)
|
||||
{
|
||||
if (state->active_dive)
|
||||
record_dive_to_table(state->active_dive.release(), state->log->dives.get());
|
||||
state->log->dives.record_dive(std::move(state->active_dive));
|
||||
}
|
||||
|
||||
static void create_new_dive(timestamp_t when, struct git_parser_state *state)
|
||||
|
|
|
@ -169,6 +169,5 @@ void ostctools_import(const char *file, struct divelog *log)
|
|||
else if (it == ostcdive->dcs[0].extra_data.end())
|
||||
add_extra_data(&ostcdive->dcs[0], "Serial", ostcdive->dcs[0].serial);
|
||||
|
||||
record_dive_to_table(ostcdive.release(), log->dives.get());
|
||||
sort_dive_table(log->dives.get());
|
||||
log->dives.record_dive(std::move(ostcdive));
|
||||
}
|
||||
|
|
|
@ -124,6 +124,7 @@ public:
|
|||
this->insert(it, std::move(item));
|
||||
return { ptr, idx };
|
||||
}
|
||||
|
||||
// Optimized version of get_idx(), which uses binary search
|
||||
// If not found, fall back to linear search and emit a warning.
|
||||
// Note: this is probaly slower than a linesr search. But for now,
|
||||
|
@ -140,6 +141,15 @@ public:
|
|||
}
|
||||
return it - this->begin();
|
||||
}
|
||||
|
||||
// Get place where insertion would take place
|
||||
size_t get_insertion_index(const T *item) const {
|
||||
auto it = std::lower_bound(this->begin(), this->end(), item,
|
||||
[] (const auto &i1, const auto &i2)
|
||||
{ return CMP(*i1, *i2) < 0; });
|
||||
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
|
||||
|
@ -152,6 +162,7 @@ public:
|
|||
}
|
||||
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; });
|
||||
}
|
||||
|
|
|
@ -31,14 +31,6 @@ struct divecomputer *get_dc(struct parser_state *state)
|
|||
return state->cur_dc ?: &state->cur_dive->dcs[0];
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a dive into the dive_table array
|
||||
*/
|
||||
void record_dive_to_table(struct dive *dive, struct dive_table *table)
|
||||
{
|
||||
add_to_dive_table(table, table->nr, fixup_dive(dive));
|
||||
}
|
||||
|
||||
void start_match(const char *type, const char *name, char *buffer)
|
||||
{
|
||||
if (verbose > 2)
|
||||
|
@ -270,7 +262,12 @@ void dive_end(struct parser_state *state)
|
|||
if (is_dive(state)) {
|
||||
if (state->cur_trip)
|
||||
add_dive_to_trip(state->cur_dive.get(), state->cur_trip.get());
|
||||
record_dive_to_table(state->cur_dive.release(), state->log->dives.get());
|
||||
// Note: we add dives in an unsorted way. The caller of the parsing
|
||||
// function must sort dives.
|
||||
fixup_dive(state->cur_dive.get());
|
||||
state->log->dives.push_back(std::move(state->cur_dive));
|
||||
// This would add dives in a sorted way:
|
||||
// state->log->dives.record_dive(std::move(state->cur_dive));
|
||||
}
|
||||
state->cur_dive.reset();
|
||||
state->cur_dc = NULL;
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include "picture.h"
|
||||
#include "dive.h"
|
||||
#include "divelist.h"
|
||||
#include "divelog.h"
|
||||
#if !defined(SUBSURFACE_MOBILE)
|
||||
#include "metadata.h"
|
||||
#endif
|
||||
|
@ -30,11 +32,11 @@ int get_picture_idx(const picture_table &t, const std::string &filename)
|
|||
|
||||
#if !defined(SUBSURFACE_MOBILE)
|
||||
/* Return distance of timestamp to time of dive. Result is always positive, 0 means during dive. */
|
||||
static timestamp_t time_from_dive(const struct dive *d, timestamp_t timestamp)
|
||||
static timestamp_t time_from_dive(const struct dive &d, timestamp_t timestamp)
|
||||
{
|
||||
timestamp_t end_time = d->endtime();
|
||||
if (timestamp < d->when)
|
||||
return d->when - timestamp;
|
||||
timestamp_t end_time = d.endtime();
|
||||
if (timestamp < d.when)
|
||||
return d.when - timestamp;
|
||||
else if (timestamp > end_time)
|
||||
return timestamp - end_time;
|
||||
else
|
||||
|
@ -44,16 +46,15 @@ static timestamp_t time_from_dive(const struct dive *d, timestamp_t timestamp)
|
|||
/* Return dive closest selected dive to given timestamp or NULL if no dives are selected. */
|
||||
static struct dive *nearest_selected_dive(timestamp_t timestamp)
|
||||
{
|
||||
struct dive *d, *res = NULL;
|
||||
int i;
|
||||
timestamp_t offset, min = 0;
|
||||
struct dive *res = NULL;
|
||||
timestamp_t min = 0;
|
||||
|
||||
for_each_dive(i, d) {
|
||||
for (auto &d: divelog.dives) {
|
||||
if (!d->selected)
|
||||
continue;
|
||||
offset = time_from_dive(d, timestamp);
|
||||
timestamp_t offset = time_from_dive(*d, timestamp);
|
||||
if (!res || offset < min) {
|
||||
res = d;
|
||||
res = d.get();
|
||||
min = offset;
|
||||
}
|
||||
|
||||
|
@ -71,7 +72,7 @@ static struct dive *nearest_selected_dive(timestamp_t timestamp)
|
|||
// only add pictures that have timestamps between 30 minutes before the dive and
|
||||
// 30 minutes after the dive ends
|
||||
static constexpr timestamp_t d30min = 30 * 60;
|
||||
static bool dive_check_picture_time(const struct dive *d, timestamp_t timestamp)
|
||||
static bool dive_check_picture_time(const struct dive &d, timestamp_t timestamp)
|
||||
{
|
||||
return time_from_dive(d, timestamp) < d30min;
|
||||
}
|
||||
|
@ -93,7 +94,7 @@ std::pair<std::optional<picture>, dive *> create_picture(const std::string &file
|
|||
return { {}, nullptr };
|
||||
if (get_picture_idx(dive->pictures, filename) >= 0)
|
||||
return { {}, nullptr };
|
||||
if (!match_all && !dive_check_picture_time(dive, timestamp))
|
||||
if (!match_all && !dive_check_picture_time(*dive, timestamp))
|
||||
return { {}, nullptr };
|
||||
|
||||
struct picture picture;
|
||||
|
@ -105,12 +106,8 @@ std::pair<std::optional<picture>, dive *> create_picture(const std::string &file
|
|||
|
||||
bool picture_check_valid_time(timestamp_t timestamp, timestamp_t shift_time)
|
||||
{
|
||||
int i;
|
||||
struct dive *dive;
|
||||
|
||||
for_each_dive (i, dive)
|
||||
if (dive->selected && dive_check_picture_time(dive, timestamp + shift_time))
|
||||
return true;
|
||||
return false;
|
||||
return std::any_of(divelog.dives.begin(), divelog.dives.end(),
|
||||
[t = timestamp + shift_time] (auto &d)
|
||||
{ return d->selected && dive_check_picture_time(*d, t); });
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -301,7 +301,7 @@ static void create_dive_from_plan(struct diveplan *diveplan, struct dive *dive,
|
|||
dc->last_manual_time.seconds = last_manual_point;
|
||||
|
||||
#if DEBUG_PLAN & 32
|
||||
save_dive(stdout, dive);
|
||||
save_dive(stdout, *dive);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -988,14 +988,14 @@ static QString get_dive_only_date_string(timestamp_t when)
|
|||
|
||||
QString get_first_dive_date_string()
|
||||
{
|
||||
const dive_table &dives = *divelog.dives;
|
||||
return dives.nr > 0 ? get_dive_only_date_string(dives.dives[0]->when) : gettextFromC::tr("no dives");
|
||||
const dive_table &dives = divelog.dives;
|
||||
return !dives.empty() ? get_dive_only_date_string(dives[0]->when) : gettextFromC::tr("no dives");
|
||||
}
|
||||
|
||||
QString get_last_dive_date_string()
|
||||
{
|
||||
const dive_table &dives = *divelog.dives;
|
||||
return dives.nr > 0 ? get_dive_only_date_string(dives.dives[dives.nr - 1]->when) : gettextFromC::tr("no dives");
|
||||
const dive_table &dives = divelog.dives;
|
||||
return !dives.empty() ? get_dive_only_date_string(dives.back()->when) : gettextFromC::tr("no dives");
|
||||
}
|
||||
|
||||
std::string get_current_date()
|
||||
|
|
|
@ -46,7 +46,7 @@ static void cond_put_format(int cond, struct membuffer *b, const char *fmt, ...)
|
|||
}
|
||||
}
|
||||
|
||||
#define SAVE(str, x) cond_put_format(dive->x, b, str " %d\n", dive->x)
|
||||
#define SAVE(str, x) cond_put_format(dive.x, b, str " %d\n", dive.x)
|
||||
|
||||
static void quote(struct membuffer *b, const char *text)
|
||||
{
|
||||
|
@ -96,12 +96,12 @@ static void show_utf8(struct membuffer *b, const char *prefix, const char *value
|
|||
}
|
||||
}
|
||||
|
||||
static void save_overview(struct membuffer *b, struct dive *dive)
|
||||
static void save_overview(struct membuffer *b, const struct dive &dive)
|
||||
{
|
||||
show_utf8(b, "divemaster ", dive->diveguide.c_str(), "\n");
|
||||
show_utf8(b, "buddy ", dive->buddy.c_str(), "\n");
|
||||
show_utf8(b, "suit ", dive->suit.c_str(), "\n");
|
||||
show_utf8(b, "notes ", dive->notes.c_str(), "\n");
|
||||
show_utf8(b, "divemaster ", dive.diveguide.c_str(), "\n");
|
||||
show_utf8(b, "buddy ", dive.buddy.c_str(), "\n");
|
||||
show_utf8(b, "suit ", dive.suit.c_str(), "\n");
|
||||
show_utf8(b, "notes ", dive.notes.c_str(), "\n");
|
||||
}
|
||||
|
||||
static void save_tags(struct membuffer *b, const tag_list &tags)
|
||||
|
@ -138,9 +138,9 @@ static void put_gasmix(struct membuffer *b, struct gasmix mix)
|
|||
}
|
||||
}
|
||||
|
||||
static void save_cylinder_info(struct membuffer *b, struct dive *dive)
|
||||
static void save_cylinder_info(struct membuffer *b, const struct dive &dive)
|
||||
{
|
||||
for (auto &cyl: dive->cylinders) {
|
||||
for (auto &cyl: dive.cylinders) {
|
||||
int volume = cyl.type.size.mliter;
|
||||
int use = cyl.cylinder_use;
|
||||
|
||||
|
@ -161,9 +161,9 @@ static void save_cylinder_info(struct membuffer *b, struct dive *dive)
|
|||
}
|
||||
}
|
||||
|
||||
static void save_weightsystem_info(struct membuffer *b, const struct dive *dive)
|
||||
static void save_weightsystem_info(struct membuffer *b, const struct dive &dive)
|
||||
{
|
||||
for (auto &ws: dive->weightsystems) {
|
||||
for (auto &ws: dive.weightsystems) {
|
||||
int grams = ws.weight.grams;
|
||||
|
||||
put_string(b, "weightsystem");
|
||||
|
@ -173,12 +173,12 @@ static void save_weightsystem_info(struct membuffer *b, const struct dive *dive)
|
|||
}
|
||||
}
|
||||
|
||||
static void save_dive_temperature(struct membuffer *b, struct dive *dive)
|
||||
static void save_dive_temperature(struct membuffer *b, const struct dive &dive)
|
||||
{
|
||||
if (dive->airtemp.mkelvin != dive->dc_airtemp().mkelvin)
|
||||
put_temperature(b, dive->airtemp, "airtemp ", "°C\n");
|
||||
if (dive->watertemp.mkelvin != dive->dc_watertemp().mkelvin)
|
||||
put_temperature(b, dive->watertemp, "watertemp ", "°C\n");
|
||||
if (dive.airtemp.mkelvin != dive.dc_airtemp().mkelvin)
|
||||
put_temperature(b, dive.airtemp, "airtemp ", "°C\n");
|
||||
if (dive.watertemp.mkelvin != dive.dc_watertemp().mkelvin)
|
||||
put_temperature(b, dive.watertemp, "watertemp ", "°C\n");
|
||||
}
|
||||
|
||||
static void save_depths(struct membuffer *b, const struct divecomputer &dc)
|
||||
|
@ -356,13 +356,13 @@ static void save_sample(struct membuffer *b, const struct sample &sample, struct
|
|||
put_format(b, "\n");
|
||||
}
|
||||
|
||||
static void save_samples(struct membuffer *b, struct dive *dive, const struct divecomputer &dc)
|
||||
static void save_samples(struct membuffer *b, const struct dive &dive, const struct divecomputer &dc)
|
||||
{
|
||||
int o2sensor;
|
||||
struct sample dummy;
|
||||
|
||||
/* Is this a CCR dive with the old-style "o2pressure" sensor? */
|
||||
o2sensor = legacy_format_o2pressures(dive, &dc);
|
||||
o2sensor = legacy_format_o2pressures(&dive, &dc);
|
||||
if (o2sensor >= 0) {
|
||||
dummy.sensor[0] = !o2sensor;
|
||||
dummy.sensor[1] = o2sensor;
|
||||
|
@ -372,7 +372,7 @@ static void save_samples(struct membuffer *b, struct dive *dive, const struct di
|
|||
save_sample(b, s, dummy, o2sensor);
|
||||
}
|
||||
|
||||
static void save_one_event(struct membuffer *b, struct dive *dive, const struct event &ev)
|
||||
static void save_one_event(struct membuffer *b, const struct dive &dive, const struct event &ev)
|
||||
{
|
||||
put_format(b, "event %d:%02d", FRACTION_TUPLE(ev.time.seconds, 60));
|
||||
show_index(b, ev.type, "type=", "");
|
||||
|
@ -384,7 +384,7 @@ static void save_one_event(struct membuffer *b, struct dive *dive, const struct
|
|||
show_index(b, ev.value, "value=", "");
|
||||
show_utf8(b, " name=", ev.name.c_str(), "");
|
||||
if (ev.is_gaschange()) {
|
||||
struct gasmix mix = get_gasmix_from_event(dive, ev);
|
||||
struct gasmix mix = get_gasmix_from_event(&dive, ev);
|
||||
if (ev.gas.index >= 0)
|
||||
show_integer(b, ev.gas.index, "cylinder=", "");
|
||||
put_gasmix(b, mix);
|
||||
|
@ -392,13 +392,13 @@ static void save_one_event(struct membuffer *b, struct dive *dive, const struct
|
|||
put_string(b, "\n");
|
||||
}
|
||||
|
||||
static void save_events(struct membuffer *b, struct dive *dive, const struct divecomputer &dc)
|
||||
static void save_events(struct membuffer *b, const struct dive &dive, const struct divecomputer &dc)
|
||||
{
|
||||
for (auto &ev: dc.events)
|
||||
save_one_event(b, dive, ev);
|
||||
}
|
||||
|
||||
static void save_dc(struct membuffer *b, struct dive *dive, const struct divecomputer &dc)
|
||||
static void save_dc(struct membuffer *b, const struct dive &dive, const struct divecomputer &dc)
|
||||
{
|
||||
show_utf8(b, "model ", dc.model.c_str(), "\n");
|
||||
if (dc.last_manual_time.seconds)
|
||||
|
@ -407,9 +407,9 @@ static void save_dc(struct membuffer *b, struct dive *dive, const struct divecom
|
|||
put_format(b, "deviceid %08x\n", dc.deviceid);
|
||||
if (dc.diveid)
|
||||
put_format(b, "diveid %08x\n", dc.diveid);
|
||||
if (dc.when && dc.when != dive->when)
|
||||
if (dc.when && dc.when != dive.when)
|
||||
show_date(b, dc.when);
|
||||
if (dc.duration.seconds && dc.duration.seconds != dive->dcs[0].duration.seconds)
|
||||
if (dc.duration.seconds && dc.duration.seconds != dive.dcs[0].duration.seconds)
|
||||
put_duration(b, dc.duration, "duration ", "min\n");
|
||||
if (dc.divemode != OC) {
|
||||
put_format(b, "dctype %s\n", divemode_text[dc.divemode]);
|
||||
|
@ -431,28 +431,28 @@ static void save_dc(struct membuffer *b, struct dive *dive, const struct divecom
|
|||
* Note that we don't save the date and time or dive
|
||||
* number: they are encoded in the filename.
|
||||
*/
|
||||
static void create_dive_buffer(struct dive *dive, struct membuffer *b)
|
||||
static void create_dive_buffer(const struct dive &dive, struct membuffer *b)
|
||||
{
|
||||
pressure_t surface_pressure = un_fixup_surface_pressure(dive);
|
||||
if (dive->dcs[0].duration.seconds > 0)
|
||||
put_format(b, "duration %u:%02u min\n", FRACTION_TUPLE(dive->dcs[0].duration.seconds, 60));
|
||||
pressure_t surface_pressure = un_fixup_surface_pressure(&dive);
|
||||
if (dive.dcs[0].duration.seconds > 0)
|
||||
put_format(b, "duration %u:%02u min\n", FRACTION_TUPLE(dive.dcs[0].duration.seconds, 60));
|
||||
SAVE("rating", rating);
|
||||
SAVE("visibility", visibility);
|
||||
SAVE("wavesize", wavesize);
|
||||
SAVE("current", current);
|
||||
SAVE("surge", surge);
|
||||
SAVE("chill", chill);
|
||||
if (dive->user_salinity)
|
||||
put_format(b, "watersalinity %d g/l\n", (int)(dive->user_salinity/10));
|
||||
if (dive.user_salinity)
|
||||
put_format(b, "watersalinity %d g/l\n", (int)(dive.user_salinity/10));
|
||||
if (surface_pressure.mbar)
|
||||
SAVE("airpressure", surface_pressure.mbar);
|
||||
cond_put_format(dive->notrip, b, "notrip\n");
|
||||
cond_put_format(dive->invalid, b, "invalid\n");
|
||||
save_tags(b, dive->tags);
|
||||
if (dive->dive_site)
|
||||
put_format(b, "divesiteid %08x\n", dive->dive_site->uuid);
|
||||
if (verbose && dive->dive_site)
|
||||
report_info("removed reference to non-existant dive site with uuid %08x\n", dive->dive_site->uuid);
|
||||
cond_put_format(dive.notrip, b, "notrip\n");
|
||||
cond_put_format(dive.invalid, b, "invalid\n");
|
||||
save_tags(b, dive.tags);
|
||||
if (dive.dive_site)
|
||||
put_format(b, "divesiteid %08x\n", dive.dive_site->uuid);
|
||||
if (verbose && dive.dive_site)
|
||||
report_info("removed reference to non-existant dive site with uuid %08x\n", dive.dive_site->uuid);
|
||||
save_overview(b, dive);
|
||||
save_cylinder_info(b, dive);
|
||||
save_weightsystem_info(b, dive);
|
||||
|
@ -565,12 +565,12 @@ static struct dir *mktree(git_repository *repo, struct dir *dir, const char *fmt
|
|||
* We do *not* want to use localized weekdays and cause peoples save
|
||||
* formats to depend on their locale.
|
||||
*/
|
||||
static void create_dive_name(struct dive *dive, struct membuffer *name, struct tm *dirtm)
|
||||
static void create_dive_name(struct dive &dive, struct membuffer *name, struct tm *dirtm)
|
||||
{
|
||||
struct tm tm;
|
||||
static const char weekday[7][4] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
|
||||
|
||||
utc_mkdate(dive->when, &tm);
|
||||
utc_mkdate(dive.when, &tm);
|
||||
if (tm.tm_year != dirtm->tm_year)
|
||||
put_format(name, "%04u-", tm.tm_year);
|
||||
if (tm.tm_mon != dirtm->tm_mon)
|
||||
|
@ -600,7 +600,7 @@ static int blob_insert(git_repository *repo, struct dir *tree, struct membuffer
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int save_one_divecomputer(git_repository *repo, struct dir *tree, struct dive *dive, const struct divecomputer &dc, int idx)
|
||||
static int save_one_divecomputer(git_repository *repo, struct dir *tree, const struct dive &dive, const struct divecomputer &dc, int idx)
|
||||
{
|
||||
int ret;
|
||||
membuffer buf;
|
||||
|
@ -635,17 +635,17 @@ static int save_one_picture(git_repository *repo, struct dir *dir, const struct
|
|||
sign, h, FRACTION_TUPLE(offset, 60));
|
||||
}
|
||||
|
||||
static int save_pictures(git_repository *repo, struct dir *dir, struct dive *dive)
|
||||
static int save_pictures(git_repository *repo, struct dir *dir, const struct dive &dive)
|
||||
{
|
||||
if (!dive->pictures.empty()) {
|
||||
if (!dive.pictures.empty()) {
|
||||
dir = mktree(repo, dir, "Pictures");
|
||||
for (auto &picture: dive->pictures)
|
||||
for (auto &picture: dive.pictures)
|
||||
save_one_picture(repo, dir, picture);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int save_one_dive(git_repository *repo, struct dir *tree, struct dive *dive, struct tm *tm, bool cached_ok)
|
||||
static int save_one_dive(git_repository *repo, struct dir *tree, struct dive &dive, struct tm *tm, bool cached_ok)
|
||||
{
|
||||
membuffer buf, name;
|
||||
struct dir *subdir;
|
||||
|
@ -658,9 +658,9 @@ static int save_one_dive(git_repository *repo, struct dir *tree, struct dive *di
|
|||
* If the dive git ID is valid, we just create the whole directory
|
||||
* with that ID
|
||||
*/
|
||||
if (cached_ok && dive_cache_is_valid(dive)) {
|
||||
if (cached_ok && dive_cache_is_valid(&dive)) {
|
||||
git_oid oid;
|
||||
git_oid_fromraw(&oid, dive->git_id);
|
||||
git_oid_fromraw(&oid, dive.git_id);
|
||||
ret = tree_insert(tree->files, mb_cstring(&name), 1,
|
||||
&oid, GIT_FILEMODE_TREE);
|
||||
if (ret)
|
||||
|
@ -672,7 +672,7 @@ static int save_one_dive(git_repository *repo, struct dir *tree, struct dive *di
|
|||
subdir->unique = true;
|
||||
|
||||
create_dive_buffer(dive, &buf);
|
||||
nr = dive->number;
|
||||
nr = dive.number;
|
||||
ret = blob_insert(repo, subdir, &buf,
|
||||
"Dive%c%d", nr ? '-' : 0, nr);
|
||||
if (ret)
|
||||
|
@ -683,8 +683,8 @@ static int save_one_dive(git_repository *repo, struct dir *tree, struct dive *di
|
|||
* computer, use index 0 for that (which disables the index
|
||||
* generation when naming it).
|
||||
*/
|
||||
nr = dive->dcs.size() > 1 ? 1 : 0;
|
||||
for (auto &dc: dive->dcs)
|
||||
nr = dive.dcs.size() > 1 ? 1 : 0;
|
||||
for (auto &dc: dive.dcs)
|
||||
save_one_divecomputer(repo, subdir, dive, dc, nr++);
|
||||
|
||||
/* Save the picture data, if any */
|
||||
|
@ -782,8 +782,6 @@ static void verify_shared_date(timestamp_t when, struct tm *tm)
|
|||
|
||||
static int save_one_trip(git_repository *repo, struct dir *tree, dive_trip *trip, struct tm *tm, bool cached_ok)
|
||||
{
|
||||
int i;
|
||||
struct dive *dive;
|
||||
struct dir *subdir;
|
||||
membuffer name;
|
||||
timestamp_t first, last;
|
||||
|
@ -799,7 +797,7 @@ static int save_one_trip(git_repository *repo, struct dir *tree, dive_trip *trip
|
|||
/* Make sure we write out the dates to the dives consistently */
|
||||
first = MAX_TIMESTAMP;
|
||||
last = MIN_TIMESTAMP;
|
||||
for_each_dive(i, dive) {
|
||||
for (auto &dive: divelog.dives) {
|
||||
if (dive->divetrip != trip)
|
||||
continue;
|
||||
if (dive->when < first)
|
||||
|
@ -811,9 +809,9 @@ static int save_one_trip(git_repository *repo, struct dir *tree, dive_trip *trip
|
|||
verify_shared_date(last, tm);
|
||||
|
||||
/* Save each dive in the directory */
|
||||
for_each_dive(i, dive) {
|
||||
for (auto &dive: divelog.dives) {
|
||||
if (dive->divetrip == trip)
|
||||
save_one_dive(repo, subdir, dive, tm, cached_ok);
|
||||
save_one_dive(repo, subdir, *dive, tm, cached_ok);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -981,9 +979,6 @@ static void save_filter_presets(git_repository *repo, struct dir *tree)
|
|||
|
||||
static int create_git_tree(git_repository *repo, struct dir *root, bool select_only, bool cached_ok)
|
||||
{
|
||||
int i;
|
||||
struct dive *dive;
|
||||
|
||||
git_storage_update_progress(translate("gettextFromC", "Start saving data"));
|
||||
save_settings(repo, root);
|
||||
|
||||
|
@ -995,7 +990,7 @@ static int create_git_tree(git_repository *repo, struct dir *root, bool select_o
|
|||
|
||||
/* save the dives */
|
||||
git_storage_update_progress(translate("gettextFromC", "Start saving dives"));
|
||||
for_each_dive(i, dive) {
|
||||
for (auto &dive: divelog.dives) {
|
||||
struct tm tm;
|
||||
struct dir *tree;
|
||||
|
||||
|
@ -1024,7 +1019,7 @@ static int create_git_tree(git_repository *repo, struct dir *root, bool select_o
|
|||
continue;
|
||||
}
|
||||
|
||||
save_one_dive(repo, tree, dive, &tm, cached_ok);
|
||||
save_one_dive(repo, tree, *dive, &tm, cached_ok);
|
||||
}
|
||||
git_storage_update_progress(translate("gettextFromC", "Done creating local cache"));
|
||||
return 0;
|
||||
|
@ -1095,7 +1090,7 @@ int get_authorship(git_repository *repo, git_signature **authorp)
|
|||
|
||||
static void create_commit_message(struct membuffer *msg, bool create_empty)
|
||||
{
|
||||
int nr = divelog.dives->nr;
|
||||
int nr = static_cast<int>(divelog.dives.size());
|
||||
struct dive *dive = get_dive(nr-1);
|
||||
std::string changes_made = get_changes_made();
|
||||
|
||||
|
|
|
@ -43,13 +43,13 @@ static void copy_image_and_overwrite(const std::string &cfileName, const std::st
|
|||
report_info("copy of %s to %s failed", cfileName.c_str(), newName.c_str());
|
||||
}
|
||||
|
||||
static void save_photos(struct membuffer *b, const char *photos_dir, const struct dive *dive)
|
||||
static void save_photos(struct membuffer *b, const char *photos_dir, const struct dive &dive)
|
||||
{
|
||||
if (dive->pictures.empty())
|
||||
if (dive.pictures.empty())
|
||||
return;
|
||||
|
||||
const char *separator = "\"photos\":[";
|
||||
for (auto &picture: dive->pictures) {
|
||||
for (auto &picture: dive.pictures) {
|
||||
put_string(b, separator);
|
||||
separator = ", ";
|
||||
std::string fname = get_file_name(local_file_path(picture));
|
||||
|
@ -61,11 +61,11 @@ static void save_photos(struct membuffer *b, const char *photos_dir, const struc
|
|||
put_string(b, "],");
|
||||
}
|
||||
|
||||
static void write_divecomputers(struct membuffer *b, const struct dive *dive)
|
||||
static void write_divecomputers(struct membuffer *b, const struct dive &dive)
|
||||
{
|
||||
put_string(b, "\"divecomputers\":[");
|
||||
const char *separator = "";
|
||||
for (auto &dc: dive->dcs) {
|
||||
for (auto &dc: dive.dcs) {
|
||||
put_string(b, separator);
|
||||
separator = ", ";
|
||||
put_format(b, "{");
|
||||
|
@ -83,17 +83,17 @@ static void write_divecomputers(struct membuffer *b, const struct dive *dive)
|
|||
put_string(b, "],");
|
||||
}
|
||||
|
||||
static void write_dive_status(struct membuffer *b, const struct dive *dive)
|
||||
static void write_dive_status(struct membuffer *b, const struct dive &dive)
|
||||
{
|
||||
put_format(b, "\"sac\":\"%d\",", dive->sac);
|
||||
put_format(b, "\"otu\":\"%d\",", dive->otu);
|
||||
put_format(b, "\"cns\":\"%d\",", dive->cns);
|
||||
put_format(b, "\"sac\":\"%d\",", dive.sac);
|
||||
put_format(b, "\"otu\":\"%d\",", dive.otu);
|
||||
put_format(b, "\"cns\":\"%d\",", dive.cns);
|
||||
}
|
||||
|
||||
static void put_HTML_bookmarks(struct membuffer *b, const struct dive *dive)
|
||||
static void put_HTML_bookmarks(struct membuffer *b, const struct dive &dive)
|
||||
{
|
||||
const char *separator = "\"events\":[";
|
||||
for (const auto &ev: dive->dcs[0].events) {
|
||||
for (const auto &ev: dive.dcs[0].events) {
|
||||
put_string(b, separator);
|
||||
separator = ", ";
|
||||
put_string(b, "{\"name\":\"");
|
||||
|
@ -106,13 +106,13 @@ static void put_HTML_bookmarks(struct membuffer *b, const struct dive *dive)
|
|||
put_string(b, "],");
|
||||
}
|
||||
|
||||
static void put_weightsystem_HTML(struct membuffer *b, const struct dive *dive)
|
||||
static void put_weightsystem_HTML(struct membuffer *b, const struct dive &dive)
|
||||
{
|
||||
put_string(b, "\"Weights\":[");
|
||||
|
||||
const char *separator = "";
|
||||
|
||||
for (auto &ws: dive->weightsystems) {
|
||||
for (auto &ws: dive.weightsystems) {
|
||||
int grams = ws.weight.grams;
|
||||
|
||||
put_string(b, separator);
|
||||
|
@ -125,14 +125,14 @@ static void put_weightsystem_HTML(struct membuffer *b, const struct dive *dive)
|
|||
put_string(b, "],");
|
||||
}
|
||||
|
||||
static void put_cylinder_HTML(struct membuffer *b, const struct dive *dive)
|
||||
static void put_cylinder_HTML(struct membuffer *b, const struct dive &dive)
|
||||
{
|
||||
const char *separator = "\"Cylinders\":[";
|
||||
|
||||
if (dive->cylinders.empty())
|
||||
if (dive.cylinders.empty())
|
||||
put_string(b, separator);
|
||||
|
||||
for (auto &cyl: dive->cylinders) {
|
||||
for (auto &cyl: dive.cylinders) {
|
||||
put_format(b, "%s{", separator);
|
||||
separator = ", ";
|
||||
write_attribute(b, "Type", cyl.type.description.c_str(), ", ");
|
||||
|
@ -172,25 +172,25 @@ static void put_cylinder_HTML(struct membuffer *b, const struct dive *dive)
|
|||
}
|
||||
|
||||
|
||||
static void put_HTML_samples(struct membuffer *b, const struct dive *dive)
|
||||
static void put_HTML_samples(struct membuffer *b, const struct dive &dive)
|
||||
{
|
||||
put_format(b, "\"maxdepth\":%d,", dive->dcs[0].maxdepth.mm);
|
||||
put_format(b, "\"duration\":%d,", dive->dcs[0].duration.seconds);
|
||||
put_format(b, "\"maxdepth\":%d,", dive.dcs[0].maxdepth.mm);
|
||||
put_format(b, "\"duration\":%d,", dive.dcs[0].duration.seconds);
|
||||
|
||||
if (dive->dcs[0].samples.empty())
|
||||
if (dive.dcs[0].samples.empty())
|
||||
return;
|
||||
|
||||
const char *separator = "\"samples\":[";
|
||||
for (auto &s: dive->dcs[0].samples) {
|
||||
for (auto &s: dive.dcs[0].samples) {
|
||||
put_format(b, "%s[%d,%d,%d,%d]", separator, s.time.seconds, s.depth.mm, s.pressure[0].mbar, s.temperature.mkelvin);
|
||||
separator = ", ";
|
||||
}
|
||||
put_string(b, "],");
|
||||
}
|
||||
|
||||
static void put_HTML_coordinates(struct membuffer *b, const struct dive *dive)
|
||||
static void put_HTML_coordinates(struct membuffer *b, const struct dive &dive)
|
||||
{
|
||||
struct dive_site *ds = get_dive_site_for_dive(dive);
|
||||
struct dive_site *ds = get_dive_site_for_dive(&dive);
|
||||
if (!ds)
|
||||
return;
|
||||
degrees_t latitude = ds->location.lat;
|
||||
|
@ -206,10 +206,10 @@ static void put_HTML_coordinates(struct membuffer *b, const struct dive *dive)
|
|||
put_string(b, "},");
|
||||
}
|
||||
|
||||
void put_HTML_date(struct membuffer *b, const struct dive *dive, const char *pre, const char *post)
|
||||
void put_HTML_date(struct membuffer *b, const struct dive &dive, const char *pre, const char *post)
|
||||
{
|
||||
struct tm tm;
|
||||
utc_mkdate(dive->when, &tm);
|
||||
utc_mkdate(dive.when, &tm);
|
||||
put_format(b, "%s%04u-%02u-%02u%s", pre, tm.tm_year, tm.tm_mon + 1, tm.tm_mday, post);
|
||||
}
|
||||
|
||||
|
@ -219,11 +219,11 @@ void put_HTML_quoted(struct membuffer *b, const char *text)
|
|||
put_quoted(b, text, is_attribute, is_html);
|
||||
}
|
||||
|
||||
void put_HTML_notes(struct membuffer *b, const struct dive *dive, const char *pre, const char *post)
|
||||
void put_HTML_notes(struct membuffer *b, const struct dive &dive, const char *pre, const char *post)
|
||||
{
|
||||
put_string(b, pre);
|
||||
if (!dive->notes.empty())
|
||||
put_HTML_quoted(b, dive->notes.c_str());
|
||||
if (!dive.notes.empty())
|
||||
put_HTML_quoted(b, dive.notes.c_str());
|
||||
else
|
||||
put_string(b, "--");
|
||||
put_string(b, post);
|
||||
|
@ -263,24 +263,24 @@ void put_HTML_weight_units(struct membuffer *b, unsigned int grams, const char *
|
|||
put_format(b, "%s%.1f %s%s", pre, value, unit, post);
|
||||
}
|
||||
|
||||
void put_HTML_time(struct membuffer *b, const struct dive *dive, const char *pre, const char *post)
|
||||
void put_HTML_time(struct membuffer *b, const struct dive &dive, const char *pre, const char *post)
|
||||
{
|
||||
struct tm tm;
|
||||
utc_mkdate(dive->when, &tm);
|
||||
utc_mkdate(dive.when, &tm);
|
||||
put_format(b, "%s%02u:%02u:%02u%s", pre, tm.tm_hour, tm.tm_min, tm.tm_sec, post);
|
||||
}
|
||||
|
||||
void put_HTML_depth(struct membuffer *b, const struct dive *dive, const char *pre, const char *post)
|
||||
void put_HTML_depth(struct membuffer *b, const struct dive &dive, const char *pre, const char *post)
|
||||
{
|
||||
const char *unit;
|
||||
double value;
|
||||
const struct units *units_p = get_units();
|
||||
|
||||
if (!dive->maxdepth.mm) {
|
||||
if (!dive.maxdepth.mm) {
|
||||
put_format(b, "%s--%s", pre, post);
|
||||
return;
|
||||
}
|
||||
value = get_depth_units(dive->maxdepth.mm, NULL, &unit);
|
||||
value = get_depth_units(dive.maxdepth.mm, NULL, &unit);
|
||||
|
||||
switch (units_p->length) {
|
||||
case units::METERS:
|
||||
|
@ -293,41 +293,41 @@ void put_HTML_depth(struct membuffer *b, const struct dive *dive, const char *pr
|
|||
}
|
||||
}
|
||||
|
||||
void put_HTML_airtemp(struct membuffer *b, const struct dive *dive, const char *pre, const char *post)
|
||||
void put_HTML_airtemp(struct membuffer *b, const struct dive &dive, const char *pre, const char *post)
|
||||
{
|
||||
const char *unit;
|
||||
double value;
|
||||
|
||||
if (!dive->airtemp.mkelvin) {
|
||||
if (!dive.airtemp.mkelvin) {
|
||||
put_format(b, "%s--%s", pre, post);
|
||||
return;
|
||||
}
|
||||
value = get_temp_units(dive->airtemp.mkelvin, &unit);
|
||||
value = get_temp_units(dive.airtemp.mkelvin, &unit);
|
||||
put_format(b, "%s%.1f %s%s", pre, value, unit, post);
|
||||
}
|
||||
|
||||
void put_HTML_watertemp(struct membuffer *b, const struct dive *dive, const char *pre, const char *post)
|
||||
void put_HTML_watertemp(struct membuffer *b, const struct dive &dive, const char *pre, const char *post)
|
||||
{
|
||||
const char *unit;
|
||||
double value;
|
||||
|
||||
if (!dive->watertemp.mkelvin) {
|
||||
if (!dive.watertemp.mkelvin) {
|
||||
put_format(b, "%s--%s", pre, post);
|
||||
return;
|
||||
}
|
||||
value = get_temp_units(dive->watertemp.mkelvin, &unit);
|
||||
value = get_temp_units(dive.watertemp.mkelvin, &unit);
|
||||
put_format(b, "%s%.1f %s%s", pre, value, unit, post);
|
||||
}
|
||||
|
||||
static void put_HTML_tags(struct membuffer *b, const struct dive *dive, const char *pre, const char *post)
|
||||
static void put_HTML_tags(struct membuffer *b, const struct dive &dive, const char *pre, const char *post)
|
||||
{
|
||||
put_string(b, pre);
|
||||
|
||||
if (dive->tags.empty())
|
||||
if (dive.tags.empty())
|
||||
put_string(b, "[\"--\"");
|
||||
|
||||
const char *separator = "[";
|
||||
for (const divetag *tag: dive->tags) {
|
||||
for (const divetag *tag: dive.tags) {
|
||||
put_format(b, "%s\"", separator);
|
||||
separator = ", ";
|
||||
put_HTML_quoted(b, tag->name.c_str());
|
||||
|
@ -338,30 +338,30 @@ static void put_HTML_tags(struct membuffer *b, const struct dive *dive, const ch
|
|||
}
|
||||
|
||||
/* if exporting list_only mode, we neglect exporting the samples, bookmarks and cylinders */
|
||||
static void write_one_dive(struct membuffer *b, const struct dive *dive, const char *photos_dir, int *dive_no, bool list_only)
|
||||
static void write_one_dive(struct membuffer *b, const struct dive &dive, const char *photos_dir, int *dive_no, bool list_only)
|
||||
{
|
||||
put_string(b, "{");
|
||||
put_format(b, "\"number\":%d,", *dive_no);
|
||||
put_format(b, "\"subsurface_number\":%d,", dive->number);
|
||||
put_format(b, "\"subsurface_number\":%d,", dive.number);
|
||||
put_HTML_date(b, dive, "\"date\":\"", "\",");
|
||||
put_HTML_time(b, dive, "\"time\":\"", "\",");
|
||||
write_attribute(b, "location", get_dive_location(dive).c_str(), ", ");
|
||||
write_attribute(b, "location", get_dive_location(&dive).c_str(), ", ");
|
||||
put_HTML_coordinates(b, dive);
|
||||
put_format(b, "\"rating\":%d,", dive->rating);
|
||||
put_format(b, "\"visibility\":%d,", dive->visibility);
|
||||
put_format(b, "\"current\":%d,", dive->current);
|
||||
put_format(b, "\"wavesize\":%d,", dive->wavesize);
|
||||
put_format(b, "\"surge\":%d,", dive->surge);
|
||||
put_format(b, "\"chill\":%d,", dive->chill);
|
||||
put_format(b, "\"rating\":%d,", dive.rating);
|
||||
put_format(b, "\"visibility\":%d,", dive.visibility);
|
||||
put_format(b, "\"current\":%d,", dive.current);
|
||||
put_format(b, "\"wavesize\":%d,", dive.wavesize);
|
||||
put_format(b, "\"surge\":%d,", dive.surge);
|
||||
put_format(b, "\"chill\":%d,", dive.chill);
|
||||
put_format(b, "\"dive_duration\":\"%u:%02u min\",",
|
||||
FRACTION_TUPLE(dive->duration.seconds, 60));
|
||||
FRACTION_TUPLE(dive.duration.seconds, 60));
|
||||
put_string(b, "\"temperature\":{");
|
||||
put_HTML_airtemp(b, dive, "\"air\":\"", "\",");
|
||||
put_HTML_watertemp(b, dive, "\"water\":\"", "\"");
|
||||
put_string(b, " },");
|
||||
write_attribute(b, "buddy", dive->buddy.c_str(), ", ");
|
||||
write_attribute(b, "diveguide", dive->diveguide.c_str(), ", ");
|
||||
write_attribute(b, "suit", dive->suit.c_str(), ", ");
|
||||
write_attribute(b, "buddy", dive.buddy.c_str(), ", ");
|
||||
write_attribute(b, "diveguide", dive.diveguide.c_str(), ", ");
|
||||
write_attribute(b, "suit", dive.suit.c_str(), ", ");
|
||||
put_HTML_tags(b, dive, "\"tags\":", ",");
|
||||
if (!list_only) {
|
||||
put_cylinder_HTML(b, dive);
|
||||
|
@ -380,12 +380,10 @@ static void write_one_dive(struct membuffer *b, const struct dive *dive, const c
|
|||
|
||||
static void write_no_trip(struct membuffer *b, int *dive_no, bool selected_only, const char *photos_dir, const bool list_only, char *sep)
|
||||
{
|
||||
int i;
|
||||
const struct dive *dive;
|
||||
const char *separator = "";
|
||||
bool found_sel_dive = 0;
|
||||
|
||||
for_each_dive (i, dive) {
|
||||
for (auto &dive: divelog.dives) {
|
||||
// write dive if it doesn't belong to any trip and the dive is selected
|
||||
// or we are in exporting all dives mode.
|
||||
if (!dive->divetrip && (dive->selected || !selected_only)) {
|
||||
|
@ -398,7 +396,7 @@ static void write_no_trip(struct membuffer *b, int *dive_no, bool selected_only,
|
|||
}
|
||||
put_string(b, separator);
|
||||
separator = ", ";
|
||||
write_one_dive(b, dive, photos_dir, dive_no, list_only);
|
||||
write_one_dive(b, *dive, photos_dir, dive_no, list_only);
|
||||
}
|
||||
}
|
||||
if (found_sel_dive)
|
||||
|
@ -424,7 +422,7 @@ static void write_trip(struct membuffer *b, dive_trip *trip, int *dive_no, bool
|
|||
}
|
||||
put_string(b, separator);
|
||||
separator = ", ";
|
||||
write_one_dive(b, dive, photos_dir, dive_no, list_only);
|
||||
write_one_dive(b, *dive, photos_dir, dive_no, list_only);
|
||||
}
|
||||
|
||||
// close the trip object if contain dives.
|
||||
|
@ -434,15 +432,14 @@ static void write_trip(struct membuffer *b, dive_trip *trip, int *dive_no, bool
|
|||
|
||||
static void write_trips(struct membuffer *b, const char *photos_dir, bool selected_only, const bool list_only)
|
||||
{
|
||||
int i, dive_no = 0;
|
||||
const struct dive *dive;
|
||||
int dive_no = 0;
|
||||
char sep_ = ' ';
|
||||
char *sep = &sep_;
|
||||
|
||||
for (auto &trip: *divelog.trips)
|
||||
trip->saved = 0;
|
||||
|
||||
for_each_dive (i, dive) {
|
||||
for (auto &dive: divelog.dives) {
|
||||
dive_trip *trip = dive->divetrip;
|
||||
|
||||
/*Continue if the dive have no trips or we have seen this trip before*/
|
||||
|
|
|
@ -6,12 +6,12 @@
|
|||
|
||||
struct dive;
|
||||
|
||||
void put_HTML_date(struct membuffer *b, const struct dive *dive, const char *pre, const char *post);
|
||||
void put_HTML_depth(struct membuffer *b, const struct dive *dive, const char *pre, const char *post);
|
||||
void put_HTML_airtemp(struct membuffer *b, const struct dive *dive, const char *pre, const char *post);
|
||||
void put_HTML_watertemp(struct membuffer *b, const struct dive *dive, const char *pre, const char *post);
|
||||
void put_HTML_time(struct membuffer *b, const struct dive *dive, const char *pre, const char *post);
|
||||
void put_HTML_notes(struct membuffer *b, const struct dive *dive, const char *pre, const char *post);
|
||||
void put_HTML_date(struct membuffer *b, const struct dive &dive, const char *pre, const char *post);
|
||||
void put_HTML_depth(struct membuffer *b, const struct dive &dive, const char *pre, const char *post);
|
||||
void put_HTML_airtemp(struct membuffer *b, const struct dive &dive, const char *pre, const char *post);
|
||||
void put_HTML_watertemp(struct membuffer *b, const struct dive &dive, const char *pre, const char *post);
|
||||
void put_HTML_time(struct membuffer *b, const struct dive &dive, const char *pre, const char *post);
|
||||
void put_HTML_notes(struct membuffer *b, const struct dive &dive, const char *pre, const char *post);
|
||||
void put_HTML_quoted(struct membuffer *b, const char *text);
|
||||
void put_HTML_pressure_units(struct membuffer *b, pressure_t pressure, const char *pre, const char *post);
|
||||
void put_HTML_weight_units(struct membuffer *b, unsigned int grams, const char *pre, const char *post);
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#include "core/save-profiledata.h"
|
||||
#include "core/dive.h"
|
||||
#include "core/divelist.h"
|
||||
#include "core/divelog.h"
|
||||
#include "core/profile.h"
|
||||
#include "core/errorhelper.h"
|
||||
#include "core/file.h"
|
||||
|
@ -203,14 +205,12 @@ static void put_st_event(struct membuffer *b, const plot_data &entry, const plot
|
|||
|
||||
static void save_profiles_buffer(struct membuffer *b, bool select_only)
|
||||
{
|
||||
int i;
|
||||
struct dive *dive;
|
||||
struct deco_state *planner_deco_state = NULL;
|
||||
|
||||
for_each_dive(i, dive) {
|
||||
for(auto &dive: divelog.dives) {
|
||||
if (select_only && !dive->selected)
|
||||
continue;
|
||||
plot_info pi = create_plot_info_new(dive, &dive->dcs[0], planner_deco_state);
|
||||
plot_info pi = create_plot_info_new(dive.get(), &dive->dcs[0], planner_deco_state);
|
||||
put_headers(b, pi.nr_cylinders);
|
||||
|
||||
for (int i = 0; i < pi.nr; i++)
|
||||
|
|
|
@ -100,67 +100,67 @@ static void show_utf8_blanked(struct membuffer *b, const char *text, const char
|
|||
show_utf8(b, copy.c_str(), pre, post, is_attribute);
|
||||
}
|
||||
|
||||
static void save_depths(struct membuffer *b, struct divecomputer *dc)
|
||||
static void save_depths(struct membuffer *b, const struct divecomputer &dc)
|
||||
{
|
||||
/* What's the point of this dive entry again? */
|
||||
if (!dc->maxdepth.mm && !dc->meandepth.mm)
|
||||
if (!dc.maxdepth.mm && !dc.meandepth.mm)
|
||||
return;
|
||||
|
||||
put_string(b, " <depth");
|
||||
put_depth(b, dc->maxdepth, " max='", " m'");
|
||||
put_depth(b, dc->meandepth, " mean='", " m'");
|
||||
put_depth(b, dc.maxdepth, " max='", " m'");
|
||||
put_depth(b, dc.meandepth, " mean='", " m'");
|
||||
put_string(b, " />\n");
|
||||
}
|
||||
|
||||
static void save_dive_temperature(struct membuffer *b, struct dive *dive)
|
||||
static void save_dive_temperature(struct membuffer *b, const struct dive &dive)
|
||||
{
|
||||
if (!dive->airtemp.mkelvin && !dive->watertemp.mkelvin)
|
||||
if (!dive.airtemp.mkelvin && !dive.watertemp.mkelvin)
|
||||
return;
|
||||
if (dive->airtemp.mkelvin == dive->dc_airtemp().mkelvin && dive->watertemp.mkelvin == dive->dc_watertemp().mkelvin)
|
||||
if (dive.airtemp.mkelvin == dive.dc_airtemp().mkelvin && dive.watertemp.mkelvin == dive.dc_watertemp().mkelvin)
|
||||
return;
|
||||
|
||||
put_string(b, " <divetemperature");
|
||||
if (dive->airtemp.mkelvin != dive->dc_airtemp().mkelvin)
|
||||
put_temperature(b, dive->airtemp, " air='", " C'");
|
||||
if (dive->watertemp.mkelvin != dive->dc_watertemp().mkelvin)
|
||||
put_temperature(b, dive->watertemp, " water='", " C'");
|
||||
if (dive.airtemp.mkelvin != dive.dc_airtemp().mkelvin)
|
||||
put_temperature(b, dive.airtemp, " air='", " C'");
|
||||
if (dive.watertemp.mkelvin != dive.dc_watertemp().mkelvin)
|
||||
put_temperature(b, dive.watertemp, " water='", " C'");
|
||||
put_string(b, "/>\n");
|
||||
}
|
||||
|
||||
static void save_temperatures(struct membuffer *b, struct divecomputer *dc)
|
||||
static void save_temperatures(struct membuffer *b, const struct divecomputer &dc)
|
||||
{
|
||||
if (!dc->airtemp.mkelvin && !dc->watertemp.mkelvin)
|
||||
if (!dc.airtemp.mkelvin && !dc.watertemp.mkelvin)
|
||||
return;
|
||||
put_string(b, " <temperature");
|
||||
put_temperature(b, dc->airtemp, " air='", " C'");
|
||||
put_temperature(b, dc->watertemp, " water='", " C'");
|
||||
put_temperature(b, dc.airtemp, " air='", " C'");
|
||||
put_temperature(b, dc.watertemp, " water='", " C'");
|
||||
put_string(b, " />\n");
|
||||
}
|
||||
|
||||
static void save_airpressure(struct membuffer *b, struct divecomputer *dc)
|
||||
static void save_airpressure(struct membuffer *b, const struct divecomputer &dc)
|
||||
{
|
||||
if (!dc->surface_pressure.mbar)
|
||||
if (!dc.surface_pressure.mbar)
|
||||
return;
|
||||
put_string(b, " <surface");
|
||||
put_pressure(b, dc->surface_pressure, " pressure='", " bar'");
|
||||
put_pressure(b, dc.surface_pressure, " pressure='", " bar'");
|
||||
put_string(b, " />\n");
|
||||
}
|
||||
|
||||
static void save_salinity(struct membuffer *b, struct divecomputer *dc)
|
||||
static void save_salinity(struct membuffer *b, const struct divecomputer &dc)
|
||||
{
|
||||
if (!dc->salinity)
|
||||
if (!dc.salinity)
|
||||
return;
|
||||
put_string(b, " <water");
|
||||
put_salinity(b, dc->salinity, " salinity='", " g/l'");
|
||||
put_salinity(b, dc.salinity, " salinity='", " g/l'");
|
||||
put_string(b, " />\n");
|
||||
}
|
||||
|
||||
static void save_overview(struct membuffer *b, struct dive *dive, bool anonymize)
|
||||
static void save_overview(struct membuffer *b, const struct dive &dive, bool anonymize)
|
||||
{
|
||||
show_utf8_blanked(b, dive->diveguide.c_str(), " <divemaster>", "</divemaster>\n", 0, anonymize);
|
||||
show_utf8_blanked(b, dive->buddy.c_str(), " <buddy>", "</buddy>\n", 0, anonymize);
|
||||
show_utf8_blanked(b, dive->notes.c_str(), " <notes>", "</notes>\n", 0, anonymize);
|
||||
show_utf8_blanked(b, dive->suit.c_str(), " <suit>", "</suit>\n", 0, anonymize);
|
||||
show_utf8_blanked(b, dive.diveguide.c_str(), " <divemaster>", "</divemaster>\n", 0, anonymize);
|
||||
show_utf8_blanked(b, dive.buddy.c_str(), " <buddy>", "</buddy>\n", 0, anonymize);
|
||||
show_utf8_blanked(b, dive.notes.c_str(), " <notes>", "</notes>\n", 0, anonymize);
|
||||
show_utf8_blanked(b, dive.suit.c_str(), " <suit>", "</suit>\n", 0, anonymize);
|
||||
}
|
||||
|
||||
static void put_gasmix(struct membuffer *b, struct gasmix mix)
|
||||
|
@ -175,9 +175,9 @@ static void put_gasmix(struct membuffer *b, struct gasmix mix)
|
|||
}
|
||||
}
|
||||
|
||||
static void save_cylinder_info(struct membuffer *b, struct dive *dive)
|
||||
static void save_cylinder_info(struct membuffer *b, const struct dive &dive)
|
||||
{
|
||||
for (auto &cyl: dive->cylinders) {
|
||||
for (auto &cyl: dive.cylinders) {
|
||||
int volume = cyl.type.size.mliter;
|
||||
int use = cyl.cylinder_use;
|
||||
|
||||
|
@ -197,9 +197,9 @@ static void save_cylinder_info(struct membuffer *b, struct dive *dive)
|
|||
}
|
||||
}
|
||||
|
||||
static void save_weightsystem_info(struct membuffer *b, const struct dive *dive)
|
||||
static void save_weightsystem_info(struct membuffer *b, const struct dive &dive)
|
||||
{
|
||||
for (auto &ws: dive->weightsystems) {
|
||||
for (auto &ws: dive.weightsystems) {
|
||||
int grams = ws.weight.grams;
|
||||
|
||||
put_format(b, " <weightsystem");
|
||||
|
@ -341,7 +341,7 @@ static void save_sample(struct membuffer *b, const struct sample &sample, struct
|
|||
put_format(b, " />\n");
|
||||
}
|
||||
|
||||
static void save_one_event(struct membuffer *b, struct dive *dive, const struct event &ev)
|
||||
static void save_one_event(struct membuffer *b, const struct dive &dive, const struct event &ev)
|
||||
{
|
||||
put_format(b, " <event time='%d:%02d min'", FRACTION_TUPLE(ev.time.seconds, 60));
|
||||
show_index(b, ev.type, "type='", "'");
|
||||
|
@ -352,7 +352,7 @@ static void save_one_event(struct membuffer *b, struct dive *dive, const struct
|
|||
show_index(b, ev.value, "value='", "'");
|
||||
show_utf8(b, ev.name.c_str(), " name='", "'", 1);
|
||||
if (ev.is_gaschange()) {
|
||||
struct gasmix mix = get_gasmix_from_event(dive, ev);
|
||||
struct gasmix mix = get_gasmix_from_event(&dive, ev);
|
||||
if (ev.gas.index >= 0)
|
||||
show_integer(b, ev.gas.index, "cylinder='", "'");
|
||||
put_gasmix(b, mix);
|
||||
|
@ -361,9 +361,9 @@ static void save_one_event(struct membuffer *b, struct dive *dive, const struct
|
|||
}
|
||||
|
||||
|
||||
static void save_events(struct membuffer *b, struct dive *dive, const struct divecomputer *dc)
|
||||
static void save_events(struct membuffer *b, const struct dive &dive, const struct divecomputer &dc)
|
||||
{
|
||||
for (auto &ev: dc->events)
|
||||
for (auto &ev: dc.events)
|
||||
save_one_event(b, dive, ev);
|
||||
}
|
||||
|
||||
|
@ -381,9 +381,9 @@ static void save_tags(struct membuffer *b, const tag_list &tags)
|
|||
}
|
||||
}
|
||||
|
||||
static void save_extra_data(struct membuffer *b, const struct divecomputer *dc)
|
||||
static void save_extra_data(struct membuffer *b, const struct divecomputer &dc)
|
||||
{
|
||||
for (const auto &ed: dc->extra_data) {
|
||||
for (const auto &ed: dc.extra_data) {
|
||||
if (!ed.key.empty() && !ed.value.empty()) {
|
||||
put_string(b, " <extradata");
|
||||
show_utf8(b, ed.key.c_str(), " key='", "'", 1);
|
||||
|
@ -406,49 +406,48 @@ static void show_date(struct membuffer *b, timestamp_t when)
|
|||
tm.tm_hour, tm.tm_min, tm.tm_sec);
|
||||
}
|
||||
|
||||
static void save_samples(struct membuffer *b, struct dive *dive, struct divecomputer *dc)
|
||||
static void save_samples(struct membuffer *b, const struct dive &dive, const struct divecomputer &dc)
|
||||
{
|
||||
int o2sensor;
|
||||
struct sample dummy;
|
||||
|
||||
/* Set up default pressure sensor indices */
|
||||
o2sensor = legacy_format_o2pressures(dive, dc);
|
||||
int o2sensor = legacy_format_o2pressures(&dive, &dc);
|
||||
if (o2sensor >= 0) {
|
||||
dummy.sensor[0] = !o2sensor;
|
||||
dummy.sensor[1] = o2sensor;
|
||||
}
|
||||
|
||||
for (const auto &s: dc->samples)
|
||||
for (const auto &s: dc.samples)
|
||||
save_sample(b, s, dummy, o2sensor);
|
||||
}
|
||||
|
||||
static void save_dc(struct membuffer *b, struct dive *dive, struct divecomputer *dc)
|
||||
static void save_dc(struct membuffer *b, const struct dive &dive, const struct divecomputer &dc)
|
||||
{
|
||||
put_format(b, " <divecomputer");
|
||||
show_utf8(b, dc->model.c_str(), " model='", "'", 1);
|
||||
if (dc->last_manual_time.seconds)
|
||||
put_duration(b, dc->last_manual_time, " last-manual-time='", " min'");
|
||||
if (dc->deviceid)
|
||||
put_format(b, " deviceid='%08x'", dc->deviceid);
|
||||
if (dc->diveid)
|
||||
put_format(b, " diveid='%08x'", dc->diveid);
|
||||
if (dc->when && dc->when != dive->when)
|
||||
show_date(b, dc->when);
|
||||
if (dc->duration.seconds && dc->duration.seconds != dive->dcs[0].duration.seconds)
|
||||
put_duration(b, dc->duration, " duration='", " min'");
|
||||
if (dc->divemode != OC) {
|
||||
int i = (int)dc->divemode;
|
||||
show_utf8(b, dc.model.c_str(), " model='", "'", 1);
|
||||
if (dc.last_manual_time.seconds)
|
||||
put_duration(b, dc.last_manual_time, " last-manual-time='", " min'");
|
||||
if (dc.deviceid)
|
||||
put_format(b, " deviceid='%08x'", dc.deviceid);
|
||||
if (dc.diveid)
|
||||
put_format(b, " diveid='%08x'", dc.diveid);
|
||||
if (dc.when && dc.when != dive.when)
|
||||
show_date(b, dc.when);
|
||||
if (dc.duration.seconds && dc.duration.seconds != dive.dcs[0].duration.seconds)
|
||||
put_duration(b, dc.duration, " duration='", " min'");
|
||||
if (dc.divemode != OC) {
|
||||
int i = (int)dc.divemode;
|
||||
if (i >= 0 && i < NUM_DIVEMODE)
|
||||
show_utf8(b, divemode_text[i], " dctype='", "'", 1);
|
||||
if (dc->no_o2sensors)
|
||||
put_format(b," no_o2sensors='%d'", dc->no_o2sensors);
|
||||
if (dc.no_o2sensors)
|
||||
put_format(b," no_o2sensors='%d'", dc.no_o2sensors);
|
||||
}
|
||||
put_format(b, ">\n");
|
||||
save_depths(b, dc);
|
||||
save_temperatures(b, dc);
|
||||
save_airpressure(b, dc);
|
||||
save_salinity(b, dc);
|
||||
put_duration(b, dc->surfacetime, " <surfacetime>", " min</surfacetime>\n");
|
||||
put_duration(b, dc.surfacetime, " <surfacetime>", " min</surfacetime>\n");
|
||||
save_extra_data(b, dc);
|
||||
save_events(b, dive, dc);
|
||||
save_samples(b, dive, dc);
|
||||
|
@ -475,50 +474,50 @@ static void save_picture(struct membuffer *b, const struct picture &pic)
|
|||
put_string(b, "/>\n");
|
||||
}
|
||||
|
||||
void save_one_dive_to_mb(struct membuffer *b, struct dive *dive, bool anonymize)
|
||||
void save_one_dive_to_mb(struct membuffer *b, const struct dive &dive, bool anonymize)
|
||||
{
|
||||
pressure_t surface_pressure = un_fixup_surface_pressure(dive);
|
||||
pressure_t surface_pressure = un_fixup_surface_pressure(&dive);
|
||||
|
||||
put_string(b, "<dive");
|
||||
if (dive->number)
|
||||
put_format(b, " number='%d'", dive->number);
|
||||
if (dive->notrip)
|
||||
if (dive.number)
|
||||
put_format(b, " number='%d'", dive.number);
|
||||
if (dive.notrip)
|
||||
put_format(b, " tripflag='NOTRIP'");
|
||||
if (dive->rating)
|
||||
put_format(b, " rating='%d'", dive->rating);
|
||||
if (dive->visibility)
|
||||
put_format(b, " visibility='%d'", dive->visibility);
|
||||
if (dive->wavesize)
|
||||
put_format(b, " wavesize='%d'", dive->wavesize);
|
||||
if (dive->current)
|
||||
put_format(b, " current='%d'", dive->current);
|
||||
if (dive->surge)
|
||||
put_format(b, " surge='%d'", dive->surge);
|
||||
if (dive->chill)
|
||||
put_format(b, " chill='%d'", dive->chill);
|
||||
if (dive->invalid)
|
||||
if (dive.rating)
|
||||
put_format(b, " rating='%d'", dive.rating);
|
||||
if (dive.visibility)
|
||||
put_format(b, " visibility='%d'", dive.visibility);
|
||||
if (dive.wavesize)
|
||||
put_format(b, " wavesize='%d'", dive.wavesize);
|
||||
if (dive.current)
|
||||
put_format(b, " current='%d'", dive.current);
|
||||
if (dive.surge)
|
||||
put_format(b, " surge='%d'", dive.surge);
|
||||
if (dive.chill)
|
||||
put_format(b, " chill='%d'", dive.chill);
|
||||
if (dive.invalid)
|
||||
put_format(b, " invalid='1'");
|
||||
|
||||
// These three are calculated, and not read when loading.
|
||||
// But saving them into the XML is useful for data export.
|
||||
if (dive->sac > 100)
|
||||
put_format(b, " sac='%d.%03d l/min'", FRACTION_TUPLE(dive->sac, 1000));
|
||||
if (dive->otu)
|
||||
put_format(b, " otu='%d'", dive->otu);
|
||||
if (dive->maxcns)
|
||||
put_format(b, " cns='%d%%'", dive->maxcns);
|
||||
if (dive.sac > 100)
|
||||
put_format(b, " sac='%d.%03d l/min'", FRACTION_TUPLE(dive.sac, 1000));
|
||||
if (dive.otu)
|
||||
put_format(b, " otu='%d'", dive.otu);
|
||||
if (dive.maxcns)
|
||||
put_format(b, " cns='%d%%'", dive.maxcns);
|
||||
|
||||
save_tags(b, dive->tags);
|
||||
if (dive->dive_site)
|
||||
put_format(b, " divesiteid='%8x'", dive->dive_site->uuid);
|
||||
if (dive->user_salinity)
|
||||
put_salinity(b, dive->user_salinity, " watersalinity='", " g/l'");
|
||||
show_date(b, dive->when);
|
||||
save_tags(b, dive.tags);
|
||||
if (dive.dive_site)
|
||||
put_format(b, " divesiteid='%8x'", dive.dive_site->uuid);
|
||||
if (dive.user_salinity)
|
||||
put_salinity(b, dive.user_salinity, " watersalinity='", " g/l'");
|
||||
show_date(b, dive.when);
|
||||
if (surface_pressure.mbar)
|
||||
put_pressure(b, surface_pressure, " airpressure='", " bar'");
|
||||
if (dive->dcs[0].duration.seconds > 0)
|
||||
if (dive.dcs[0].duration.seconds > 0)
|
||||
put_format(b, " duration='%u:%02u min'>\n",
|
||||
FRACTION_TUPLE(dive->dcs[0].duration.seconds, 60));
|
||||
FRACTION_TUPLE(dive.dcs[0].duration.seconds, 60));
|
||||
else
|
||||
put_format(b, ">\n");
|
||||
save_overview(b, dive, anonymize);
|
||||
|
@ -526,14 +525,14 @@ void save_one_dive_to_mb(struct membuffer *b, struct dive *dive, bool anonymize)
|
|||
save_weightsystem_info(b, dive);
|
||||
save_dive_temperature(b, dive);
|
||||
/* Save the dive computer data */
|
||||
for (auto &dc: dive->dcs)
|
||||
save_dc(b, dive, &dc);
|
||||
for (auto &picture: dive->pictures)
|
||||
for (auto &dc: dive.dcs)
|
||||
save_dc(b, dive, dc);
|
||||
for (auto &picture: dive.pictures)
|
||||
save_picture(b, picture);
|
||||
put_format(b, "</dive>\n");
|
||||
}
|
||||
|
||||
int save_dive(FILE *f, struct dive *dive, bool anonymize)
|
||||
int save_dive(FILE *f, const struct dive &dive, bool anonymize)
|
||||
{
|
||||
membuffer buf;
|
||||
|
||||
|
@ -545,9 +544,6 @@ int save_dive(FILE *f, struct dive *dive, bool anonymize)
|
|||
|
||||
static void save_trip(struct membuffer *b, dive_trip &trip, bool anonymize)
|
||||
{
|
||||
int i;
|
||||
struct dive *dive;
|
||||
|
||||
put_format(b, "<trip");
|
||||
show_date(b, trip_date(trip));
|
||||
show_utf8(b, trip.location.c_str(), " location=\'", "\'", 1);
|
||||
|
@ -560,9 +556,9 @@ static void save_trip(struct membuffer *b, dive_trip &trip, bool anonymize)
|
|||
* list in the trip, we just traverse the global dive array and
|
||||
* check the divetrip pointer..
|
||||
*/
|
||||
for_each_dive(i, dive) {
|
||||
for (auto &dive: divelog.dives) {
|
||||
if (dive->divetrip == &trip)
|
||||
save_one_dive_to_mb(b, dive, anonymize);
|
||||
save_one_dive_to_mb(b, *dive, anonymize);
|
||||
}
|
||||
|
||||
put_format(b, "</trip>\n");
|
||||
|
@ -640,9 +636,6 @@ static void save_filter_presets(struct membuffer *b)
|
|||
|
||||
static void save_dives_buffer(struct membuffer *b, bool select_only, bool anonymize)
|
||||
{
|
||||
int i;
|
||||
struct dive *dive;
|
||||
|
||||
put_format(b, "<divelog program='subsurface' version='%d'>\n<settings>\n", DATAFORMAT_VERSION);
|
||||
|
||||
/* save the dive computer nicknames, if any */
|
||||
|
@ -692,19 +685,17 @@ static void save_dives_buffer(struct membuffer *b, bool select_only, bool anonym
|
|||
save_filter_presets(b);
|
||||
|
||||
/* save the dives */
|
||||
for_each_dive(i, dive) {
|
||||
for (auto &dive: divelog.dives) {
|
||||
if (select_only) {
|
||||
|
||||
if (!dive->selected)
|
||||
continue;
|
||||
save_one_dive_to_mb(b, dive, anonymize);
|
||||
|
||||
save_one_dive_to_mb(b, *dive, anonymize);
|
||||
} else {
|
||||
dive_trip *trip = dive->divetrip;
|
||||
|
||||
/* Bare dive without a trip? */
|
||||
if (!trip) {
|
||||
save_one_dive_to_mb(b, dive, anonymize);
|
||||
save_one_dive_to_mb(b, *dive, anonymize);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -16,32 +16,20 @@ static int amount_trips_selected;
|
|||
|
||||
struct dive *first_selected_dive()
|
||||
{
|
||||
int idx;
|
||||
struct dive *d;
|
||||
|
||||
for_each_dive (idx, d) {
|
||||
if (d->selected)
|
||||
return d;
|
||||
}
|
||||
return NULL;
|
||||
auto it = std::find_if(divelog.dives.begin(), divelog.dives.end(),
|
||||
[](auto &d) { return d->selected; });
|
||||
return it != divelog.dives.end() ? it->get() : nullptr;
|
||||
}
|
||||
|
||||
struct dive *last_selected_dive()
|
||||
{
|
||||
int idx;
|
||||
struct dive *d, *ret = NULL;
|
||||
|
||||
for_each_dive (idx, d) {
|
||||
if (d->selected)
|
||||
ret = d;
|
||||
}
|
||||
return ret;
|
||||
auto it = std::find_if(divelog.dives.rbegin(), divelog.dives.rend(),
|
||||
[](auto &d) { return d->selected; });
|
||||
return it != divelog.dives.rend() ? it->get() : nullptr;
|
||||
}
|
||||
|
||||
bool consecutive_selected()
|
||||
{
|
||||
struct dive *d;
|
||||
int i;
|
||||
bool consecutive = true;
|
||||
bool firstfound = false;
|
||||
bool lastfound = false;
|
||||
|
@ -49,7 +37,7 @@ bool consecutive_selected()
|
|||
if (amount_selected == 0 || amount_selected == 1)
|
||||
return true;
|
||||
|
||||
for_each_dive(i, d) {
|
||||
for (auto &d: divelog.dives) {
|
||||
if (d->selected) {
|
||||
if (!firstfound)
|
||||
firstfound = true;
|
||||
|
@ -65,11 +53,8 @@ bool consecutive_selected()
|
|||
#if DEBUG_SELECTION_TRACKING
|
||||
void dump_selection()
|
||||
{
|
||||
int i;
|
||||
struct dive *dive;
|
||||
|
||||
printf("currently selected are %u dives:", amount_selected);
|
||||
for_each_dive(i, dive) {
|
||||
for (auto &dive: divelog.dives) {
|
||||
if (dive->selected)
|
||||
printf(" %d", i);
|
||||
}
|
||||
|
@ -137,10 +122,8 @@ QVector<dive *> setSelectionCore(const std::vector<dive *> &selection, dive *cur
|
|||
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) {
|
||||
for (auto &d: divelog.dives) {
|
||||
// We only modify dives that are currently visible.
|
||||
if (d->hidden_by_filter) {
|
||||
d->selected = false; // Note, not necessary, just to be sure
|
||||
|
@ -150,11 +133,11 @@ QVector<dive *> setSelectionCore(const std::vector<dive *> &selection, dive *cur
|
|||
|
||||
// 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();
|
||||
bool newState = std::find(selection.begin(), selection.end(), d.get()) != selection.end();
|
||||
|
||||
if (newState) {
|
||||
++amount_selected;
|
||||
divesToSelect.push_back(d);
|
||||
divesToSelect.push_back(d.get());
|
||||
}
|
||||
d->selected = newState;
|
||||
}
|
||||
|
@ -217,10 +200,8 @@ void setTripSelection(dive_trip *trip, dive *currentDive)
|
|||
return;
|
||||
|
||||
current_dive = currentDive;
|
||||
for (int i = 0; i < divelog.dives->nr; ++i) {
|
||||
dive &d = *divelog.dives->dives[i];
|
||||
d.selected = d.divetrip == trip;
|
||||
}
|
||||
for (auto &d: divelog.dives)
|
||||
d->selected = d->divetrip == trip;
|
||||
for (auto &t: *divelog.trips)
|
||||
t->selected = t.get() == trip;
|
||||
|
||||
|
@ -245,11 +226,9 @@ std::vector<dive *> getDiveSelection()
|
|||
std::vector<dive *> res;
|
||||
res.reserve(amount_selected);
|
||||
|
||||
int i;
|
||||
dive *d;
|
||||
for_each_dive(i, d) {
|
||||
for (auto &d: divelog.dives) {
|
||||
if (d->selected)
|
||||
res.push_back(d);
|
||||
res.push_back(d.get());
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
@ -257,7 +236,7 @@ std::vector<dive *> getDiveSelection()
|
|||
bool diveInSelection(const std::vector<dive *> &selection, const dive *d)
|
||||
{
|
||||
// Do a binary search using the ordering of the dive list.
|
||||
auto it = std::lower_bound(selection.begin(), selection.end(), d, dive_less_than);
|
||||
auto it = std::lower_bound(selection.begin(), selection.end(), d, dive_less_than_ptr);
|
||||
return it != selection.end() && *it == d;
|
||||
}
|
||||
|
||||
|
@ -265,7 +244,7 @@ void updateSelection(std::vector<dive *> &selection, const std::vector<dive *> &
|
|||
{
|
||||
// We could sort the array and merge the vectors as we do in the undo code. But is it necessary?
|
||||
for (dive *d: add) {
|
||||
auto it = std::lower_bound(selection.begin(), selection.end(), d, dive_less_than);
|
||||
auto it = std::lower_bound(selection.begin(), selection.end(), d, dive_less_than_ptr);
|
||||
if (it != selection.end() && *it == d)
|
||||
continue; // Ooops. Already there?
|
||||
selection.insert(it, d);
|
||||
|
@ -273,7 +252,7 @@ void updateSelection(std::vector<dive *> &selection, const std::vector<dive *> &
|
|||
|
||||
// Likewise, we could sort the array and be smarter here. Again, is it necessary?
|
||||
for (dive *d: remove) {
|
||||
auto it = std::lower_bound(selection.begin(), selection.end(), d, dive_less_than);
|
||||
auto it = std::lower_bound(selection.begin(), selection.end(), d, dive_less_than_ptr);
|
||||
if (it == selection.end() || *it != d)
|
||||
continue; // Ooops. Not there?
|
||||
selection.erase(it);
|
||||
|
@ -283,10 +262,9 @@ void updateSelection(std::vector<dive *> &selection, const std::vector<dive *> &
|
|||
// Select the first dive that is visible
|
||||
void select_newest_visible_dive()
|
||||
{
|
||||
for (int i = divelog.dives->nr - 1; i >= 0; --i) {
|
||||
dive *d = divelog.dives->dives[i];
|
||||
if (!d->hidden_by_filter)
|
||||
return select_single_dive(d);
|
||||
for (auto it = divelog.dives.rbegin(); it != divelog.dives.rend(); ++it) {
|
||||
if (!(*it)->hidden_by_filter)
|
||||
return select_single_dive(it->get());
|
||||
}
|
||||
|
||||
// No visible dive -> deselect all
|
||||
|
|
|
@ -19,15 +19,15 @@
|
|||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
static void process_temperatures(struct dive *dp, stats_t &stats)
|
||||
static void process_temperatures(const struct dive &dp, stats_t &stats)
|
||||
{
|
||||
temperature_t min_temp, mean_temp, max_temp = {.mkelvin = 0};
|
||||
|
||||
max_temp.mkelvin = dp->maxtemp.mkelvin;
|
||||
max_temp.mkelvin = dp.maxtemp.mkelvin;
|
||||
if (max_temp.mkelvin && (!stats.max_temp.mkelvin || max_temp.mkelvin > stats.max_temp.mkelvin))
|
||||
stats.max_temp.mkelvin = max_temp.mkelvin;
|
||||
|
||||
min_temp.mkelvin = dp->mintemp.mkelvin;
|
||||
min_temp.mkelvin = dp.mintemp.mkelvin;
|
||||
if (min_temp.mkelvin && (!stats.min_temp.mkelvin || min_temp.mkelvin < stats.min_temp.mkelvin))
|
||||
stats.min_temp.mkelvin = min_temp.mkelvin;
|
||||
|
||||
|
@ -42,10 +42,10 @@ static void process_temperatures(struct dive *dp, stats_t &stats)
|
|||
}
|
||||
}
|
||||
|
||||
static void process_dive(struct dive *dive, stats_t &stats)
|
||||
static void process_dive(const struct dive &dive, stats_t &stats)
|
||||
{
|
||||
int old_tadt, sac_time = 0;
|
||||
int32_t duration = dive->duration.seconds;
|
||||
int32_t duration = dive.duration.seconds;
|
||||
|
||||
old_tadt = stats.total_average_depth_time.seconds;
|
||||
stats.total_time.seconds += duration;
|
||||
|
@ -53,32 +53,32 @@ static void process_dive(struct dive *dive, stats_t &stats)
|
|||
stats.longest_time.seconds = duration;
|
||||
if (stats.shortest_time.seconds == 0 || duration < stats.shortest_time.seconds)
|
||||
stats.shortest_time.seconds = duration;
|
||||
if (dive->maxdepth.mm > stats.max_depth.mm)
|
||||
stats.max_depth.mm = dive->maxdepth.mm;
|
||||
if (stats.min_depth.mm == 0 || dive->maxdepth.mm < stats.min_depth.mm)
|
||||
stats.min_depth.mm = dive->maxdepth.mm;
|
||||
stats.combined_max_depth.mm += dive->maxdepth.mm;
|
||||
if (dive.maxdepth.mm > stats.max_depth.mm)
|
||||
stats.max_depth.mm = dive.maxdepth.mm;
|
||||
if (stats.min_depth.mm == 0 || dive.maxdepth.mm < stats.min_depth.mm)
|
||||
stats.min_depth.mm = dive.maxdepth.mm;
|
||||
stats.combined_max_depth.mm += dive.maxdepth.mm;
|
||||
|
||||
process_temperatures(dive, stats);
|
||||
|
||||
/* Maybe we should drop zero-duration dives */
|
||||
if (!duration)
|
||||
return;
|
||||
if (dive->meandepth.mm) {
|
||||
if (dive.meandepth.mm) {
|
||||
stats.total_average_depth_time.seconds += duration;
|
||||
stats.avg_depth.mm = lrint((1.0 * old_tadt * stats.avg_depth.mm +
|
||||
duration * dive->meandepth.mm) /
|
||||
duration * dive.meandepth.mm) /
|
||||
stats.total_average_depth_time.seconds);
|
||||
}
|
||||
if (dive->sac > 100) { /* less than .1 l/min is bogus, even with a pSCR */
|
||||
if (dive.sac > 100) { /* less than .1 l/min is bogus, even with a pSCR */
|
||||
sac_time = stats.total_sac_time.seconds + duration;
|
||||
stats.avg_sac.mliter = lrint((1.0 * stats.total_sac_time.seconds * stats.avg_sac.mliter +
|
||||
duration * dive->sac) /
|
||||
duration * dive.sac) /
|
||||
sac_time);
|
||||
if (dive->sac > stats.max_sac.mliter)
|
||||
stats.max_sac.mliter = dive->sac;
|
||||
if (stats.min_sac.mliter == 0 || dive->sac < stats.min_sac.mliter)
|
||||
stats.min_sac.mliter = dive->sac;
|
||||
if (dive.sac > stats.max_sac.mliter)
|
||||
stats.max_sac.mliter = dive.sac;
|
||||
if (stats.min_sac.mliter == 0 || dive.sac < stats.min_sac.mliter)
|
||||
stats.min_sac.mliter = dive.sac;
|
||||
stats.total_sac_time.seconds = sac_time;
|
||||
}
|
||||
}
|
||||
|
@ -91,8 +91,6 @@ static void process_dive(struct dive *dive, stats_t &stats)
|
|||
*/
|
||||
stats_summary calculate_stats_summary(bool selected_only)
|
||||
{
|
||||
int idx;
|
||||
struct dive *dp;
|
||||
struct tm tm;
|
||||
int current_year = -1;
|
||||
int current_month = 0;
|
||||
|
@ -128,7 +126,7 @@ stats_summary calculate_stats_summary(bool selected_only)
|
|||
|
||||
/* this relies on the fact that the dives in the dive_table
|
||||
* are in chronological order */
|
||||
for_each_dive (idx, dp) {
|
||||
for (auto &dp: divelog.dives) {
|
||||
if (selected_only && !dp->selected)
|
||||
continue;
|
||||
if (dp->invalid)
|
||||
|
@ -143,34 +141,34 @@ stats_summary calculate_stats_summary(bool selected_only)
|
|||
out.stats_yearly.emplace_back();
|
||||
out.stats_yearly.back().is_year = true;
|
||||
}
|
||||
process_dive(dp, out.stats_yearly.back());
|
||||
process_dive(*dp, out.stats_yearly.back());
|
||||
|
||||
out.stats_yearly.back().selection_size++;
|
||||
out.stats_yearly.back().period = current_year;
|
||||
|
||||
/* stats_by_type[0] is all the dives combined */
|
||||
out.stats_by_type[0].selection_size++;
|
||||
process_dive(dp, out.stats_by_type[0]);
|
||||
process_dive(*dp, out.stats_by_type[0]);
|
||||
|
||||
process_dive(dp, out.stats_by_type[dp->dcs[0].divemode + 1]);
|
||||
process_dive(*dp, out.stats_by_type[dp->dcs[0].divemode + 1]);
|
||||
out.stats_by_type[dp->dcs[0].divemode + 1].selection_size++;
|
||||
|
||||
/* stats_by_depth[0] is all the dives combined */
|
||||
out.stats_by_depth[0].selection_size++;
|
||||
process_dive(dp, out.stats_by_depth[0]);
|
||||
process_dive(*dp, out.stats_by_depth[0]);
|
||||
|
||||
int d_idx = dp->maxdepth.mm / (STATS_DEPTH_BUCKET * 1000);
|
||||
d_idx = std::clamp(d_idx, 0, STATS_MAX_DEPTH / STATS_DEPTH_BUCKET);
|
||||
process_dive(dp, out.stats_by_depth[d_idx + 1]);
|
||||
process_dive(*dp, out.stats_by_depth[d_idx + 1]);
|
||||
out.stats_by_depth[d_idx + 1].selection_size++;
|
||||
|
||||
/* stats_by_temp[0] is all the dives combined */
|
||||
out.stats_by_temp[0].selection_size++;
|
||||
process_dive(dp, out.stats_by_temp[0]);
|
||||
process_dive(*dp, out.stats_by_temp[0]);
|
||||
|
||||
int t_idx = ((int)mkelvin_to_C(dp->mintemp.mkelvin)) / STATS_TEMP_BUCKET;
|
||||
t_idx = std::clamp(t_idx, 0, STATS_MAX_TEMP / STATS_TEMP_BUCKET);
|
||||
process_dive(dp, out.stats_by_temp[t_idx + 1]);
|
||||
process_dive(*dp, out.stats_by_temp[t_idx + 1]);
|
||||
out.stats_by_temp[t_idx + 1].selection_size++;
|
||||
|
||||
if (dp->divetrip != NULL) {
|
||||
|
@ -182,11 +180,11 @@ stats_summary calculate_stats_summary(bool selected_only)
|
|||
/* stats_by_trip[0] is all the dives combined */
|
||||
/* TODO: yet, this doesn't seem to consider dives outside of trips !? */
|
||||
out.stats_by_trip[0].selection_size++;
|
||||
process_dive(dp, out.stats_by_trip[0]);
|
||||
process_dive(*dp, out.stats_by_trip[0]);
|
||||
out.stats_by_trip[0].is_trip = true;
|
||||
out.stats_by_trip[0].location = translate("gettextFromC", "All (by trip stats)");
|
||||
|
||||
process_dive(dp, out.stats_by_trip.back());
|
||||
process_dive(*dp, out.stats_by_trip.back());
|
||||
out.stats_by_trip.back().selection_size++;
|
||||
out.stats_by_trip.back().is_trip = true;
|
||||
out.stats_by_trip.back().location = dp->divetrip->location;
|
||||
|
@ -202,7 +200,7 @@ stats_summary calculate_stats_summary(bool selected_only)
|
|||
if (prev_month != current_month || prev_year != current_year)
|
||||
out.stats_monthly.emplace_back();
|
||||
}
|
||||
process_dive(dp, out.stats_monthly.back());
|
||||
process_dive(*dp, out.stats_monthly.back());
|
||||
out.stats_monthly.back().selection_size++;
|
||||
out.stats_monthly.back().period = current_month;
|
||||
prev_month = current_month;
|
||||
|
@ -230,25 +228,18 @@ stats_summary calculate_stats_summary(bool selected_only)
|
|||
return out;
|
||||
}
|
||||
|
||||
stats_summary::stats_summary()
|
||||
{
|
||||
}
|
||||
|
||||
stats_summary::~stats_summary()
|
||||
{
|
||||
}
|
||||
stats_summary::stats_summary() = default;
|
||||
stats_summary::~stats_summary() = default;
|
||||
|
||||
/* make sure we skip the selected summary entries */
|
||||
stats_t calculate_stats_selected()
|
||||
{
|
||||
stats_t stats_selection;
|
||||
struct dive *dive;
|
||||
unsigned int i, nr;
|
||||
unsigned int nr = 0;
|
||||
|
||||
nr = 0;
|
||||
for_each_dive(i, dive) {
|
||||
for (auto &dive: divelog.dives) {
|
||||
if (dive->selected && !dive->invalid) {
|
||||
process_dive(dive, stats_selection);
|
||||
process_dive(*dive, stats_selection);
|
||||
nr++;
|
||||
}
|
||||
}
|
||||
|
@ -336,16 +327,14 @@ static std::pair<volume_t, volume_t> get_gas_parts(struct gasmix mix, volume_t v
|
|||
|
||||
std::pair<volume_t, volume_t> selected_dives_gas_parts()
|
||||
{
|
||||
int i;
|
||||
struct dive *d;
|
||||
volume_t o2_tot, he_tot;
|
||||
for_each_dive (i, d) {
|
||||
for (auto &d: divelog.dives) {
|
||||
if (!d->selected || d->invalid)
|
||||
continue;
|
||||
int j = 0;
|
||||
for (auto &gas: get_gas_used(d)) {
|
||||
for (auto &gas: get_gas_used(d.get())) {
|
||||
if (gas.mliter) {
|
||||
auto [o2, he] = get_gas_parts(get_cylinder(d, j)->gasmix, gas, O2_IN_AIR);
|
||||
auto [o2, he] = get_gas_parts(get_cylinder(d.get(), j)->gasmix, gas, O2_IN_AIR);
|
||||
o2_tot.mliter += o2.mliter;
|
||||
he_tot.mliter += he.mliter;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#include "string-format.h"
|
||||
#include "dive.h"
|
||||
#include "divelist.h"
|
||||
#include "divelog.h"
|
||||
#include "divesite.h"
|
||||
#include "event.h"
|
||||
#include "format.h"
|
||||
|
@ -135,9 +137,7 @@ static void addStringToSortedList(QStringList &l, const std::string &s)
|
|||
QStringList formatFullCylinderList()
|
||||
{
|
||||
QStringList cylinders;
|
||||
struct dive *d;
|
||||
int i = 0;
|
||||
for_each_dive (i, d) {
|
||||
for (auto &d: divelog.dives) {
|
||||
for (const cylinder_t &cyl: d->cylinders)
|
||||
addStringToSortedList(cylinders, cyl.type.description);
|
||||
}
|
||||
|
|
|
@ -50,22 +50,6 @@ static timestamp_t trip_enddate(const struct dive_trip &trip)
|
|||
return trip.dives.back()->endtime();
|
||||
}
|
||||
|
||||
/* check if we have a trip right before / after this dive */
|
||||
bool is_trip_before_after(const struct dive *dive, bool before)
|
||||
{
|
||||
int idx = get_idx_by_uniq_id(dive->id);
|
||||
if (before) {
|
||||
const struct dive *d = get_dive(idx - 1);
|
||||
if (d && d->divetrip)
|
||||
return true;
|
||||
} else {
|
||||
const struct dive *d = get_dive(idx + 1);
|
||||
if (d && d->divetrip)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Add dive to a trip. Caller is responsible for removing dive
|
||||
* from trip beforehand. */
|
||||
void add_dive_to_trip(struct dive *dive, dive_trip *trip)
|
||||
|
@ -73,8 +57,8 @@ void add_dive_to_trip(struct dive *dive, dive_trip *trip)
|
|||
if (dive->divetrip == trip)
|
||||
return;
|
||||
if (dive->divetrip)
|
||||
report_info("Warning: adding dive to trip that has trip set\n");
|
||||
range_insert_sorted(trip->dives, dive, comp_dives);
|
||||
report_info("Warning: adding dive to trip, which already has a trip set");
|
||||
range_insert_sorted(trip->dives, dive, comp_dives_ptr);
|
||||
dive->divetrip = trip;
|
||||
}
|
||||
|
||||
|
@ -112,13 +96,10 @@ std::unique_ptr<dive_trip> create_trip_from_dive(const struct dive *dive)
|
|||
* exist, allocate a new trip. A unique_ptr is returned if a new trip
|
||||
* was allocated. The caller has to store it.
|
||||
*/
|
||||
std::pair<dive_trip *, std::unique_ptr<dive_trip>> get_trip_for_new_dive(const struct dive *new_dive)
|
||||
std::pair<dive_trip *, std::unique_ptr<dive_trip>> get_trip_for_new_dive(const struct divelog &log, const struct dive *new_dive)
|
||||
{
|
||||
dive *d;
|
||||
int i;
|
||||
|
||||
/* Find dive that is within TRIP_THRESHOLD of current dive */
|
||||
for_each_dive(i, d) {
|
||||
for (auto &d: log.dives) {
|
||||
/* Check if we're past the range of possible dives */
|
||||
if (d->when >= new_dive->when + TRIP_THRESHOLD)
|
||||
break;
|
||||
|
@ -164,7 +145,7 @@ bool trips_overlap(const struct dive_trip &t1, const struct dive_trip &t2)
|
|||
* manually injects the new trips. If there are no dives to be autogrouped,
|
||||
* return NULL.
|
||||
*/
|
||||
std::vector<dives_to_autogroup_result> get_dives_to_autogroup(struct dive_table *table)
|
||||
std::vector<dives_to_autogroup_result> get_dives_to_autogroup(const struct dive_table &table)
|
||||
{
|
||||
std::vector<dives_to_autogroup_result> res;
|
||||
struct dive *lastdive = NULL;
|
||||
|
@ -172,12 +153,11 @@ std::vector<dives_to_autogroup_result> get_dives_to_autogroup(struct dive_table
|
|||
/* Find first dive that should be merged and remember any previous
|
||||
* dive that could be merged into.
|
||||
*/
|
||||
for (int i = 0; i < table->nr; ++i) {
|
||||
struct dive *dive = table->dives[i];
|
||||
dive_trip *trip;
|
||||
for (size_t i = 0; i < table.size(); ++i) {
|
||||
auto &dive = table[i];
|
||||
|
||||
if (dive->divetrip) {
|
||||
lastdive = dive;
|
||||
lastdive = dive.get();
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -190,9 +170,10 @@ std::vector<dives_to_autogroup_result> get_dives_to_autogroup(struct dive_table
|
|||
|
||||
/* We found a dive, let's see if we have to allocate a new trip */
|
||||
std::unique_ptr<dive_trip> allocated;
|
||||
dive_trip *trip;
|
||||
if (!lastdive || dive->when >= lastdive->when + TRIP_THRESHOLD) {
|
||||
/* allocate new trip */
|
||||
allocated = create_trip_from_dive(dive);
|
||||
allocated = create_trip_from_dive(dive.get());
|
||||
allocated->autogen = true;
|
||||
trip = allocated.get();
|
||||
} else {
|
||||
|
@ -201,16 +182,16 @@ std::vector<dives_to_autogroup_result> get_dives_to_autogroup(struct dive_table
|
|||
}
|
||||
|
||||
// Now, find all dives that will be added to this trip
|
||||
lastdive = dive;
|
||||
int to;
|
||||
for (to = i + 1; to < table->nr; to++) {
|
||||
dive = table->dives[to];
|
||||
lastdive = dive.get();
|
||||
size_t to;
|
||||
for (to = i + 1; to < table.size(); to++) {
|
||||
auto &dive = table[to];
|
||||
if (dive->divetrip || dive->notrip ||
|
||||
dive->when >= lastdive->when + TRIP_THRESHOLD)
|
||||
break;
|
||||
if (trip->location.empty())
|
||||
trip->location = get_dive_location(dive);
|
||||
lastdive = dive;
|
||||
trip->location = get_dive_location(dive.get());
|
||||
lastdive = dive.get();
|
||||
}
|
||||
res.push_back({ i, to, trip, std::move(allocated) });
|
||||
i = to - 1;
|
||||
|
@ -250,7 +231,7 @@ int comp_trips(const struct dive_trip &a, const struct dive_trip &b)
|
|||
return -1;
|
||||
if (b.dives.empty())
|
||||
return 1;
|
||||
return comp_dives(a.dives[0], b.dives[0]);
|
||||
return comp_dives(*a.dives[0], *b.dives[0]);
|
||||
}
|
||||
|
||||
static bool is_same_day(timestamp_t trip_when, timestamp_t dive_when)
|
||||
|
@ -285,5 +266,5 @@ int trip_shown_dives(const struct dive_trip *trip)
|
|||
|
||||
void dive_trip::sort_dives()
|
||||
{
|
||||
std::sort(dives.begin(), dives.end(), [] (dive *d1, dive *d2) { return comp_dives(d1, d2) < 0; });
|
||||
std::sort(dives.begin(), dives.end(), [] (dive *d1, dive *d2) { return comp_dives(*d1, *d2) < 0; });
|
||||
}
|
||||
|
|
17
core/trip.h
17
core/trip.h
|
@ -3,9 +3,8 @@
|
|||
#define TRIP_H
|
||||
|
||||
#include "divelist.h"
|
||||
#include "owning_table.h"
|
||||
|
||||
#include <string>
|
||||
struct divelog;
|
||||
|
||||
struct dive_trip
|
||||
{
|
||||
|
@ -26,10 +25,6 @@ struct dive_trip
|
|||
|
||||
int comp_trips(const dive_trip &t1, const dive_trip &t2);
|
||||
|
||||
struct trip_table : public sorted_owning_table<dive_trip, &comp_trips> {
|
||||
dive_trip *get_by_uniq_id(int tripId) const;
|
||||
};
|
||||
|
||||
extern void add_dive_to_trip(struct dive *, dive_trip *);
|
||||
extern struct dive_trip *unregister_dive_from_trip(struct dive *dive);
|
||||
|
||||
|
@ -40,18 +35,17 @@ extern dive_trip *create_and_hookup_trip_from_dive(const struct dive *dive, stru
|
|||
|
||||
// Result item of get_dives_to_autogroup()
|
||||
struct dives_to_autogroup_result {
|
||||
int from, to; // Group dives in the range [from, to)
|
||||
size_t from, to; // Group dives in the range [from, to)
|
||||
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 std::vector<dives_to_autogroup_result> get_dives_to_autogroup(const struct dive_table &table);
|
||||
extern std::pair<dive_trip *, std::unique_ptr<dive_trip>> get_trip_for_new_dive(const struct divelog &log, const struct dive *new_dive);
|
||||
extern bool trips_overlap(const struct dive_trip &t1, const struct dive_trip &t2);
|
||||
|
||||
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 trip_is_single_day(const struct dive_trip &trip);
|
||||
extern int trip_shown_dives(const struct dive_trip *trip);
|
||||
|
||||
|
@ -59,10 +53,9 @@ extern int trip_shown_dives(const struct dive_trip *trip);
|
|||
extern void dump_trip_list();
|
||||
#endif
|
||||
|
||||
/* Make pointers to dive_trip and trip_table "Qt metatypes" so that they can be
|
||||
/* Make pointers to dive_trip "Qt metatypes" so that they can be
|
||||
* passed through QVariants and through QML. See comment in dive.h. */
|
||||
#include <QObject>
|
||||
Q_DECLARE_METATYPE(struct dive_trip *);
|
||||
Q_DECLARE_METATYPE(trip_table *);
|
||||
|
||||
#endif
|
||||
|
|
21
core/triptable.h
Normal file
21
core/triptable.h
Normal file
|
@ -0,0 +1,21 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
#ifndef TRIPTABLE_H
|
||||
#define TRIPTABLE_H
|
||||
|
||||
#include "owning_table.h"
|
||||
|
||||
struct dive_trip;
|
||||
|
||||
int comp_trips(const dive_trip &t1, const dive_trip &t2);
|
||||
|
||||
struct trip_table : public sorted_owning_table<dive_trip, &comp_trips> {
|
||||
dive_trip *get_by_uniq_id(int tripId) const;
|
||||
};
|
||||
|
||||
/* Make pointers to trip_table "Qt metatypes" so that they can be
|
||||
* passed through QVariants and through QML. See comment in dive.h. */
|
||||
#include <QObject>
|
||||
Q_DECLARE_METATYPE(trip_table *);
|
||||
|
||||
#endif
|
||||
|
|
@ -190,9 +190,9 @@ static std::unique_ptr<dive> uemis_start_dive(uint32_t deviceid)
|
|||
|
||||
static struct dive *get_dive_by_uemis_diveid(device_data_t *devdata, uint32_t object_id)
|
||||
{
|
||||
for (int i = 0; i < devdata->log->dives->nr; i++) {
|
||||
if (object_id == devdata->log->dives->dives[i]->dcs[0].diveid)
|
||||
return devdata->log->dives->dives[i];
|
||||
for (auto &d: devdata->log->dives) {
|
||||
if (object_id == d->dcs[0].diveid)
|
||||
return d.get();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
@ -767,27 +767,13 @@ static void parse_tag(struct dive *dive, std::string_view tag, std::string_view
|
|||
|
||||
static bool uemis_delete_dive(device_data_t *devdata, uint32_t diveid)
|
||||
{
|
||||
struct dive *dive = NULL;
|
||||
auto it = std::find_if(devdata->log->dives.begin(), devdata->log->dives.end(),
|
||||
[diveid] (auto &d) { return d->dcs[0].diveid == diveid; });
|
||||
if (it == devdata->log->dives.end())
|
||||
return false;
|
||||
|
||||
if (devdata->log->dives->dives[devdata->log->dives->nr - 1]->dcs[0].diveid == diveid) {
|
||||
/* we hit the last one in the array */
|
||||
dive = devdata->log->dives->dives[devdata->log->dives->nr - 1];
|
||||
} else {
|
||||
for (int i = 0; i < devdata->log->dives->nr - 1; i++) {
|
||||
if (devdata->log->dives->dives[i]->dcs[0].diveid == diveid) {
|
||||
dive = devdata->log->dives->dives[i];
|
||||
for (int x = i; x < devdata->log->dives->nr - 1; x++)
|
||||
devdata->log->dives->dives[i] = devdata->log->dives->dives[x + 1];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (dive) {
|
||||
devdata->log->dives->dives[--devdata->log->dives->nr] = NULL;
|
||||
delete dive;
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
devdata->log->dives.erase(it);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* This function is called for both dive log and dive information that we get
|
||||
|
@ -914,7 +900,7 @@ static bool process_raw_buffer(device_data_t *devdata, uint32_t deviceid, std::s
|
|||
bp = bp.substr(1);
|
||||
if (bp[0] != '{' && bp.find("{{") != std::string::npos) {
|
||||
done = false;
|
||||
record_dive_to_table(owned_dive.release(), devdata->log->dives.get());
|
||||
devdata->log->dives.record_dive(std::move(owned_dive));
|
||||
owned_dive = uemis_start_dive(deviceid);
|
||||
}
|
||||
}
|
||||
|
@ -947,7 +933,7 @@ static bool process_raw_buffer(device_data_t *devdata, uint32_t deviceid, std::s
|
|||
}
|
||||
if (is_log) {
|
||||
if (owned_dive->dcs[0].diveid)
|
||||
record_dive_to_table(owned_dive.release(), devdata->log->dives.get());
|
||||
devdata->log->dives.record_dive(std::move(owned_dive));
|
||||
else /* partial dive */
|
||||
return false;
|
||||
}
|
||||
|
@ -959,7 +945,6 @@ static std::pair<uint32_t, uint32_t> uemis_get_divenr(uint32_t deviceid, struct
|
|||
{
|
||||
uint32_t maxdiveid = 0;
|
||||
uint32_t mindiveid = 0xFFFFFFFF;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* If we are are retrying after a disconnect/reconnect, we
|
||||
|
@ -971,11 +956,10 @@ static std::pair<uint32_t, uint32_t> uemis_get_divenr(uint32_t deviceid, struct
|
|||
*
|
||||
* Otherwise, use the global dive table.
|
||||
*/
|
||||
if (!force && !table->nr)
|
||||
table = divelog.dives.get();
|
||||
if (!force && table->empty())
|
||||
table = &divelog.dives;
|
||||
|
||||
for (i = 0; i < table->nr; i++) {
|
||||
struct dive *d = table->dives[i];
|
||||
for (auto &d: *table) {
|
||||
if (!d)
|
||||
continue;
|
||||
for (auto &dc: d->dcs) {
|
||||
|
@ -1037,19 +1021,19 @@ static bool do_dump_buffer_to_file(std::string_view buf, const char *prefix)
|
|||
* return : ok if there is enough memory for a full round
|
||||
* full if the memory is exhausted
|
||||
*/
|
||||
static uemis_mem_status get_memory(struct dive_table *td, uemis_checkpoint checkpoint)
|
||||
static uemis_mem_status get_memory(struct dive_table &td, uemis_checkpoint checkpoint)
|
||||
{
|
||||
if (td->nr <= 0)
|
||||
if (td.empty())
|
||||
return uemis_mem_status::ok;
|
||||
|
||||
switch (checkpoint) {
|
||||
case uemis_checkpoint::log:
|
||||
if (filenr / td->nr > max_mem_used)
|
||||
max_mem_used = filenr / td->nr;
|
||||
if (filenr / static_cast<int>(td.size()) > max_mem_used)
|
||||
max_mem_used = filenr / static_cast<int>(td.size());
|
||||
|
||||
/* check if a full block of dive logs + dive details and dive spot fit into the UEMIS buffer */
|
||||
#if UEMIS_DEBUG & 4
|
||||
report_info("max_mem_used %d (from td->nr %d) * block_size %d > max_files %d - filenr %d?\n", max_mem_used, td->nr, uemis_log_block_size, uemis_max_files, filenr);
|
||||
report_info("max_mem_used %d (from td.size() %d) * block_size %d > max_files %d - filenr %d?\n", max_mem_used, static_cast<int>(td.size()), uemis_log_block_size, uemis_max_files, filenr);
|
||||
#endif
|
||||
if (max_mem_used * uemis_log_block_size > uemis_max_files - filenr)
|
||||
return uemis_mem_status::full;
|
||||
|
@ -1069,10 +1053,10 @@ static uemis_mem_status get_memory(struct dive_table *td, uemis_checkpoint check
|
|||
|
||||
/* we misuse the hidden_by_filter flag to mark a dive as deleted.
|
||||
* this will be picked up by some cleaning statement later. */
|
||||
static void do_delete_dives(struct dive_table *td, int idx)
|
||||
static void do_delete_dives(struct dive_table &td, size_t idx)
|
||||
{
|
||||
for (int x = idx; x < td->nr; x++)
|
||||
td->dives[x]->hidden_by_filter = true;
|
||||
for (auto it = td.begin() + idx; it != td.end(); ++it)
|
||||
(*it)->hidden_by_filter = true;
|
||||
}
|
||||
|
||||
static bool load_uemis_divespot(const std::string &mountpath, int divespot_id)
|
||||
|
@ -1128,9 +1112,9 @@ static void get_uemis_divespot(device_data_t *devdata, const std::string &mountp
|
|||
}
|
||||
}
|
||||
|
||||
static bool get_matching_dive(int idx, int &newmax, uemis_mem_status &mem_status, device_data_t *data, const std::string &mountpath, const char deviceidnr)
|
||||
static bool get_matching_dive(size_t idx, int &newmax, uemis_mem_status &mem_status, device_data_t *data, const std::string &mountpath, const char deviceidnr)
|
||||
{
|
||||
struct dive *dive = data->log->dives->dives[idx];
|
||||
auto &dive = data->log->dives[idx];
|
||||
char log_file_no_to_find[20];
|
||||
bool found = false;
|
||||
bool found_below = false;
|
||||
|
@ -1151,7 +1135,7 @@ static bool get_matching_dive(int idx, int &newmax, uemis_mem_status &mem_status
|
|||
#if UEMIS_DEBUG & 16
|
||||
do_dump_buffer_to_file(mbuf, "Dive");
|
||||
#endif
|
||||
mem_status = get_memory(data->log->dives.get(), uemis_checkpoint::single_dive);
|
||||
mem_status = get_memory(data->log->dives, uemis_checkpoint::single_dive);
|
||||
if (mem_status == uemis_mem_status::ok) {
|
||||
/* if the memory isn's completely full we can try to read more dive log vs. dive details
|
||||
* and the dive spots should fit into the UEMIS memory
|
||||
|
@ -1174,7 +1158,7 @@ static bool get_matching_dive(int idx, int &newmax, uemis_mem_status &mem_status
|
|||
#endif
|
||||
int divespot_id = uemis_obj.get_divespot_id_by_diveid(dive->dcs[0].diveid);
|
||||
if (divespot_id >= 0)
|
||||
get_uemis_divespot(data, mountpath, divespot_id, dive);
|
||||
get_uemis_divespot(data, mountpath, divespot_id, dive.get());
|
||||
|
||||
} else {
|
||||
/* in this case we found a deleted file, so let's increment */
|
||||
|
@ -1215,7 +1199,7 @@ static bool get_matching_dive(int idx, int &newmax, uemis_mem_status &mem_status
|
|||
} else {
|
||||
/* At this point the memory of the UEMIS is full, let's cleanup all dive log files were
|
||||
* we could not match the details to. */
|
||||
do_delete_dives(data->log->dives.get(), idx);
|
||||
do_delete_dives(data->log->dives, idx);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -1236,7 +1220,6 @@ std::string do_uemis_import(device_data_t *data)
|
|||
std::string deviceid;
|
||||
std::string result;
|
||||
bool once = true;
|
||||
int match_dive_and_log = 0;
|
||||
int dive_offset = 0;
|
||||
uemis_mem_status mem_status = uemis_mem_status::ok;
|
||||
|
||||
|
@ -1274,7 +1257,7 @@ std::string do_uemis_import(device_data_t *data)
|
|||
|
||||
param_buff[1] = "notempty";
|
||||
{
|
||||
auto [mindiveid, maxdiveid] = uemis_get_divenr(deviceidnr, data->log->dives.get(), force_download);
|
||||
auto [mindiveid, maxdiveid] = uemis_get_divenr(deviceidnr, &data->log->dives, force_download);
|
||||
newmax = maxdiveid;
|
||||
if (verbose)
|
||||
report_info("Uemis downloader: start looking at dive nr %d", newmax);
|
||||
|
@ -1292,13 +1275,13 @@ std::string do_uemis_import(device_data_t *data)
|
|||
report_info("d_u_i inner loop start %d end %d newmax %d\n", start, end, newmax);
|
||||
#endif
|
||||
/* start at the last filled download table index */
|
||||
match_dive_and_log = data->log->dives->nr;
|
||||
size_t match_dive_and_log = data->log->dives.size();
|
||||
newmax = start;
|
||||
std::string newmax_str = std::to_string(newmax);
|
||||
param_buff[2] = newmax_str.c_str();
|
||||
param_buff[3].clear();
|
||||
std::string mbuf = uemis_get_answer(mountpath, "getDivelogs", 3, 0, result);
|
||||
mem_status = get_memory(data->log->dives.get(), uemis_checkpoint::details);
|
||||
mem_status = get_memory(data->log->dives, uemis_checkpoint::details);
|
||||
/* first, remove any leading garbage... this needs to start with a '{' */
|
||||
std::string_view realmbuf = mbuf;
|
||||
size_t pos = realmbuf.find('{');
|
||||
|
@ -1341,7 +1324,7 @@ std::string do_uemis_import(device_data_t *data)
|
|||
* What the following part does is to optimize the mapping by using
|
||||
* dive_to_read = the dive details entry that need to be read using the object_id
|
||||
* logFileNoToFind = map the logfilenr of the dive details with the object_id = diveid from the get dive logs */
|
||||
for (int i = match_dive_and_log; i < data->log->dives->nr; i++) {
|
||||
for (size_t i = match_dive_and_log; i < data->log->dives.size(); i++) {
|
||||
if (!get_matching_dive(i, newmax, mem_status, data, mountpath, deviceidnr))
|
||||
break;
|
||||
if (import_thread_cancelled)
|
||||
|
@ -1351,7 +1334,7 @@ std::string do_uemis_import(device_data_t *data)
|
|||
start = end;
|
||||
|
||||
/* Do some memory checking here */
|
||||
mem_status = get_memory(data->log->dives.get(), uemis_checkpoint::log);
|
||||
mem_status = get_memory(data->log->dives, uemis_checkpoint::log);
|
||||
if (mem_status != uemis_mem_status::ok) {
|
||||
#if UEMIS_DEBUG & 4
|
||||
report_info("d_u_i out of memory, bailing\n");
|
||||
|
@ -1365,7 +1348,7 @@ std::string do_uemis_import(device_data_t *data)
|
|||
// Resetting to original state
|
||||
filenr = 0;
|
||||
max_mem_used = -1;
|
||||
mem_status = get_memory(data->log->dives.get(), uemis_checkpoint::details);
|
||||
mem_status = get_memory(data->log->dives, uemis_checkpoint::details);
|
||||
if (uemis_get_answer(mountpath, "getDeviceId", 0, 1, result).empty())
|
||||
goto bail;
|
||||
if (deviceid != param_buff[0]) {
|
||||
|
@ -1408,7 +1391,7 @@ std::string do_uemis_import(device_data_t *data)
|
|||
* be deleted from the download_table.
|
||||
*/
|
||||
if (mem_status == uemis_mem_status::full)
|
||||
do_delete_dives(data->log->dives.get(), match_dive_and_log);
|
||||
do_delete_dives(data->log->dives, match_dive_and_log);
|
||||
#if UEMIS_DEBUG & 4
|
||||
report_info("d_u_i out of memory, bailing instead of processing\n");
|
||||
#endif
|
||||
|
@ -1425,9 +1408,9 @@ std::string do_uemis_import(device_data_t *data)
|
|||
|
||||
/* Regardless on where we are with the memory situation, it's time now
|
||||
* to see if we have to clean some dead bodies from our download table */
|
||||
for (int next_table_index = 0; next_table_index < data->log->dives->nr; ) {
|
||||
if (data->log->dives->dives[next_table_index]->hidden_by_filter)
|
||||
uemis_delete_dive(data, data->log->dives->dives[next_table_index]->dcs[0].diveid);
|
||||
for (size_t next_table_index = 0; next_table_index < data->log->dives.size(); ) {
|
||||
if (data->log->dives[next_table_index]->hidden_by_filter)
|
||||
uemis_delete_dive(data, data->log->dives[next_table_index]->dcs[0].diveid);
|
||||
else
|
||||
next_table_index++;
|
||||
}
|
||||
|
@ -1446,7 +1429,7 @@ bail:
|
|||
else
|
||||
result = param_buff[2];
|
||||
}
|
||||
if (!data->log->dives->nr)
|
||||
if (data->log->dives.empty())
|
||||
result = translate("gettextFromC", ERR_NO_FILES);
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -7,8 +7,11 @@
|
|||
#include "core/errorhelper.h"
|
||||
#include "core/qthelper.h"
|
||||
#include "core/dive.h"
|
||||
#include "core/membuffer.h"
|
||||
#include "core/divelist.h"
|
||||
#include "core/divelog.h"
|
||||
#include "core/divesite.h"
|
||||
#include "core/membuffer.h"
|
||||
#include "core/range.h"
|
||||
#include "core/cloudstorage.h"
|
||||
#include "core/xmlparams.h"
|
||||
#ifndef SUBSURFACE_MOBILE
|
||||
|
@ -87,9 +90,7 @@ bool uploadDiveLogsDE::prepareDives(const QString &tempfile, bool selected)
|
|||
}
|
||||
|
||||
/* walk the dive list in chronological order */
|
||||
int i;
|
||||
struct dive *dive;
|
||||
for_each_dive (i, dive) {
|
||||
for (auto [i, dive]: enumerated_range(divelog.dives)) {
|
||||
char filename[PATH_MAX];
|
||||
int streamsize;
|
||||
char *membuf;
|
||||
|
@ -131,7 +132,7 @@ bool uploadDiveLogsDE::prepareDives(const QString &tempfile, bool selected)
|
|||
put_format(&mb, "</site>\n</divesites>\n");
|
||||
}
|
||||
|
||||
save_one_dive_to_mb(&mb, dive, false);
|
||||
save_one_dive_to_mb(&mb, *dive, false);
|
||||
|
||||
if (ds) {
|
||||
put_format(&mb, "</divelog>\n");
|
||||
|
|
|
@ -10,10 +10,12 @@
|
|||
#include <stdio.h>
|
||||
|
||||
#include "dive.h"
|
||||
#include "membuffer.h"
|
||||
#include "divelist.h"
|
||||
#include "divelog.h"
|
||||
#include "divesite.h"
|
||||
#include "errorhelper.h"
|
||||
#include "file.h"
|
||||
#include "membuffer.h"
|
||||
#include "save-html.h"
|
||||
#include "format.h"
|
||||
#include "worldmap-save.h"
|
||||
|
@ -28,43 +30,39 @@ static const char *getGoogleApi()
|
|||
|
||||
static void writeMarkers(struct membuffer *b, bool selected_only)
|
||||
{
|
||||
int i, dive_no = 0;
|
||||
struct dive *dive;
|
||||
std::string pre, post;
|
||||
int dive_no = 0;
|
||||
|
||||
for_each_dive (i, dive) {
|
||||
if (selected_only) {
|
||||
if (!dive->selected)
|
||||
for (auto &dive: divelog.dives) {
|
||||
if (selected_only && !dive->selected)
|
||||
continue;
|
||||
}
|
||||
struct dive_site *ds = get_dive_site_for_dive(dive);
|
||||
struct dive_site *ds = get_dive_site_for_dive(dive.get());
|
||||
if (!dive_site_has_gps_location(ds))
|
||||
continue;
|
||||
put_degrees(b, ds->location.lat, "temp = new google.maps.Marker({position: new google.maps.LatLng(", "");
|
||||
put_degrees(b, ds->location.lon, ",", ")});\n");
|
||||
put_string(b, "markers.push(temp);\ntempinfowindow = new google.maps.InfoWindow({content: '<div id=\"content\">'+'<div id=\"siteNotice\">'+'</div>'+'<div id=\"bodyContent\">");
|
||||
pre = format_string_std("<p>%s ", translate("gettextFromC", "Date:"));
|
||||
put_HTML_date(b, dive, pre.c_str(), "</p>");
|
||||
std::string pre = format_string_std("<p>%s ", translate("gettextFromC", "Date:"));
|
||||
put_HTML_date(b, *dive, pre.c_str(), "</p>");
|
||||
pre = format_string_std("<p>%s ", translate("gettextFromC", "Time:"));
|
||||
put_HTML_time(b, dive, pre.c_str(), "</p>");
|
||||
put_HTML_time(b, *dive, pre.c_str(), "</p>");
|
||||
pre = format_string_std("<p>%s ", translate("gettextFromC", "Duration:"));
|
||||
post = format_string_std(" %s</p>", translate("gettextFromC", "min"));
|
||||
std::string post = format_string_std(" %s</p>", translate("gettextFromC", "min"));
|
||||
put_duration(b, dive->duration, pre.c_str(), post.c_str());
|
||||
put_string(b, "<p> ");
|
||||
put_HTML_quoted(b, translate("gettextFromC", "Max. depth:"));
|
||||
put_HTML_depth(b, dive, " ", "</p>");
|
||||
put_HTML_depth(b, *dive, " ", "</p>");
|
||||
put_string(b, "<p> ");
|
||||
put_HTML_quoted(b, translate("gettextFromC", "Air temp.:"));
|
||||
put_HTML_airtemp(b, dive, " ", "</p>");
|
||||
put_HTML_airtemp(b, *dive, " ", "</p>");
|
||||
put_string(b, "<p> ");
|
||||
put_HTML_quoted(b, translate("gettextFromC", "Water temp.:"));
|
||||
put_HTML_watertemp(b, dive, " ", "</p>");
|
||||
put_HTML_watertemp(b, *dive, " ", "</p>");
|
||||
pre = format_string_std("<p>%s <b>", translate("gettextFromC", "Location:"));
|
||||
put_string(b, pre.c_str());
|
||||
put_HTML_quoted(b, get_dive_location(dive).c_str());
|
||||
put_HTML_quoted(b, get_dive_location(dive.get()).c_str());
|
||||
put_string(b, "</b></p>");
|
||||
pre = format_string_std("<p> %s ", translate("gettextFromC", "Notes:"));
|
||||
put_HTML_notes(b, dive, pre.c_str(), " </p>");
|
||||
put_HTML_notes(b, *dive, pre.c_str(), " </p>");
|
||||
put_string(b, "</p>'+'</div>'+'</div>'});\ninfowindows.push(tempinfowindow);\n");
|
||||
put_format(b, "google.maps.event.addListener(markers[%d], 'mouseover', function() {\ninfowindows[%d].open(map,markers[%d]);}", dive_no, dive_no, dive_no);
|
||||
put_format(b, ");google.maps.event.addListener(markers[%d], 'mouseout', function() {\ninfowindows[%d].close();});\n", dive_no, dive_no);
|
||||
|
|
|
@ -755,9 +755,9 @@ void DiveListView::contextMenuEvent(QContextMenuEvent *event)
|
|||
bottom = first_selected_dive();
|
||||
}
|
||||
}
|
||||
if (is_trip_before_after(top, (currentOrder == Qt::AscendingOrder)))
|
||||
if (divelog.is_trip_before_after(top, (currentOrder == Qt::AscendingOrder)))
|
||||
popup.addAction(tr("Add dive(s) to trip immediately above","",amount_selected), this, &DiveListView::addToTripAbove);
|
||||
if (is_trip_before_after(bottom, (currentOrder == Qt::DescendingOrder)))
|
||||
if (divelog.is_trip_before_after(bottom, (currentOrder == Qt::DescendingOrder)))
|
||||
popup.addAction(tr("Add dive(s) to trip immediately below","",amount_selected), this, &DiveListView::addToTripBelow);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -465,7 +465,7 @@ void DownloadFromDCWidget::on_downloadCancelRetryButton_clicked()
|
|||
qPrefDiveComputer::set_device(data->devName());
|
||||
|
||||
// before we start, remember where the dive_table ended
|
||||
previousLast = divelog.dives->nr;
|
||||
previousLast = static_cast<int>(divelog.dives.size());
|
||||
diveImportedModel->startDownload();
|
||||
|
||||
// FIXME: We should get the _actual_ device info instead of whatever
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include "findmovedimagesdialog.h"
|
||||
#include "core/divelog.h"
|
||||
#include "core/divelist.h"
|
||||
#include "core/picture.h"
|
||||
#include "core/qthelper.h"
|
||||
#include "desktop-widgets/divelistview.h" // TODO: used for lastUsedImageDir()
|
||||
|
@ -184,12 +186,12 @@ void FindMovedImagesDialog::on_scanButton_clicked()
|
|||
// We have to collect the names of the image filenames in the main thread
|
||||
bool onlySelected = ui.onlySelectedDives->isChecked();
|
||||
QVector<QString> imagePaths;
|
||||
int i;
|
||||
struct dive *dive;
|
||||
for_each_dive (i, dive)
|
||||
if (!onlySelected || dive->selected)
|
||||
for (auto &dive: divelog.dives) {
|
||||
if (!onlySelected || dive->selected) {
|
||||
for (auto &picture: dive->pictures)
|
||||
imagePaths.append(QString::fromStdString(picture.filename));
|
||||
}
|
||||
}
|
||||
stopScanning = 0;
|
||||
QFuture<QVector<Match>> future = QtConcurrent::run(
|
||||
// Note that we capture everything but "this" by copy to avoid dangling references.
|
||||
|
|
|
@ -430,7 +430,7 @@ void MainWindow::on_actionCloudstorageopen_triggered()
|
|||
// Return whether saving to cloud is OK. If it isn't, show an error return false.
|
||||
static bool saveToCloudOK()
|
||||
{
|
||||
if (!divelog.dives->nr) {
|
||||
if (divelog.dives.empty()) {
|
||||
report_error("%s", qPrintable(gettextFromC::tr("Don't save an empty log to the cloud")));
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include "printer.h"
|
||||
#include "templatelayout.h"
|
||||
#include "core/dive.h" // for get_dive_by_uniq_id()
|
||||
#include "core/divelist.h"
|
||||
#include "core/divelog.h"
|
||||
#include "core/selection.h"
|
||||
#include "core/statistics.h"
|
||||
#include "core/qthelper.h"
|
||||
|
@ -129,7 +130,7 @@ void Printer::render(int pages)
|
|||
// dive id field should be dive_{{dive_no}} se we remove the first 5 characters
|
||||
QString diveIdString = collection.at(elemNo).attribute("id");
|
||||
int diveId = diveIdString.remove(0, 5).toInt(0, 10);
|
||||
putProfileImage(collection.at(elemNo).geometry(), viewPort, &painter, get_dive_by_uniq_id(diveId), profile.get());
|
||||
putProfileImage(collection.at(elemNo).geometry(), viewPort, &painter, divelog.dives.get_by_uniq_id(diveId), profile.get());
|
||||
elemNo++;
|
||||
}
|
||||
|
||||
|
@ -160,10 +161,8 @@ std::vector<dive *> Printer::getDives() const
|
|||
return getDiveSelection();
|
||||
} else {
|
||||
std::vector<dive *> res;
|
||||
int i;
|
||||
struct dive *dive;
|
||||
for_each_dive (i, dive)
|
||||
res.push_back(dive);
|
||||
for (auto &d: divelog.dives)
|
||||
res.push_back(d.get());
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,12 +31,10 @@ void RenumberDialog::buttonClicked(QAbstractButton *button)
|
|||
if (ui.buttonBox->buttonRole(button) == QDialogButtonBox::AcceptRole) {
|
||||
// we remember a list from dive uuid to a new number
|
||||
QVector<QPair<dive *, int>> renumberedDives;
|
||||
int i;
|
||||
int newNr = ui.spinBox->value();
|
||||
struct dive *d;
|
||||
for_each_dive (i, d) {
|
||||
for (auto &d: divelog.dives) {
|
||||
if (!selectedOnly || d->selected)
|
||||
renumberedDives.append({ d, newNr++ });
|
||||
renumberedDives.append({ d.get(), newNr++ });
|
||||
}
|
||||
Command::renumberDives(renumberedDives);
|
||||
}
|
||||
|
|
|
@ -5,9 +5,12 @@
|
|||
#include <QVector>
|
||||
|
||||
#include "qmlmapwidgethelper.h"
|
||||
#include "core/divefilter.h"
|
||||
#include "core/divelist.h"
|
||||
#include "core/divelog.h"
|
||||
#include "core/divesite.h"
|
||||
#include "core/qthelper.h"
|
||||
#include "core/divefilter.h"
|
||||
#include "core/range.h"
|
||||
#include "qt-models/maplocationmodel.h"
|
||||
#include "qt-models/divelocationmodel.h"
|
||||
#ifndef SUBSURFACE_MOBILE
|
||||
|
@ -122,8 +125,6 @@ void MapWidgetHelper::reloadMapLocations()
|
|||
|
||||
void MapWidgetHelper::selectedLocationChanged(struct dive_site *ds_in)
|
||||
{
|
||||
int idx;
|
||||
struct dive *dive;
|
||||
QList<int> selectedDiveIds;
|
||||
|
||||
if (!ds_in)
|
||||
|
@ -133,8 +134,8 @@ void MapWidgetHelper::selectedLocationChanged(struct dive_site *ds_in)
|
|||
return;
|
||||
QGeoCoordinate locationCoord = location->coordinate;
|
||||
|
||||
for_each_dive (idx, dive) {
|
||||
struct dive_site *ds = get_dive_site_for_dive(dive);
|
||||
for (auto [idx, dive]: enumerated_range(divelog.dives)) {
|
||||
struct dive_site *ds = get_dive_site_for_dive(dive.get());
|
||||
if (!dive_site_has_gps_location(ds))
|
||||
continue;
|
||||
#ifndef SUBSURFACE_MOBILE
|
||||
|
@ -160,11 +161,9 @@ void MapWidgetHelper::selectedLocationChanged(struct dive_site *ds_in)
|
|||
|
||||
void MapWidgetHelper::selectVisibleLocations()
|
||||
{
|
||||
int idx;
|
||||
struct dive *dive;
|
||||
QList<int> selectedDiveIds;
|
||||
for_each_dive (idx, dive) {
|
||||
struct dive_site *ds = get_dive_site_for_dive(dive);
|
||||
for (auto [idx, dive]: enumerated_range(divelog.dives)) {
|
||||
struct dive_site *ds = get_dive_site_for_dive(dive.get());
|
||||
if (!dive_site_has_gps_location(ds))
|
||||
continue;
|
||||
const qreal latitude = ds->location.lat.udeg * 0.000001;
|
||||
|
|
|
@ -413,9 +413,9 @@ void QMLManager::openLocalThenRemote(QString url)
|
|||
qPrefTechnicalDetails::set_show_ccr_sensors(git_prefs.show_ccr_sensors);
|
||||
qPrefPartialPressureGas::set_po2(git_prefs.pp_graphs.po2);
|
||||
// the following steps can take a long time, so provide updates
|
||||
setNotificationText(tr("Processing %1 dives").arg(divelog.dives->nr));
|
||||
setNotificationText(tr("Processing %1 dives").arg(divelog.dives.size()));
|
||||
process_loaded_dives();
|
||||
setNotificationText(tr("%1 dives loaded from local dive data file").arg(divelog.dives->nr));
|
||||
setNotificationText(tr("%1 dives loaded from local dive data file").arg(divelog.dives.size()));
|
||||
}
|
||||
if (qPrefCloudStorage::cloud_verification_status() == qPrefCloudStorage::CS_NEED_TO_VERIFY) {
|
||||
appendTextToLog(QStringLiteral("have cloud credentials, but still needs PIN"));
|
||||
|
@ -478,7 +478,7 @@ void QMLManager::mergeLocalRepo()
|
|||
{
|
||||
struct divelog log;
|
||||
parse_file(qPrintable(nocloud_localstorage()), &log);
|
||||
add_imported_dives(&log, IMPORT_MERGE_ALL_TRIPS);
|
||||
add_imported_dives(log, IMPORT_MERGE_ALL_TRIPS);
|
||||
mark_divelist_changed(true);
|
||||
}
|
||||
|
||||
|
@ -588,7 +588,7 @@ void QMLManager::finishSetup()
|
|||
// successfully opened the local file, now add thigs to the dive list
|
||||
consumeFinishedLoad();
|
||||
updateHaveLocalChanges(true);
|
||||
appendTextToLog(QString("working in no-cloud mode, finished loading %1 dives from %2").arg(divelog.dives->nr).arg(existing_filename.c_str()));
|
||||
appendTextToLog(QString("working in no-cloud mode, finished loading %1 dives from %2").arg(divelog.dives.size()).arg(existing_filename.c_str()));
|
||||
}
|
||||
} else {
|
||||
qPrefCloudStorage::set_cloud_verification_status(qPrefCloudStorage::CS_UNKNOWN);
|
||||
|
@ -672,7 +672,7 @@ void QMLManager::saveCloudCredentials(const QString &newEmail, const QString &ne
|
|||
qPrefCloudStorage::set_cloud_storage_email(email);
|
||||
qPrefCloudStorage::set_cloud_storage_password(newPassword);
|
||||
|
||||
if (m_oldStatus == qPrefCloudStorage::CS_NOCLOUD && cloudCredentialsChanged && divelog.dives->nr) {
|
||||
if (m_oldStatus == qPrefCloudStorage::CS_NOCLOUD && cloudCredentialsChanged && divelog.dives.size()) {
|
||||
// we came from NOCLOUD and are connecting to a cloud account;
|
||||
// since we already have dives in the table, let's remember that so we can keep them
|
||||
noCloudToCloud = true;
|
||||
|
@ -830,7 +830,7 @@ void QMLManager::loadDivesWithValidCredentials()
|
|||
if (noCloudToCloud) {
|
||||
git_storage_update_progress(qPrintable(tr("Loading dives from local storage ('no cloud' mode)")));
|
||||
mergeLocalRepo();
|
||||
appendTextToLog(QStringLiteral("%1 dives loaded after importing nocloud local storage").arg(divelog.dives->nr));
|
||||
appendTextToLog(QStringLiteral("%1 dives loaded after importing nocloud local storage").arg(divelog.dives.size()));
|
||||
noCloudToCloud = false;
|
||||
mark_divelist_changed(true);
|
||||
emit syncStateChanged();
|
||||
|
@ -894,8 +894,8 @@ void QMLManager::consumeFinishedLoad()
|
|||
prefs.show_ccr_sensors = git_prefs.show_ccr_sensors;
|
||||
prefs.pp_graphs.po2 = git_prefs.pp_graphs.po2;
|
||||
process_loaded_dives();
|
||||
appendTextToLog(QStringLiteral("%1 dives loaded").arg(divelog.dives->nr));
|
||||
if (divelog.dives->nr == 0)
|
||||
appendTextToLog(QStringLiteral("%1 dives loaded").arg(divelog.dives.size()));
|
||||
if (divelog.dives.empty())
|
||||
setStartPageText(tr("Cloud storage open successfully. No dives in dive list."));
|
||||
}
|
||||
|
||||
|
@ -1168,7 +1168,7 @@ void QMLManager::commitChanges(QString diveId, QString number, QString date, QSt
|
|||
QString airtemp, QString watertemp, QString suit, QString buddy, QString diveGuide, QString tags, QString weight, QString notes,
|
||||
QStringList startpressure, QStringList endpressure, QStringList gasmix, QStringList usedCylinder, int rating, int visibility, QString state)
|
||||
{
|
||||
struct dive *orig = get_dive_by_uniq_id(diveId.toInt());
|
||||
struct dive *orig = divelog.dives.get_by_uniq_id(diveId.toInt());
|
||||
|
||||
if (!orig) {
|
||||
appendTextToLog("cannot commit changes: no dive");
|
||||
|
@ -1389,7 +1389,7 @@ void QMLManager::updateTripDetails(QString tripIdString, QString tripLocation, Q
|
|||
|
||||
void QMLManager::removeDiveFromTrip(int id)
|
||||
{
|
||||
struct dive *d = get_dive_by_uniq_id(id);
|
||||
struct dive *d = divelog.dives.get_by_uniq_id(id);
|
||||
if (!d) {
|
||||
appendTextToLog(QString("Asked to remove non-existing dive with id %1 from its trip.").arg(id));
|
||||
return;
|
||||
|
@ -1406,7 +1406,7 @@ void QMLManager::removeDiveFromTrip(int id)
|
|||
|
||||
void QMLManager::addTripForDive(int id)
|
||||
{
|
||||
struct dive *d = get_dive_by_uniq_id(id);
|
||||
struct dive *d = divelog.dives.get_by_uniq_id(id);
|
||||
if (!d) {
|
||||
appendTextToLog(QString("Asked to create trip for non-existing dive with id %1").arg(id));
|
||||
return;
|
||||
|
@ -1423,7 +1423,7 @@ void QMLManager::addTripForDive(int id)
|
|||
|
||||
void QMLManager::addDiveToTrip(int id, int tripId)
|
||||
{
|
||||
struct dive *d = get_dive_by_uniq_id(id);
|
||||
struct dive *d = divelog.dives.get_by_uniq_id(id);
|
||||
if (!d) {
|
||||
appendTextToLog(QString("Asked to add non-existing dive with id %1 to trip %2.").arg(id).arg(tripId));
|
||||
return;
|
||||
|
@ -1575,12 +1575,10 @@ void QMLManager::redo()
|
|||
|
||||
void QMLManager::selectDive(int id)
|
||||
{
|
||||
int i;
|
||||
extern int amount_selected;
|
||||
struct dive *dive = NULL;
|
||||
|
||||
amount_selected = 0;
|
||||
for_each_dive (i, dive) {
|
||||
for (auto &dive: divelog.dives) {
|
||||
dive->selected = (dive->id == id);
|
||||
if (dive->selected)
|
||||
amount_selected++;
|
||||
|
@ -1591,7 +1589,7 @@ void QMLManager::selectDive(int id)
|
|||
|
||||
void QMLManager::deleteDive(int id)
|
||||
{
|
||||
struct dive *d = get_dive_by_uniq_id(id);
|
||||
struct dive *d = divelog.dives.get_by_uniq_id(id);
|
||||
if (!d) {
|
||||
appendTextToLog("trying to delete non-existing dive");
|
||||
return;
|
||||
|
@ -1602,7 +1600,7 @@ void QMLManager::deleteDive(int id)
|
|||
|
||||
void QMLManager::toggleDiveInvalid(int id)
|
||||
{
|
||||
struct dive *d = get_dive_by_uniq_id(id);
|
||||
struct dive *d = divelog.dives.get_by_uniq_id(id);
|
||||
if (!d) {
|
||||
appendTextToLog("trying to toggle invalid flag of non-existing dive");
|
||||
return;
|
||||
|
@ -1693,7 +1691,7 @@ bool QMLManager::toggleWeights(bool toggle)
|
|||
|
||||
void QMLManager::copyDiveData(int id)
|
||||
{
|
||||
m_copyPasteDive = get_dive_by_uniq_id(id);
|
||||
m_copyPasteDive = divelog.dives.get_by_uniq_id(id);
|
||||
if (!m_copyPasteDive) {
|
||||
appendTextToLog("trying to copy non-existing dive");
|
||||
return;
|
||||
|
@ -1781,7 +1779,7 @@ void QMLManager::setStartPageText(const QString& text)
|
|||
QString QMLManager::getNumber(const QString& diveId)
|
||||
{
|
||||
int dive_id = diveId.toInt();
|
||||
struct dive *d = get_dive_by_uniq_id(dive_id);
|
||||
struct dive *d = divelog.dives.get_by_uniq_id(dive_id);
|
||||
QString number;
|
||||
if (d)
|
||||
number = QString::number(d->number);
|
||||
|
@ -1791,7 +1789,7 @@ QString QMLManager::getNumber(const QString& diveId)
|
|||
QString QMLManager::getDate(const QString& diveId)
|
||||
{
|
||||
int dive_id = diveId.toInt();
|
||||
struct dive *d = get_dive_by_uniq_id(dive_id);
|
||||
struct dive *d = divelog.dives.get_by_uniq_id(dive_id);
|
||||
QString datestring;
|
||||
if (d)
|
||||
datestring = get_short_dive_date_string(d->when);
|
||||
|
@ -2360,7 +2358,7 @@ void QMLManager::importCacheRepo(QString repo)
|
|||
QString repoPath = QString("%1/cloudstorage/%2").arg(system_default_directory()).arg(repo);
|
||||
appendTextToLog(QString("importing %1").arg(repoPath));
|
||||
parse_file(qPrintable(repoPath), &log);
|
||||
add_imported_dives(&log, IMPORT_MERGE_ALL_TRIPS);
|
||||
add_imported_dives(log, IMPORT_MERGE_ALL_TRIPS);
|
||||
changesNeedSaving();
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include "qmlprofile.h"
|
||||
#include "profilescene.h"
|
||||
#include "mobile-widgets/qmlmanager.h"
|
||||
#include "core/divelist.h"
|
||||
#include "core/errorhelper.h"
|
||||
#include "core/subsurface-float.h"
|
||||
#include "core/metrics.h"
|
||||
|
@ -60,7 +61,7 @@ void QMLProfile::paint(QPainter *painter)
|
|||
painter->resetTransform();
|
||||
if (m_diveId < 0)
|
||||
return;
|
||||
struct dive *d = get_dive_by_uniq_id(m_diveId);
|
||||
struct dive *d = divelog.dives.get_by_uniq_id(m_diveId);
|
||||
if (!d)
|
||||
return;
|
||||
m_profileWidget->draw(painter, painterRect, d, m_dc, nullptr, false);
|
||||
|
@ -143,7 +144,7 @@ void QMLProfile::prevDC()
|
|||
|
||||
void QMLProfile::rotateDC(int dir)
|
||||
{
|
||||
struct dive *d = get_dive_by_uniq_id(m_diveId);
|
||||
struct dive *d = divelog.dives.get_by_uniq_id(m_diveId);
|
||||
if (!d)
|
||||
return;
|
||||
int numDC = number_of_computers(d);
|
||||
|
@ -157,6 +158,6 @@ void QMLProfile::rotateDC(int dir)
|
|||
|
||||
int QMLProfile::numDC() const
|
||||
{
|
||||
struct dive *d = get_dive_by_uniq_id(m_diveId);
|
||||
struct dive *d = divelog.dives.get_by_uniq_id(m_diveId);
|
||||
return d ? number_of_computers(d) : 0;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include "qt-models/completionmodels.h"
|
||||
#include "core/dive.h"
|
||||
#include "core/divelist.h"
|
||||
#include "core/divelog.h"
|
||||
#include "core/tag.h"
|
||||
#include <QSet>
|
||||
|
||||
|
@ -31,10 +33,8 @@ void CompletionModelBase::divesChanged(const QVector<dive *> &, DiveField field)
|
|||
static QStringList getCSVList(const std::string dive::*item)
|
||||
{
|
||||
QSet<QString> set;
|
||||
struct dive *dive;
|
||||
int i = 0;
|
||||
for_each_dive (i, dive) {
|
||||
QString str = QString::fromStdString(dive->*item);
|
||||
for (auto &dive: divelog.dives) {
|
||||
QString str = QString::fromStdString(dive.get()->*item);
|
||||
for (const QString &value: str.split(",", SKIP_EMPTY))
|
||||
set.insert(value.trimmed());
|
||||
}
|
||||
|
@ -66,9 +66,7 @@ bool DiveGuideCompletionModel::relevantDiveField(const DiveField &f)
|
|||
QStringList SuitCompletionModel::getStrings()
|
||||
{
|
||||
QStringList list;
|
||||
struct dive *dive;
|
||||
int i = 0;
|
||||
for_each_dive (i, dive) {
|
||||
for (auto &dive: divelog.dives) {
|
||||
QString suit = QString::fromStdString(dive->suit);
|
||||
if (!list.contains(suit))
|
||||
list.append(suit);
|
||||
|
|
|
@ -16,7 +16,7 @@ int DiveImportedModel::columnCount(const QModelIndex&) const
|
|||
|
||||
int DiveImportedModel::rowCount(const QModelIndex&) const
|
||||
{
|
||||
return log.dives->nr;
|
||||
return static_cast<int>(log.dives.size());
|
||||
}
|
||||
|
||||
QVariant DiveImportedModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
|
@ -46,15 +46,10 @@ QVariant DiveImportedModel::headerData(int section, Qt::Orientation orientation,
|
|||
|
||||
QVariant DiveImportedModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
if (index.row() < 0 || static_cast<size_t>(index.row()) >= log.dives.size())
|
||||
return QVariant();
|
||||
|
||||
if (index.row() >= log.dives->nr)
|
||||
return QVariant();
|
||||
|
||||
struct dive *d = get_dive_from_table(index.row(), log.dives.get());
|
||||
if (!d)
|
||||
return QVariant();
|
||||
const struct dive &d = *log.dives[index.row()];
|
||||
|
||||
// widgets access the model via index.column(), qml via role.
|
||||
int column = index.column();
|
||||
|
@ -66,11 +61,11 @@ QVariant DiveImportedModel::data(const QModelIndex &index, int role) const
|
|||
if (role == Qt::DisplayRole) {
|
||||
switch (column) {
|
||||
case 0:
|
||||
return QVariant(get_short_dive_date_string(d->when));
|
||||
return QVariant(get_short_dive_date_string(d.when));
|
||||
case 1:
|
||||
return QVariant(get_dive_duration_string(d->duration.seconds, tr("h"), tr("min")));
|
||||
return QVariant(get_dive_duration_string(d.duration.seconds, tr("h"), tr("min")));
|
||||
case 2:
|
||||
return QVariant(get_depth_string(d->maxdepth.mm, true, false));
|
||||
return QVariant(get_depth_string(d.maxdepth.mm, true, false));
|
||||
case 3:
|
||||
return checkStates[index.row()];
|
||||
}
|
||||
|
@ -90,8 +85,10 @@ void DiveImportedModel::changeSelected(QModelIndex clickedIndex)
|
|||
|
||||
void DiveImportedModel::selectAll()
|
||||
{
|
||||
if (log.dives.empty())
|
||||
return;
|
||||
std::fill(checkStates.begin(), checkStates.end(), true);
|
||||
dataChanged(index(0, 0), index(log.dives->nr - 1, 0), QVector<int>() << Qt::CheckStateRole << Selected);
|
||||
dataChanged(index(0, 0), index(log.dives.size() - 1, 0), QVector<int>() << Qt::CheckStateRole << Selected);
|
||||
}
|
||||
|
||||
void DiveImportedModel::selectRow(int row)
|
||||
|
@ -102,8 +99,10 @@ void DiveImportedModel::selectRow(int row)
|
|||
|
||||
void DiveImportedModel::selectNone()
|
||||
{
|
||||
if (log.dives.empty())
|
||||
return;
|
||||
std::fill(checkStates.begin(), checkStates.end(), false);
|
||||
dataChanged(index(0, 0), index(log.dives->nr - 1, 0 ), QVector<int>() << Qt::CheckStateRole << Selected);
|
||||
dataChanged(index(0, 0), index(log.dives.size() - 1, 0 ), QVector<int>() << Qt::CheckStateRole << Selected);
|
||||
}
|
||||
|
||||
Qt::ItemFlags DiveImportedModel::flags(const QModelIndex &index) const
|
||||
|
@ -129,7 +128,7 @@ void DiveImportedModel::downloadThreadFinished()
|
|||
log.clear();
|
||||
std::swap(log, thread.log);
|
||||
|
||||
checkStates.resize(log.dives->nr);
|
||||
checkStates.resize(log.dives.size());
|
||||
std::fill(checkStates.begin(), checkStates.end(), true);
|
||||
|
||||
endResetModel();
|
||||
|
@ -166,24 +165,24 @@ struct divelog DiveImportedModel::consumeTables()
|
|||
|
||||
int DiveImportedModel::numDives() const
|
||||
{
|
||||
return log.dives->nr;
|
||||
return static_cast<size_t>(log.dives.size());
|
||||
}
|
||||
|
||||
// Delete non-selected dives
|
||||
void DiveImportedModel::deleteDeselected()
|
||||
{
|
||||
int total = log.dives->nr;
|
||||
int j = 0;
|
||||
for (int i = 0; i < total; i++) {
|
||||
size_t total = log.dives.size();
|
||||
size_t j = 0;
|
||||
for (size_t i = 0; i < total; i++) {
|
||||
if (checkStates[i]) {
|
||||
j++;
|
||||
} else {
|
||||
beginRemoveRows(QModelIndex(), j, j);
|
||||
delete_dive_from_table(log.dives.get(), j);
|
||||
log.dives.erase(log.dives.begin() + j);
|
||||
endRemoveRows();
|
||||
}
|
||||
}
|
||||
checkStates.resize(log.dives->nr);
|
||||
checkStates.resize(log.dives.size());
|
||||
std::fill(checkStates.begin(), checkStates.end(), true);
|
||||
}
|
||||
|
||||
|
@ -194,7 +193,7 @@ void DiveImportedModel::recordDives(int flags)
|
|||
deleteDeselected();
|
||||
|
||||
struct divelog log = consumeTables();
|
||||
if (log.dives->nr > 0) {
|
||||
if (!log.dives.empty()) {
|
||||
auto data = thread.data();
|
||||
Command::importDives(&log, flags, data->devName());
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ PictureEntry::PictureEntry(dive *dIn, const picture &p) : d(dIn),
|
|||
// should give the same result].
|
||||
bool PictureEntry::operator<(const PictureEntry &p2) const
|
||||
{
|
||||
if (int cmp = comp_dives(d, p2.d))
|
||||
if (int cmp = comp_dives_ptr(d, p2.d))
|
||||
return cmp < 0;
|
||||
if (offsetSeconds != p2.offsetSeconds)
|
||||
return offsetSeconds < p2.offsetSeconds;
|
||||
|
|
|
@ -102,9 +102,8 @@ void DivePlannerPointsModel::setupStartTime()
|
|||
// if the latest dive is in the future, then start an hour after it ends
|
||||
// otherwise start an hour from now
|
||||
startTime = QDateTime::currentDateTimeUtc().addSecs(3600 + gettimezoneoffset());
|
||||
if (divelog.dives->nr > 0) {
|
||||
struct dive *d = get_dive(divelog.dives->nr - 1);
|
||||
time_t ends = d->endtime();
|
||||
if (!divelog.dives.empty()) {
|
||||
time_t ends = divelog.dives.back()->endtime();
|
||||
time_t diff = ends - dateTimeToTimestamp(startTime);
|
||||
if (diff > 0)
|
||||
startTime = startTime.addSecs(diff + 3600);
|
||||
|
@ -1097,7 +1096,7 @@ void DivePlannerPointsModel::updateDiveProfile()
|
|||
|
||||
|
||||
#if DEBUG_PLAN
|
||||
save_dive(stderr, d);
|
||||
save_dive(stderr, *d);
|
||||
dump_plan(&diveplan);
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include "qt-models/divesummarymodel.h"
|
||||
#include "core/dive.h"
|
||||
#include "core/divelist.h"
|
||||
#include "core/divelog.h"
|
||||
#include "core/qthelper.h"
|
||||
|
||||
#include <QLocale>
|
||||
|
@ -160,13 +162,10 @@ static void calculateDive(struct dive *dive, Stats &stats)
|
|||
static Stats loopDives(timestamp_t start)
|
||||
{
|
||||
Stats stats;
|
||||
struct dive *dive;
|
||||
int i;
|
||||
|
||||
for_each_dive (i, dive) {
|
||||
for (auto &dive: divelog.dives) {
|
||||
// check if dive is newer than primaryStart (add to first column)
|
||||
if (dive->when > start)
|
||||
calculateDive(dive, stats);
|
||||
calculateDive(dive.get(), stats);
|
||||
}
|
||||
return stats;
|
||||
}
|
||||
|
|
|
@ -707,18 +707,15 @@ void DiveTripModelTree::populate()
|
|||
// we want this to be two calls as the second text is overwritten below by the lines starting with "\r"
|
||||
uiNotification(QObject::tr("populate data model"));
|
||||
uiNotification(QObject::tr("start processing"));
|
||||
for (int i = 0; i < divelog.dives->nr; ++i) {
|
||||
dive *d = get_dive(i);
|
||||
if (!d) // should never happen
|
||||
continue;
|
||||
update_cylinder_related_info(d);
|
||||
for (auto &d: divelog.dives) {
|
||||
update_cylinder_related_info(d.get());
|
||||
if (d->hidden_by_filter)
|
||||
continue;
|
||||
dive_trip *trip = d->divetrip;
|
||||
|
||||
// If this dive doesn't have a trip, add as top-level item.
|
||||
if (!trip) {
|
||||
items.emplace_back(d);
|
||||
items.emplace_back(d.get());
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -728,16 +725,16 @@ void DiveTripModelTree::populate()
|
|||
{ return item.d_or_t.trip == trip; });
|
||||
if (it == items.end()) {
|
||||
// We didn't find an entry for this trip -> add one
|
||||
items.emplace_back(trip, d);
|
||||
items.emplace_back(trip, d.get());
|
||||
} else {
|
||||
// We found the trip -> simply add the dive
|
||||
it->dives.push_back(d);
|
||||
it->dives.push_back(d.get());
|
||||
}
|
||||
}
|
||||
|
||||
// Remember the index of the current dive
|
||||
oldCurrent = current_dive;
|
||||
uiNotification(QObject::tr("%1 dives processed").arg(divelog.dives->nr));
|
||||
uiNotification(QObject::tr("%1 dives processed").arg(divelog.dives.size()));
|
||||
}
|
||||
|
||||
int DiveTripModelTree::rowCount(const QModelIndex &parent) const
|
||||
|
@ -846,7 +843,7 @@ void processByTrip(QVector<dive *> dives, Function action)
|
|||
{
|
||||
// Sort lexicographically by trip then according to the dive_less_than() function.
|
||||
std::sort(dives.begin(), dives.end(), [](const dive *d1, const dive *d2)
|
||||
{ return d1->divetrip == d2->divetrip ? dive_less_than(d1, d2) : d1->divetrip < d2->divetrip; });
|
||||
{ return d1->divetrip == d2->divetrip ? dive_less_than_ptr(d1, d2) : d1->divetrip < d2->divetrip; });
|
||||
|
||||
// Then, process the dives in batches by trip
|
||||
int i, j; // Begin and end of batch
|
||||
|
@ -995,7 +992,7 @@ void DiveTripModelTree::addDivesToTrip(int trip, const QVector<dive *> &dives)
|
|||
QModelIndex parent = createIndex(trip, 0, noParent);
|
||||
|
||||
addInBatches(items[trip].dives, dives,
|
||||
[](dive *d, dive *d2) { return dive_less_than(d, d2); }, // comp
|
||||
[](dive *d, dive *d2) { return dive_less_than_ptr(d, d2); }, // comp
|
||||
[&](std::vector<dive *> &items, const QVector<dive *> &dives, int idx, int from, int to) { // inserter
|
||||
beginInsertRows(parent, idx, idx + to - from - 1);
|
||||
items.insert(items.begin() + idx, dives.begin() + from, dives.begin() + to);
|
||||
|
@ -1485,12 +1482,11 @@ void DiveTripModelList::populate()
|
|||
DiveFilter::instance()->reset(); // The data was reset - update filter status. TODO: should this really be done here?
|
||||
|
||||
// Fill model
|
||||
items.reserve(divelog.dives->nr);
|
||||
for (int i = 0; i < divelog.dives->nr; ++i) {
|
||||
dive *d = get_dive(i);
|
||||
items.reserve(divelog.dives.size());
|
||||
for (auto &d: divelog.dives) {
|
||||
if (!d || d->hidden_by_filter)
|
||||
continue;
|
||||
items.push_back(d);
|
||||
items.push_back(d.get());
|
||||
}
|
||||
|
||||
// Remember the index of the current dive
|
||||
|
@ -1555,9 +1551,9 @@ QVariant DiveTripModelList::data(const QModelIndex &index, int role) const
|
|||
|
||||
void DiveTripModelList::addDives(QVector<dive *> &dives)
|
||||
{
|
||||
std::sort(dives.begin(), dives.end(), dive_less_than);
|
||||
std::sort(dives.begin(), dives.end(), dive_less_than_ptr);
|
||||
addInBatches(items, dives,
|
||||
&dive_less_than, // comp
|
||||
&dive_less_than_ptr, // comp
|
||||
[&](std::vector<dive *> &items, const QVector<dive *> &dives, int idx, int from, int to) { // inserter
|
||||
beginInsertRows(QModelIndex(), idx, idx + to - from - 1);
|
||||
items.insert(items.begin() + idx, dives.begin() + from, dives.begin() + to);
|
||||
|
@ -1567,7 +1563,7 @@ void DiveTripModelList::addDives(QVector<dive *> &dives)
|
|||
|
||||
void DiveTripModelList::removeDives(QVector<dive *> dives)
|
||||
{
|
||||
std::sort(dives.begin(), dives.end(), dive_less_than);
|
||||
std::sort(dives.begin(), dives.end(), dive_less_than_ptr);
|
||||
processRangesZip(items, dives,
|
||||
std::equal_to<const dive *>(), // Condition: dive-pointers are equal
|
||||
[&](std::vector<dive *> &items, const QVector<dive *> &, int from, int to, int) -> int { // Action
|
||||
|
@ -1607,7 +1603,7 @@ void DiveTripModelList::diveSiteChanged(dive_site *ds, int field)
|
|||
void DiveTripModelList::divesChanged(const QVector<dive *> &divesIn)
|
||||
{
|
||||
QVector<dive *> dives = divesIn;
|
||||
std::sort(dives.begin(), dives.end(), dive_less_than);
|
||||
std::sort(dives.begin(), dives.end(), dive_less_than_ptr);
|
||||
|
||||
ShownChange shownChange = updateShown(dives);
|
||||
removeDives(shownChange.newHidden);
|
||||
|
@ -1641,7 +1637,7 @@ void DiveTripModelList::divesTimeChanged(timestamp_t delta, const QVector<dive *
|
|||
QVector<dive *> dives = visibleDives(divesIn);
|
||||
if (dives.empty())
|
||||
return;
|
||||
std::sort(dives.begin(), dives.end(), dive_less_than);
|
||||
std::sort(dives.begin(), dives.end(), dive_less_than_ptr);
|
||||
|
||||
// See comment for DiveTripModelTree::divesTimeChanged above.
|
||||
divesDeletedInternal(dives); // Use internal version to keep current dive
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
my $input = $ARGV[0];
|
||||
my $source = `clang-format $input`;
|
||||
|
||||
# for_each_dive (...) and friends...
|
||||
# for_each (...) and friends...
|
||||
$source =~ s/(?:\G|^)(.*each.*\(.*) \* (\S.*\))$/$1 *$2/img; # if a variable is declared in the argument, '*' is an indicator for a pointer, not arithmatic
|
||||
$source =~ s/(?:\G|^)(.*each.*\(.*) \& (\S.*\))$/$1 &$2/img; # if a variable is declared in the argument, '&' is an indicator for a reference, not bit logic
|
||||
$source =~ s/(?:\G|^)(.*each[^\s(]*)\s*(\(.*)$/$1 $2/img; # we want exactly one space between keyword and opening parenthesis '('
|
||||
|
|
|
@ -1016,11 +1016,11 @@ void smartrak_import(const char *file, struct divelog *log)
|
|||
smtk_parse_bookmarks(mdb_clon, smtkdive.get(), (char *)col[0]->bind_ptr);
|
||||
concat(smtkdive->notes, "\n", std::string((char *)col[coln(REMARKS)]->bind_ptr));
|
||||
|
||||
record_dive_to_table(smtkdive.release(), log->dives.get());
|
||||
log->dives.record_dive(std::move(smtkdive));
|
||||
}
|
||||
mdb_free_catalog(mdb_clon);
|
||||
mdb->catalog = NULL;
|
||||
mdb_close(mdb_clon);
|
||||
mdb_close(mdb);
|
||||
sort_dive_table(log->dives.get());
|
||||
log->dives.sort();
|
||||
}
|
||||
|
|
|
@ -1381,7 +1381,7 @@ struct DiveNrVariable : public StatsVariableTemplate<StatsVariable::Type::Numeri
|
|||
return StatsTranslations::tr("Dive #");
|
||||
}
|
||||
std::vector<const StatsBinner *> binners() const override {
|
||||
if (divelog.dives->nr > 1000)
|
||||
if (divelog.dives.size() > 1000)
|
||||
return { &dive_nr_binner_20, &dive_nr_binner_50, &dive_nr_binner_100, &dive_nr_binner_200 };
|
||||
else
|
||||
return { &dive_nr_binner_5, &dive_nr_binner_10, &dive_nr_binner_20, &dive_nr_binner_50 };
|
||||
|
|
|
@ -106,7 +106,6 @@ int main(int argc, char **argv)
|
|||
if (!quit)
|
||||
run_ui();
|
||||
exit_ui();
|
||||
divelog.clear();
|
||||
parse_xml_exit();
|
||||
subsurface_console_exit();
|
||||
|
||||
|
|
|
@ -109,7 +109,6 @@ int main(int argc, char **argv)
|
|||
printf("No log files given, not saving dive data.\n");
|
||||
printf("Give a log file name as argument, or configure a cloud URL.\n");
|
||||
}
|
||||
divelog.clear();
|
||||
parse_xml_exit();
|
||||
|
||||
// Sync struct preferences to disk
|
||||
|
|
|
@ -92,7 +92,6 @@ int main(int argc, char **argv)
|
|||
if (!quit)
|
||||
run_mobile_ui(initial_font_size);
|
||||
exit_ui();
|
||||
divelog.clear();
|
||||
parse_xml_exit();
|
||||
subsurface_console_exit();
|
||||
|
||||
|
|
|
@ -363,7 +363,7 @@ void TestGitStorage::testGitStorageCloudMerge2()
|
|||
QCOMPARE(parse_file(cloudTestRepo.c_str(), &divelog), 0);
|
||||
process_loaded_dives();
|
||||
struct dive *dive = get_dive(1);
|
||||
divelog.delete_single_dive(1);
|
||||
divelog.delete_multiple_dives(std::vector<struct dive *>{ dive });
|
||||
QCOMPARE(save_dives("./SampleDivesMinus1.ssrf"), 0);
|
||||
git_local_only = true;
|
||||
QCOMPARE(save_dives(localCacheRepo.c_str()), 0);
|
||||
|
|
|
@ -28,9 +28,9 @@ void TestMerge::testMergeEmpty()
|
|||
*/
|
||||
struct divelog log;
|
||||
QCOMPARE(parse_file(SUBSURFACE_TEST_DATA "/dives/test47.xml", &log), 0);
|
||||
add_imported_dives(&log, IMPORT_MERGE_ALL_TRIPS);
|
||||
add_imported_dives(log, IMPORT_MERGE_ALL_TRIPS);
|
||||
QCOMPARE(parse_file(SUBSURFACE_TEST_DATA "/dives/test48.xml", &log), 0);
|
||||
add_imported_dives(&log, IMPORT_MERGE_ALL_TRIPS);
|
||||
add_imported_dives(log, IMPORT_MERGE_ALL_TRIPS);
|
||||
QCOMPARE(save_dives("./testmerge47+48.ssrf"), 0);
|
||||
QFile org(SUBSURFACE_TEST_DATA "/dives/test47+48.xml");
|
||||
org.open(QFile::ReadOnly);
|
||||
|
@ -51,9 +51,9 @@ void TestMerge::testMergeBackwards()
|
|||
*/
|
||||
struct divelog log;
|
||||
QCOMPARE(parse_file(SUBSURFACE_TEST_DATA "/dives/test48.xml", &log), 0);
|
||||
add_imported_dives(&log, IMPORT_MERGE_ALL_TRIPS);
|
||||
add_imported_dives(log, IMPORT_MERGE_ALL_TRIPS);
|
||||
QCOMPARE(parse_file(SUBSURFACE_TEST_DATA "/dives/test47.xml", &log), 0);
|
||||
add_imported_dives(&log, IMPORT_MERGE_ALL_TRIPS);
|
||||
add_imported_dives(log, IMPORT_MERGE_ALL_TRIPS);
|
||||
QCOMPARE(save_dives("./testmerge47+48.ssrf"), 0);
|
||||
QFile org(SUBSURFACE_TEST_DATA "/dives/test48+47.xml");
|
||||
org.open(QFile::ReadOnly);
|
||||
|
|
|
@ -118,19 +118,21 @@ int TestParse::parseV3()
|
|||
|
||||
void TestParse::testParse()
|
||||
{
|
||||
// On some platforms (Windows) size_t has a different format string.
|
||||
// Let's just cast to int.
|
||||
QCOMPARE(parseCSV(0, SUBSURFACE_TEST_DATA "/dives/test41.csv"), 0);
|
||||
fprintf(stderr, "number of dives %d \n", divelog.dives->nr);
|
||||
fprintf(stderr, "number of dives %d \n", static_cast<int>(divelog.dives.size()));
|
||||
|
||||
QCOMPARE(parseDivingLog(), 0);
|
||||
fprintf(stderr, "number of dives %d \n", divelog.dives->nr);
|
||||
fprintf(stderr, "number of dives %d \n", static_cast<int>(divelog.dives.size()));
|
||||
|
||||
QCOMPARE(parseV2NoQuestion(), 0);
|
||||
fprintf(stderr, "number of dives %d \n", divelog.dives->nr);
|
||||
fprintf(stderr, "number of dives %d \n", static_cast<int>(divelog.dives.size()));
|
||||
|
||||
QCOMPARE(parseV3(), 0);
|
||||
fprintf(stderr, "number of dives %d \n", divelog.dives->nr);
|
||||
fprintf(stderr, "number of dives %d \n", static_cast<int>(divelog.dives.size()));
|
||||
|
||||
sort_dive_table(divelog.dives);
|
||||
divelog.dives.sort();
|
||||
|
||||
QCOMPARE(save_dives("./testout.ssrf"), 0);
|
||||
FILE_COMPARE("./testout.ssrf",
|
||||
|
@ -142,7 +144,7 @@ void TestParse::testParseDM4()
|
|||
QCOMPARE(sqlite3_open(SUBSURFACE_TEST_DATA "/dives/TestDiveDM4.db", &_sqlite3_handle), 0);
|
||||
QCOMPARE(parse_dm4_buffer(_sqlite3_handle, 0, 0, 0, &divelog), 0);
|
||||
|
||||
sort_dive_table(divelog.dives);
|
||||
divelog.dives.sort();
|
||||
|
||||
QCOMPARE(save_dives("./testdm4out.ssrf"), 0);
|
||||
FILE_COMPARE("./testdm4out.ssrf",
|
||||
|
@ -154,7 +156,7 @@ void TestParse::testParseDM5()
|
|||
QCOMPARE(sqlite3_open(SUBSURFACE_TEST_DATA "/dives/TestDiveDM5.db", &_sqlite3_handle), 0);
|
||||
QCOMPARE(parse_dm5_buffer(_sqlite3_handle, 0, 0, 0, &divelog), 0);
|
||||
|
||||
sort_dive_table(divelog.dives);
|
||||
divelog.dives.sort();
|
||||
|
||||
QCOMPARE(save_dives("./testdm5out.ssrf"), 0);
|
||||
FILE_COMPARE("./testdm5out.ssrf",
|
||||
|
@ -186,19 +188,19 @@ void TestParse::testParseHUDC()
|
|||
¶ms, "csv", &divelog),
|
||||
0);
|
||||
|
||||
QCOMPARE(divelog.dives->nr, 1);
|
||||
QCOMPARE(divelog.dives.size(), 1);
|
||||
|
||||
/*
|
||||
* CSV import uses time and date stamps relative to current
|
||||
* time, thus we need to use a static (random) timestamp
|
||||
*/
|
||||
if (divelog.dives->nr > 0) {
|
||||
struct dive *dive = divelog.dives->dives[divelog.dives->nr - 1];
|
||||
dive->when = 1255152761;
|
||||
dive->dcs[0].when = 1255152761;
|
||||
if (!divelog.dives.empty()) {
|
||||
struct dive &dive = *divelog.dives.back();
|
||||
dive.when = 1255152761;
|
||||
dive.dcs[0].when = 1255152761;
|
||||
}
|
||||
|
||||
sort_dive_table(divelog.dives);
|
||||
divelog.dives.sort();
|
||||
|
||||
QCOMPARE(save_dives("./testhudcout.ssrf"), 0);
|
||||
FILE_COMPARE("./testhudcout.ssrf",
|
||||
|
@ -232,12 +234,12 @@ void TestParse::testParseNewFormat()
|
|||
.toLatin1()
|
||||
.data(), &divelog),
|
||||
0);
|
||||
QCOMPARE(divelog.dives->nr, i + 1);
|
||||
QCOMPARE(divelog.dives.size(), i + 1);
|
||||
}
|
||||
|
||||
sort_dive_table(divelog.dives);
|
||||
divelog.dives.sort();
|
||||
|
||||
fprintf(stderr, "number of dives %d \n", divelog.dives->nr);
|
||||
fprintf(stderr, "number of dives %d \n", static_cast<int>(divelog.dives.size()));
|
||||
QCOMPARE(save_dives("./testsbnewout.ssrf"), 0);
|
||||
|
||||
// Currently the CSV parse fails
|
||||
|
@ -253,9 +255,9 @@ void TestParse::testParseDLD()
|
|||
QVERIFY(err > 0);
|
||||
QVERIFY(try_to_open_zip(filename.toLatin1().data(), &divelog) > 0);
|
||||
|
||||
fprintf(stderr, "number of dives from DLD: %d \n", divelog.dives->nr);
|
||||
fprintf(stderr, "number of dives from DLD: %d \n", static_cast<int>(divelog.dives.size()));
|
||||
|
||||
sort_dive_table(divelog.dives);
|
||||
divelog.dives.sort();
|
||||
|
||||
// Compare output
|
||||
QCOMPARE(save_dives("./testdldout.ssrf"), 0);
|
||||
|
@ -271,7 +273,7 @@ void TestParse::testParseMerge()
|
|||
QCOMPARE(parse_file(SUBSURFACE_TEST_DATA "/dives/ostc.xml", &divelog), 0);
|
||||
QCOMPARE(parse_file(SUBSURFACE_TEST_DATA "/dives/vyper.xml", &divelog), 0);
|
||||
|
||||
sort_dive_table(divelog.dives);
|
||||
divelog.dives.sort();
|
||||
|
||||
QCOMPARE(save_dives("./testmerge.ssrf"), 0);
|
||||
FILE_COMPARE("./testmerge.ssrf",
|
||||
|
@ -324,21 +326,16 @@ void TestParse::exportCSVDiveDetails()
|
|||
export_dives_xslt("testcsvexportmanual.csv", 0, 0, "xml2manualcsv.xslt", false);
|
||||
export_dives_xslt("testcsvexportmanualimperial.csv", 0, 1, "xml2manualcsv.xslt", false);
|
||||
|
||||
if (divelog.dives->nr > 0) {
|
||||
struct dive *dive = divelog.dives->dives[divelog.dives->nr - 1];
|
||||
saved_sac = dive->sac;
|
||||
}
|
||||
if (!divelog.dives.empty())
|
||||
saved_sac = divelog.dives.back()->sac;
|
||||
clear_dive_file_data();
|
||||
|
||||
parseCSVmanual(1, "testcsvexportmanualimperial.csv");
|
||||
|
||||
// We do not currently support reading SAC, thus faking it
|
||||
if (divelog.dives->nr > 0) {
|
||||
struct dive *dive = divelog.dives->dives[divelog.dives->nr - 1];
|
||||
dive->sac = saved_sac;
|
||||
}
|
||||
|
||||
sort_dive_table(divelog.dives);
|
||||
if (!divelog.dives.empty())
|
||||
divelog.dives.back()->sac = saved_sac;
|
||||
divelog.dives.sort();
|
||||
|
||||
export_dives_xslt("testcsvexportmanual2.csv", 0, 0, "xml2manualcsv.xslt", false);
|
||||
FILE_COMPARE("testcsvexportmanual2.csv",
|
||||
|
@ -358,10 +355,8 @@ void TestParse::exportSubsurfaceCSV()
|
|||
export_dives_xslt("testcsvexportmanual-cyl.csv", 0, 0, "xml2manualcsv.xslt", false);
|
||||
export_dives_xslt("testcsvexportmanualimperial-cyl.csv", 0, 1, "xml2manualcsv.xslt", false);
|
||||
|
||||
if (divelog.dives->nr > 0) {
|
||||
struct dive *dive = divelog.dives->dives[divelog.dives->nr - 1];
|
||||
saved_sac = dive->sac;
|
||||
}
|
||||
if (!divelog.dives.empty())
|
||||
saved_sac = divelog.dives.back()->sac;
|
||||
|
||||
clear_dive_file_data();
|
||||
|
||||
|
@ -370,12 +365,10 @@ void TestParse::exportSubsurfaceCSV()
|
|||
parse_csv_file("testcsvexportmanualimperial-cyl.csv", ¶ms, "SubsurfaceCSV", &divelog);
|
||||
|
||||
// We do not currently support reading SAC, thus faking it
|
||||
if (divelog.dives->nr > 0) {
|
||||
struct dive *dive = divelog.dives->dives[divelog.dives->nr - 1];
|
||||
dive->sac = saved_sac;
|
||||
}
|
||||
if (!divelog.dives.empty())
|
||||
divelog.dives.back()->sac = saved_sac;
|
||||
|
||||
sort_dive_table(divelog.dives);
|
||||
divelog.dives.sort();
|
||||
|
||||
export_dives_xslt("testcsvexportmanual2-cyl.csv", 0, 0, "xml2manualcsv.xslt", false);
|
||||
FILE_COMPARE("testcsvexportmanual2-cyl.csv",
|
||||
|
@ -414,7 +407,7 @@ void TestParse::exportCSVDiveProfile()
|
|||
clear_dive_file_data();
|
||||
|
||||
parseCSVprofile(1, "testcsvexportprofileimperial.csv");
|
||||
sort_dive_table(divelog.dives);
|
||||
divelog.dives.sort();
|
||||
|
||||
export_dives_xslt("testcsvexportprofile2.csv", 0, 0, "xml2csv.xslt", false);
|
||||
FILE_COMPARE("testcsvexportprofile2.csv",
|
||||
|
@ -432,7 +425,7 @@ void TestParse::exportUDDF()
|
|||
clear_dive_file_data();
|
||||
|
||||
parse_file("testuddfexport.uddf", &divelog);
|
||||
sort_dive_table(divelog.dives);
|
||||
divelog.dives.sort();
|
||||
|
||||
export_dives_xslt("testuddfexport2.uddf", 0, 1, "uddf-export.xslt", false);
|
||||
FILE_COMPARE("testuddfexport.uddf",
|
||||
|
@ -478,9 +471,9 @@ void TestParse::parseDL7()
|
|||
QCOMPARE(parse_csv_file(SUBSURFACE_TEST_DATA "/dives/DL7.zxu",
|
||||
¶ms, "DL7", &divelog),
|
||||
0);
|
||||
QCOMPARE(divelog.dives->nr, 3);
|
||||
QCOMPARE(divelog.dives.size(), 3);
|
||||
|
||||
sort_dive_table(divelog.dives);
|
||||
divelog.dives.sort();
|
||||
|
||||
QCOMPARE(save_dives("./testdl7out.ssrf"), 0);
|
||||
FILE_COMPARE("./testdl7out.ssrf",
|
||||
|
|
|
@ -487,7 +487,7 @@ void TestPlan::testMetric()
|
|||
|
||||
#if DEBUG
|
||||
dive.notes.clear();
|
||||
save_dive(stdout, &dive, false);
|
||||
save_dive(stdout, dive, false);
|
||||
#endif
|
||||
|
||||
// check minimum gas result
|
||||
|
@ -527,7 +527,7 @@ void TestPlan::testImperial()
|
|||
|
||||
#if DEBUG
|
||||
dive.notes.clear();
|
||||
save_dive(stdout, &dive, false);
|
||||
save_dive(stdout, dive, false);
|
||||
#endif
|
||||
|
||||
// check minimum gas result
|
||||
|
@ -566,7 +566,7 @@ void TestPlan::testVpmbMetric45m30minTx()
|
|||
|
||||
#if DEBUG
|
||||
dive.notes.clear();
|
||||
save_dive(stdout, &dive, false);
|
||||
save_dive(stdout, dive, false);
|
||||
#endif
|
||||
|
||||
// check minimum gas result
|
||||
|
@ -595,7 +595,7 @@ void TestPlan::testVpmbMetric60m10minTx()
|
|||
|
||||
#if DEBUG
|
||||
dive.notes.clear();
|
||||
save_dive(stdout, &dive, false);
|
||||
save_dive(stdout, dive, false);
|
||||
#endif
|
||||
|
||||
// check minimum gas result
|
||||
|
@ -624,7 +624,7 @@ void TestPlan::testVpmbMetric60m30minAir()
|
|||
|
||||
#if DEBUG
|
||||
dive.notes.clear();
|
||||
save_dive(stdout, &dive, false);
|
||||
save_dive(stdout, dive, false);
|
||||
#endif
|
||||
|
||||
// check minimum gas result
|
||||
|
@ -653,7 +653,7 @@ void TestPlan::testVpmbMetric60m30minEan50()
|
|||
|
||||
#if DEBUG
|
||||
dive.notes.clear();
|
||||
save_dive(stdout, &dive, false);
|
||||
save_dive(stdout, dive, false);
|
||||
#endif
|
||||
|
||||
// check minimum gas result
|
||||
|
@ -688,7 +688,7 @@ void TestPlan::testVpmbMetric60m30minTx()
|
|||
|
||||
#if DEBUG
|
||||
dive.notes.clear();
|
||||
save_dive(stdout, &dive, false);
|
||||
save_dive(stdout, dive, false);
|
||||
#endif
|
||||
|
||||
// check minimum gas result
|
||||
|
@ -723,7 +723,7 @@ void TestPlan::testVpmbMetric100m60min()
|
|||
|
||||
#if DEBUG
|
||||
dive.notes.clear();
|
||||
save_dive(stdout, &dive, false);
|
||||
save_dive(stdout, dive, false);
|
||||
#endif
|
||||
|
||||
// check minimum gas result
|
||||
|
@ -765,7 +765,7 @@ void TestPlan::testMultipleGases()
|
|||
|
||||
#if DEBUG
|
||||
dive.notes.clear();
|
||||
save_dive(stdout, &dive, false);
|
||||
save_dive(stdout, dive, false);
|
||||
#endif
|
||||
|
||||
gasmix gas;
|
||||
|
@ -789,7 +789,7 @@ void TestPlan::testVpmbMetricMultiLevelAir()
|
|||
|
||||
#if DEBUG
|
||||
dive.notes.clear();
|
||||
save_dive(stdout, &dive, false);
|
||||
save_dive(stdout, dive, false);
|
||||
#endif
|
||||
|
||||
// check minimum gas result
|
||||
|
@ -818,7 +818,7 @@ void TestPlan::testVpmbMetric100m10min()
|
|||
|
||||
#if DEBUG
|
||||
dive.notes.clear();
|
||||
save_dive(stdout, &dive, false);
|
||||
save_dive(stdout, dive, false);
|
||||
#endif
|
||||
|
||||
// check minimum gas result
|
||||
|
@ -864,7 +864,7 @@ void TestPlan::testVpmbMetricRepeat()
|
|||
|
||||
#if DEBUG
|
||||
dive.notes.clear();
|
||||
save_dive(stdout, &dive, false);
|
||||
save_dive(stdout, dive, false);
|
||||
#endif
|
||||
|
||||
// check minimum gas result
|
||||
|
@ -884,7 +884,7 @@ void TestPlan::testVpmbMetricRepeat()
|
|||
|
||||
#if DEBUG
|
||||
dive.notes.clear();
|
||||
save_dive(stdout, &dive, false);
|
||||
save_dive(stdout, dive, false);
|
||||
#endif
|
||||
|
||||
// check minimum gas result
|
||||
|
@ -921,7 +921,7 @@ void TestPlan::testVpmbMetricRepeat()
|
|||
|
||||
#if DEBUG
|
||||
dive.notes.clear();
|
||||
save_dive(stdout, &dive, false);
|
||||
save_dive(stdout, dive, false);
|
||||
#endif
|
||||
|
||||
// check minimum gas result
|
||||
|
@ -959,7 +959,7 @@ void TestPlan::testCcrBailoutGasSelection()
|
|||
|
||||
#if DEBUG
|
||||
dive.notes.clear();
|
||||
save_dive(stdout, &dive, false);
|
||||
save_dive(stdout, dive, false);
|
||||
#endif
|
||||
|
||||
// check diluent used
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include "testprofile.h"
|
||||
#include "core/device.h"
|
||||
#include "core/dive.h"
|
||||
#include "core/divelog.h"
|
||||
#include "core/divesite.h"
|
||||
#include "core/trip.h"
|
||||
|
@ -34,7 +35,7 @@ void TestProfile::testProfileExport()
|
|||
{
|
||||
prefs.planner_deco_mode = BUEHLMANN;
|
||||
parse_file(SUBSURFACE_TEST_DATA "/dives/abitofeverything.ssrf", &divelog);
|
||||
sort_dive_table(divelog.dives);
|
||||
divelog.dives.sort();
|
||||
save_profiledata("exportprofile.csv", false);
|
||||
QFile org(SUBSURFACE_TEST_DATA "/dives/exportprofilereference.csv");
|
||||
QCOMPARE(org.open(QFile::ReadOnly), true);
|
||||
|
@ -51,7 +52,7 @@ void TestProfile::testProfileExportVPMB()
|
|||
{
|
||||
prefs.planner_deco_mode = VPMB;
|
||||
parse_file(SUBSURFACE_TEST_DATA "/dives/abitofeverything.ssrf", &divelog);
|
||||
sort_dive_table(divelog.dives);
|
||||
divelog.dives.sort();
|
||||
save_profiledata("exportprofileVPMB.csv", false);
|
||||
QFile org(SUBSURFACE_TEST_DATA "/dives/exportprofilereferenceVPMB.csv");
|
||||
QCOMPARE(org.open(QFile::ReadOnly), true);
|
||||
|
|
|
@ -20,16 +20,16 @@ void TestRenumber::testMerge()
|
|||
{
|
||||
struct divelog log;
|
||||
QCOMPARE(parse_file(SUBSURFACE_TEST_DATA "/dives/test47b.xml", &log), 0);
|
||||
add_imported_dives(&log, IMPORT_MERGE_ALL_TRIPS);
|
||||
QCOMPARE(divelog.dives->nr, 1);
|
||||
add_imported_dives(log, IMPORT_MERGE_ALL_TRIPS);
|
||||
QCOMPARE(divelog.dives.size(), 1);
|
||||
}
|
||||
|
||||
void TestRenumber::testMergeAndAppend()
|
||||
{
|
||||
struct divelog log;
|
||||
QCOMPARE(parse_file(SUBSURFACE_TEST_DATA "/dives/test47c.xml", &log), 0);
|
||||
add_imported_dives(&log, IMPORT_MERGE_ALL_TRIPS);
|
||||
QCOMPARE(divelog.dives->nr, 2);
|
||||
add_imported_dives(log, IMPORT_MERGE_ALL_TRIPS);
|
||||
QCOMPARE(divelog.dives.size(), 2);
|
||||
struct dive *d = get_dive(1);
|
||||
QVERIFY(d != NULL);
|
||||
if (d)
|
||||
|
|
Loading…
Reference in a new issue