mirror of
https://github.com/subsurface/subsurface.git
synced 2024-11-28 05:00:20 +00:00
Import: keep dive and dive site tables in DiveImportedModel
The DiveImportedModel and DownloadThread used the same table of dives and dive sites. This made it very hard to keep the model consistent: Every modification of the download thread would make the model inconsistent and could lead to memory corruption owing to dangling pointers. Therefore, keep a copy in the model. When updating the model, use move-semantics, i.e. move the data and reset the tables of the thread to zero elements. Since the DiveImportedModel and the DownloadThread are very tightly integrated, remove the accessor-functions of the dive and dive-site tables. They fulfilled no purpose whatsoever as they gave the same access-rights as a public field. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
parent
a353bcb296
commit
087a80194a
4 changed files with 31 additions and 45 deletions
|
@ -308,16 +308,6 @@ DCDeviceData *DownloadThread::data()
|
||||||
return m_data;
|
return m_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct dive_table *DownloadThread::table()
|
|
||||||
{
|
|
||||||
return &downloadTable;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct dive_site_table *DownloadThread::sites()
|
|
||||||
{
|
|
||||||
return &diveSiteTable;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString DCDeviceData::vendor() const
|
QString DCDeviceData::vendor() const
|
||||||
{
|
{
|
||||||
return data.vendor;
|
return data.vendor;
|
||||||
|
|
|
@ -64,13 +64,11 @@ public:
|
||||||
void run() override;
|
void run() override;
|
||||||
|
|
||||||
DCDeviceData *data();
|
DCDeviceData *data();
|
||||||
struct dive_table *table();
|
|
||||||
struct dive_site_table *sites();
|
|
||||||
QString error;
|
QString error;
|
||||||
|
|
||||||
private:
|
|
||||||
struct dive_table downloadTable;
|
struct dive_table downloadTable;
|
||||||
struct dive_site_table diveSiteTable;
|
struct dive_site_table diveSiteTable;
|
||||||
|
|
||||||
|
private:
|
||||||
DCDeviceData *m_data;
|
DCDeviceData *m_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -5,8 +5,8 @@
|
||||||
DiveImportedModel::DiveImportedModel(QObject *o) : QAbstractTableModel(o),
|
DiveImportedModel::DiveImportedModel(QObject *o) : QAbstractTableModel(o),
|
||||||
firstIndex(0),
|
firstIndex(0),
|
||||||
lastIndex(-1),
|
lastIndex(-1),
|
||||||
diveTable(nullptr),
|
diveTable({ 0 }),
|
||||||
sitesTable(nullptr)
|
sitesTable({ 0 })
|
||||||
{
|
{
|
||||||
connect(&thread, &QThread::finished, this, &DiveImportedModel::downloadThreadFinished);
|
connect(&thread, &QThread::finished, this, &DiveImportedModel::downloadThreadFinished);
|
||||||
}
|
}
|
||||||
|
@ -54,7 +54,7 @@ QVariant DiveImportedModel::data(const QModelIndex &index, int role) const
|
||||||
if (index.row() + firstIndex > lastIndex)
|
if (index.row() + firstIndex > lastIndex)
|
||||||
return QVariant();
|
return QVariant();
|
||||||
|
|
||||||
struct dive *d = get_dive_from_table(index.row() + firstIndex, diveTable);
|
struct dive *d = get_dive_from_table(index.row() + firstIndex, &diveTable);
|
||||||
if (!d)
|
if (!d)
|
||||||
return QVariant();
|
return QVariant();
|
||||||
|
|
||||||
|
@ -132,7 +132,19 @@ void DiveImportedModel::clearTable()
|
||||||
|
|
||||||
void DiveImportedModel::downloadThreadFinished()
|
void DiveImportedModel::downloadThreadFinished()
|
||||||
{
|
{
|
||||||
repopulate(thread.table(), thread.sites());
|
beginResetModel();
|
||||||
|
|
||||||
|
// Move the table data from thread to model
|
||||||
|
move_dive_table(&thread.downloadTable, &diveTable);
|
||||||
|
move_dive_site_table(&thread.diveSiteTable, &sitesTable);
|
||||||
|
|
||||||
|
firstIndex = 0;
|
||||||
|
lastIndex = diveTable.nr - 1;
|
||||||
|
checkStates.resize(diveTable.nr);
|
||||||
|
std::fill(checkStates.begin(), checkStates.end(), true);
|
||||||
|
|
||||||
|
endResetModel();
|
||||||
|
|
||||||
emit downloadFinished();
|
emit downloadFinished();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,29 +153,15 @@ void DiveImportedModel::startDownload()
|
||||||
thread.start();
|
thread.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DiveImportedModel::repopulate(dive_table_t *table, struct dive_site_table *sites)
|
|
||||||
{
|
|
||||||
beginResetModel();
|
|
||||||
|
|
||||||
diveTable = table;
|
|
||||||
sitesTable = sites;
|
|
||||||
firstIndex = 0;
|
|
||||||
lastIndex = diveTable->nr - 1;
|
|
||||||
checkStates.resize(diveTable->nr);
|
|
||||||
std::fill(checkStates.begin(), checkStates.end(), true);
|
|
||||||
|
|
||||||
endResetModel();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::pair<struct dive_table, struct dive_site_table> DiveImportedModel::consumeTables()
|
std::pair<struct dive_table, struct dive_site_table> DiveImportedModel::consumeTables()
|
||||||
{
|
{
|
||||||
beginResetModel();
|
beginResetModel();
|
||||||
|
|
||||||
// Move tables to result
|
// Move tables to result
|
||||||
struct dive_table dives;
|
struct dive_table dives = { 0 };
|
||||||
struct dive_site_table sites;
|
struct dive_site_table sites = { 0 };
|
||||||
move_dive_table(diveTable, &dives);
|
move_dive_table(&diveTable, &dives);
|
||||||
move_dive_site_table(sitesTable, &sites);
|
move_dive_site_table(&sitesTable, &sites);
|
||||||
|
|
||||||
// Reset indexes
|
// Reset indexes
|
||||||
firstIndex = 0;
|
firstIndex = 0;
|
||||||
|
@ -177,38 +175,38 @@ std::pair<struct dive_table, struct dive_site_table> DiveImportedModel::consumeT
|
||||||
|
|
||||||
int DiveImportedModel::numDives() const
|
int DiveImportedModel::numDives() const
|
||||||
{
|
{
|
||||||
return diveTable->nr;
|
return diveTable.nr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete non-selected dives
|
// Delete non-selected dives
|
||||||
void DiveImportedModel::deleteDeselected()
|
void DiveImportedModel::deleteDeselected()
|
||||||
{
|
{
|
||||||
int total = diveTable->nr;
|
int total = diveTable.nr;
|
||||||
int j = 0;
|
int j = 0;
|
||||||
for (int i = 0; i < total; i++) {
|
for (int i = 0; i < total; i++) {
|
||||||
if (checkStates[i]) {
|
if (checkStates[i]) {
|
||||||
j++;
|
j++;
|
||||||
} else {
|
} else {
|
||||||
beginRemoveRows(QModelIndex(), j, j);
|
beginRemoveRows(QModelIndex(), j, j);
|
||||||
delete_dive_from_table(diveTable, j);
|
delete_dive_from_table(&diveTable, j);
|
||||||
endRemoveRows();
|
endRemoveRows();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
checkStates.resize(diveTable->nr);
|
checkStates.resize(diveTable.nr);
|
||||||
std::fill(checkStates.begin(), checkStates.end(), true);
|
std::fill(checkStates.begin(), checkStates.end(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note: this function is only used from mobile - perhaps move it there or unify.
|
// Note: this function is only used from mobile - perhaps move it there or unify.
|
||||||
void DiveImportedModel::recordDives()
|
void DiveImportedModel::recordDives()
|
||||||
{
|
{
|
||||||
if (diveTable->nr == 0)
|
if (diveTable.nr == 0)
|
||||||
// nothing to do, just exit
|
// nothing to do, just exit
|
||||||
return;
|
return;
|
||||||
|
|
||||||
deleteDeselected();
|
deleteDeselected();
|
||||||
|
|
||||||
// TODO: Might want to let the user select IMPORT_ADD_TO_NEW_TRIP
|
// TODO: Might want to let the user select IMPORT_ADD_TO_NEW_TRIP
|
||||||
add_imported_dives(diveTable, nullptr, sitesTable, IMPORT_PREFER_IMPORTED | IMPORT_IS_DOWNLOADED);
|
add_imported_dives(&diveTable, nullptr, &sitesTable, IMPORT_PREFER_IMPORTED | IMPORT_IS_DOWNLOADED);
|
||||||
}
|
}
|
||||||
|
|
||||||
QHash<int, QByteArray> DiveImportedModel::roleNames() const {
|
QHash<int, QByteArray> DiveImportedModel::roleNames() const {
|
||||||
|
|
|
@ -23,6 +23,7 @@ public:
|
||||||
QHash<int, QByteArray> roleNames() const;
|
QHash<int, QByteArray> roleNames() const;
|
||||||
void deleteDeselected();
|
void deleteDeselected();
|
||||||
std::pair<struct dive_table, struct dive_site_table> consumeTables(); // Returns dives and sites and resets model.
|
std::pair<struct dive_table, struct dive_site_table> consumeTables(); // Returns dives and sites and resets model.
|
||||||
|
|
||||||
int numDives() const;
|
int numDives() const;
|
||||||
Q_INVOKABLE void recordDives();
|
Q_INVOKABLE void recordDives();
|
||||||
Q_INVOKABLE void startDownload();
|
Q_INVOKABLE void startDownload();
|
||||||
|
@ -43,12 +44,11 @@ signals:
|
||||||
void downloadFinished();
|
void downloadFinished();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void repopulate(dive_table_t *table, dive_site_table_t *sites);
|
|
||||||
int firstIndex;
|
int firstIndex;
|
||||||
int lastIndex;
|
int lastIndex;
|
||||||
std::vector<char> checkStates; // char instead of bool to avoid silly pessimization of std::vector.
|
std::vector<char> checkStates; // char instead of bool to avoid silly pessimization of std::vector.
|
||||||
struct dive_table *diveTable;
|
struct dive_table diveTable;
|
||||||
struct dive_site_table *sitesTable;
|
struct dive_site_table sitesTable;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue