mirror of
https://github.com/subsurface/subsurface.git
synced 2025-02-19 22:16:15 +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
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue