summaryrefslogtreecommitdiffstats
path: root/qt-models
diff options
context:
space:
mode:
Diffstat (limited to 'qt-models')
-rw-r--r--qt-models/cylindermodel.cpp120
-rw-r--r--qt-models/cylindermodel.h1
-rw-r--r--qt-models/diveplannermodel.cpp45
-rw-r--r--qt-models/diveplotdatamodel.cpp4
-rw-r--r--qt-models/divetripmodel.cpp6
-rw-r--r--qt-models/models.cpp6
6 files changed, 85 insertions, 97 deletions
diff --git a/qt-models/cylindermodel.cpp b/qt-models/cylindermodel.cpp
index 3a2b6e536..f64cc213a 100644
--- a/qt-models/cylindermodel.cpp
+++ b/qt-models/cylindermodel.cpp
@@ -131,10 +131,10 @@ static QVariant percent_string(fraction_t fraction)
QVariant CylindersModel::data(const QModelIndex &index, int role) const
{
- if (!index.isValid() || index.row() >= MAX_CYLINDERS)
+ if (!index.isValid() || index.row() >= rows)
return QVariant();
- const cylinder_t *cyl = &displayed_dive.cylinder[index.row()];
+ const cylinder_t *cyl = &displayed_dive.cylinders.cylinders[index.row()];
switch (role) {
case Qt::BackgroundRole: {
@@ -259,7 +259,7 @@ QVariant CylindersModel::data(const QModelIndex &index, int role) const
cylinder_t *CylindersModel::cylinderAt(const QModelIndex &index)
{
- return &displayed_dive.cylinder[index.row()];
+ return &displayed_dive.cylinders.cylinders[index.row()];
}
// this is our magic 'pass data in' function that allows the delegate to get
@@ -420,16 +420,14 @@ int CylindersModel::rowCount(const QModelIndex&) const
void CylindersModel::add()
{
- if (rows >= MAX_CYLINDERS) {
- return;
- }
-
int row = rows;
- fill_default_cylinder(&displayed_dive, row);
- displayed_dive.cylinder[row].start = displayed_dive.cylinder[row].type.workingpressure;
- displayed_dive.cylinder[row].manually_added = true;
- displayed_dive.cylinder[row].cylinder_use = OC_GAS;
+ cylinder_t cyl = { 0 };
+ fill_default_cylinder(&displayed_dive, &cyl);
+ cyl.start = cyl.type.workingpressure;
+ cyl.manually_added = true;
+ cyl.cylinder_use = OC_GAS;
beginInsertRows(QModelIndex(), row, row);
+ add_to_cylinder_table(&displayed_dive.cylinders, row, cyl);
rows++;
changed = true;
endInsertRows();
@@ -446,12 +444,12 @@ void CylindersModel::clear()
static bool show_cylinder(struct dive *dive, int i)
{
- cylinder_t *cyl = dive->cylinder + i;
-
+ if (i < 0 || i >= dive->cylinders.nr)
+ return false;
if (is_cylinder_used(dive, i))
return true;
- if (cylinder_none(cyl))
- return false;
+
+ cylinder_t *cyl = dive->cylinders.cylinders + i;
if (cyl->start.mbar || cyl->sample_start.mbar ||
cyl->end.mbar || cyl->sample_end.mbar)
return true;
@@ -467,34 +465,18 @@ static bool show_cylinder(struct dive *dive, int i)
void CylindersModel::updateDive()
{
- clear();
- rows = 0;
#ifdef DEBUG_CYL
dump_cylinders(&displayed_dive, true);
#endif
- for (int i = 0; i < MAX_CYLINDERS; i++) {
- if (show_cylinder(&displayed_dive, i))
- rows = i + 1;
- }
- if (rows > 0) {
- beginInsertRows(QModelIndex(), 0, rows - 1);
- endInsertRows();
- }
-}
-
-void CylindersModel::copyFromDive(dive *d)
-{
- if (!d)
- return;
+ beginResetModel();
+ // TODO: this is fundamentally broken - it assumes that unused cylinders are at
+ // the end. Fix by using a QSortFilterProxyModel.
rows = 0;
- for (int i = 0; i < MAX_CYLINDERS; i++) {
- if (show_cylinder(d, i))
- rows = i + 1;
- }
- if (rows > 0) {
- beginInsertRows(QModelIndex(), 0, rows - 1);
- endInsertRows();
+ for (int i = 0; i < displayed_dive.cylinders.nr; ++i) {
+ if (show_cylinder(&displayed_dive, i))
+ ++rows;
}
+ endResetModel();
}
Qt::ItemFlags CylindersModel::flags(const QModelIndex &index) const
@@ -506,7 +488,6 @@ Qt::ItemFlags CylindersModel::flags(const QModelIndex &index) const
void CylindersModel::remove(const QModelIndex &index)
{
- std::vector<int> mapping(MAX_CYLINDERS);
if (index.column() == USE) {
cylinder_t *cyl = cylinderAt(index);
@@ -518,48 +499,53 @@ void CylindersModel::remove(const QModelIndex &index)
dataChanged(index, index);
return;
}
- if (index.column() != REMOVE) {
+
+ if (index.column() != REMOVE)
return;
- }
if ((in_planner() && DivePlannerPointsModel::instance()->tankInUse(index.row())) ||
(!in_planner() && is_cylinder_prot(&displayed_dive, index.row())))
return;
- beginRemoveRows(QModelIndex(), index.row(), index.row()); // yah, know, ugly.
+ beginRemoveRows(QModelIndex(), index.row(), index.row());
rows--;
-
remove_cylinder(&displayed_dive, index.row());
- for (int i = 0; i < index.row(); i++)
- mapping[i] = i;
- // No mapping for removed gas, set to -1
+ changed = true;
+ endRemoveRows();
+
+ // Create a mapping of cylinder indexes:
+ // 1) Fill mapping[0]..mapping[index-1] with 0..index
+ // 2) Set mapping[index] to -1
+ // 3) Fill mapping[index+1]..mapping[end] with index..
+ std::vector<int> mapping(displayed_dive.cylinders.nr + 1);
+ std::iota(mapping.begin(), mapping.begin() + index.row(), 0);
mapping[index.row()] = -1;
- for (int i = index.row() + 1; i < MAX_CYLINDERS; i++)
- mapping[i] = i - 1;
+ std::iota(mapping.begin() + index.row() + 1, mapping.end(), index.row());
cylinder_renumber(&displayed_dive, &mapping[0]);
if (in_planner())
DivePlannerPointsModel::instance()->cylinderRenumber(&mapping[0]);
changed = true;
- endRemoveRows();
- dataChanged(index, index);
}
void CylindersModel::moveAtFirst(int cylid)
{
- std::vector<int> mapping(MAX_CYLINDERS);
cylinder_t temp_cyl;
beginMoveRows(QModelIndex(), cylid, cylid, QModelIndex(), 0);
- memmove(&temp_cyl, &displayed_dive.cylinder[cylid], sizeof(temp_cyl));
- for (int i = cylid - 1; i >= 0; i--) {
- memmove(&displayed_dive.cylinder[i + 1], &displayed_dive.cylinder[i], sizeof(temp_cyl));
- mapping[i] = i + 1;
- }
- memmove(&displayed_dive.cylinder[0], &temp_cyl, sizeof(temp_cyl));
+ memmove(&temp_cyl, &displayed_dive.cylinders.cylinders[cylid], sizeof(temp_cyl));
+ for (int i = cylid - 1; i >= 0; i--)
+ memmove(&displayed_dive.cylinders.cylinders[i + 1], &displayed_dive.cylinders.cylinders[i], sizeof(temp_cyl));
+ memmove(&displayed_dive.cylinders.cylinders[0], &temp_cyl, sizeof(temp_cyl));
+
+ // Create a mapping of cylinder indexes:
+ // 1) Fill mapping[0]..mapping[cyl] with 0..index
+ // 2) Set mapping[cyl] to 0
+ // 3) Fill mapping[cyl+1]..mapping[end] with cyl..
+ std::vector<int> mapping(displayed_dive.cylinders.nr);
+ std::iota(mapping.begin(), mapping.begin() + cylid, 1);
mapping[cylid] = 0;
- for (int i = cylid + 1; i < MAX_CYLINDERS; i++)
- mapping[i] = i;
+ std::iota(mapping.begin() + (cylid + 1), mapping.end(), cylid);
cylinder_renumber(&displayed_dive, &mapping[0]);
if (in_planner())
DivePlannerPointsModel::instance()->cylinderRenumber(&mapping[0]);
@@ -571,28 +557,28 @@ void CylindersModel::updateDecoDepths(pressure_t olddecopo2)
{
pressure_t decopo2;
decopo2.mbar = prefs.decopo2;
- for (int i = 0; i < MAX_CYLINDERS; i++) {
- cylinder_t *cyl = &displayed_dive.cylinder[i];
+ for (int i = 0; i < displayed_dive.cylinders.nr; i++) {
+ cylinder_t *cyl = &displayed_dive.cylinders.cylinders[i];
/* If the gas's deco MOD matches the old pO2, it will have been automatically calculated and should be updated.
* If they don't match, we should leave the user entered depth as it is */
if (cyl->depth.mm == gas_mod(cyl->gasmix, olddecopo2, &displayed_dive, M_OR_FT(3, 10)).mm) {
cyl->depth = gas_mod(cyl->gasmix, decopo2, &displayed_dive, M_OR_FT(3, 10));
}
}
- emit dataChanged(createIndex(0, 0), createIndex(MAX_CYLINDERS - 1, COLUMNS - 1));
+ emit dataChanged(createIndex(0, 0), createIndex(displayed_dive.cylinders.nr - 1, COLUMNS - 1));
}
void CylindersModel::updateTrashIcon()
{
- emit dataChanged(createIndex(0, 0), createIndex(MAX_CYLINDERS - 1, 0));
+ emit dataChanged(createIndex(0, 0), createIndex(displayed_dive.cylinders.nr - 1, 0));
}
bool CylindersModel::updateBestMixes()
{
// Check if any of the cylinders are best mixes, update if needed
bool gasUpdated = false;
- for (int i = 0; i < MAX_CYLINDERS; i++) {
- cylinder_t *cyl = &displayed_dive.cylinder[i];
+ for (int i = 0; i < displayed_dive.cylinders.nr; i++) {
+ cylinder_t *cyl = &displayed_dive.cylinders.cylinders[i];
if (cyl->bestmix_o2) {
cyl->gasmix.o2 = best_o2(displayed_dive.maxdepth, &displayed_dive);
// fO2 + fHe must not be greater than 1
@@ -614,7 +600,7 @@ bool CylindersModel::updateBestMixes()
/* This slot is called when the bottom pO2 and END preferences are updated, we want to
* emit dataChanged so MOD and MND are refreshed, even if the gas mix hasn't been changed */
if (gasUpdated)
- emit dataChanged(createIndex(0, 0), createIndex(MAX_CYLINDERS - 1, COLUMNS - 1));
+ emit dataChanged(createIndex(0, 0), createIndex(displayed_dive.cylinders.nr - 1, COLUMNS - 1));
return gasUpdated;
}
@@ -626,7 +612,7 @@ void CylindersModel::cylindersReset(const QVector<dive *> &dives)
return;
// Copy the cylinders from the current dive to the displayed dive.
- copy_cylinders(current_dive, &displayed_dive, false);
+ copy_cylinders(&current_dive->cylinders, &displayed_dive.cylinders);
// And update the model..
updateDive();
diff --git a/qt-models/cylindermodel.h b/qt-models/cylindermodel.h
index 58d11e971..0def53ba9 100644
--- a/qt-models/cylindermodel.h
+++ b/qt-models/cylindermodel.h
@@ -37,7 +37,6 @@ public:
void add();
void clear();
void updateDive();
- void copyFromDive(struct dive *d);
void updateDecoDepths(pressure_t olddecopo2);
void updateTrashIcon();
void moveAtFirst(int cylid);
diff --git a/qt-models/diveplannermodel.cpp b/qt-models/diveplannermodel.cpp
index 537bf278f..8d19afcfb 100644
--- a/qt-models/diveplannermodel.cpp
+++ b/qt-models/diveplannermodel.cpp
@@ -152,29 +152,32 @@ void DivePlannerPointsModel::loadFromDive(dive *d)
// setup the cylinder widget accordingly
void DivePlannerPointsModel::setupCylinders()
{
- int i;
+ clear_cylinder_table(&displayed_dive.cylinders);
if (mode == PLAN && current_dive) {
// take the displayed cylinders from the selected dive as starting point
- CylindersModel::instance()->copyFromDive(current_dive);
- copy_cylinders(current_dive, &displayed_dive, !prefs.display_unused_tanks);
+ copy_used_cylinders(current_dive, &displayed_dive, !prefs.display_unused_tanks);
reset_cylinders(&displayed_dive, true);
- for (i = 0; i < MAX_CYLINDERS; i++)
- if (!cylinder_none(&(displayed_dive.cylinder[i])))
- return; // We have at least one cylinder
+ if (displayed_dive.cylinders.nr > 0) {
+ CylindersModel::instance()->updateDive();
+ return; // We have at least one cylinder
+ }
}
if (!empty_string(prefs.default_cylinder)) {
- fill_default_cylinder(&displayed_dive, 0);
- displayed_dive.cylinder[0].start = displayed_dive.cylinder[0].type.workingpressure;
- }
- if (cylinder_none(&displayed_dive.cylinder[0])) {
+ cylinder_t cyl = { 0 };
+ fill_default_cylinder(&displayed_dive, &cyl);
+ cyl.start = cyl.type.workingpressure;
+ add_to_cylinder_table(&displayed_dive.cylinders, 0, cyl);
+ } else {
+ cylinder_t cyl = { 0 };
// roughly an AL80
- displayed_dive.cylinder[0].type.description = copy_qstring(tr("unknown"));
- displayed_dive.cylinder[0].type.size.mliter = 11100;
- displayed_dive.cylinder[0].type.workingpressure.mbar = 207000;
+ cyl.type.description = copy_qstring(tr("unknown"));
+ cyl.type.size.mliter = 11100;
+ cyl.type.workingpressure.mbar = 207000;
+ add_to_cylinder_table(&displayed_dive.cylinders, 0, cyl);
}
reset_cylinders(&displayed_dive, false);
- CylindersModel::instance()->copyFromDive(&displayed_dive);
+ CylindersModel::instance()->updateDive();
}
// Update the dive's maximum depth. Returns true if max. depth changed
@@ -265,13 +268,13 @@ QVariant DivePlannerPointsModel::data(const QModelIndex &index, int role) const
case GAS:
/* Check if we have the same gasmix two or more times
* If yes return more verbose string */
- int same_gas = same_gasmix_cylinder(&displayed_dive.cylinder[p.cylinderid], p.cylinderid, &displayed_dive, true);
+ int same_gas = same_gasmix_cylinder(&displayed_dive.cylinders.cylinders[p.cylinderid], p.cylinderid, &displayed_dive, true);
if (same_gas == -1)
- return get_gas_string(displayed_dive.cylinder[p.cylinderid].gasmix);
+ return get_gas_string(displayed_dive.cylinders.cylinders[p.cylinderid].gasmix);
else
- return get_gas_string(displayed_dive.cylinder[p.cylinderid].gasmix) +
+ return get_gas_string(displayed_dive.cylinders.cylinders[p.cylinderid].gasmix) +
QString(" (%1 %2 ").arg(tr("cyl.")).arg(p.cylinderid + 1) +
- displayed_dive.cylinder[p.cylinderid].type.description + ")";
+ displayed_dive.cylinders.cylinders[p.cylinderid].type.description + ")";
}
} else if (role == Qt::DecorationRole) {
switch (index.column()) {
@@ -333,7 +336,7 @@ bool DivePlannerPointsModel::setData(const QModelIndex &index, const QVariant &v
p.setpoint = po2;
} break;
case GAS:
- if (value.toInt() >= 0 && value.toInt() < MAX_CYLINDERS)
+ if (value.toInt() >= 0)
p.cylinderid = value.toInt();
/* Did we change the start (dp 0) cylinder to another cylinderid than 0? */
if (value.toInt() != 0 && index.row() == 0)
@@ -890,8 +893,8 @@ void DivePlannerPointsModel::createTemporaryPlan()
// what does the cache do???
struct deco_state *cache = NULL;
struct divedatapoint *dp = NULL;
- for (int i = 0; i < MAX_CYLINDERS; i++) {
- cylinder_t *cyl = &displayed_dive.cylinder[i];
+ for (int i = 0; i < displayed_dive.cylinders.nr; i++) {
+ cylinder_t *cyl = &displayed_dive.cylinders.cylinders[i];
if (cyl->depth.mm && cyl->cylinder_use != NOT_USED) {
dp = create_dp(0, cyl->depth.mm, i, 0);
if (diveplan.dp) {
diff --git a/qt-models/diveplotdatamodel.cpp b/qt-models/diveplotdatamodel.cpp
index 164cd04a4..eed13c501 100644
--- a/qt-models/diveplotdatamodel.cpp
+++ b/qt-models/diveplotdatamodel.cpp
@@ -190,8 +190,8 @@ void DivePlotDataModel::setDive(dive *d, const plot_info &info)
pInfo = info;
pInfo.entry = (plot_data *)malloc(sizeof(plot_data) * pInfo.nr);
memcpy(pInfo.entry, info.entry, sizeof(plot_data) * pInfo.nr);
- pInfo.pressures = (plot_pressure_data *)malloc(sizeof(plot_pressure_data) * MAX_CYLINDERS * pInfo.nr);
- memcpy(pInfo.pressures, info.pressures, sizeof(plot_pressure_data) * MAX_CYLINDERS * pInfo.nr);
+ pInfo.pressures = (plot_pressure_data *)malloc(sizeof(plot_pressure_data) * pInfo.nr_cylinders * pInfo.nr);
+ memcpy(pInfo.pressures, info.pressures, sizeof(plot_pressure_data) * pInfo.nr_cylinders * pInfo.nr);
endResetModel();
}
diff --git a/qt-models/divetripmodel.cpp b/qt-models/divetripmodel.cpp
index 30ab2175b..220d122d4 100644
--- a/qt-models/divetripmodel.cpp
+++ b/qt-models/divetripmodel.cpp
@@ -157,7 +157,7 @@ QVariant DiveTripModelBase::diveData(const struct dive *d, int column, int role)
case SUIT:
return QString(d->suit);
case CYLINDER:
- return QString(d->cylinder[0].type.description);
+ return d->cylinders.nr > 0 ? QString(d->cylinders.cylinders[0].type.description) : QString();
case SAC:
return displaySac(d, prefs.units.show_units_table);
case OTU:
@@ -1410,7 +1410,9 @@ bool DiveTripModelList::lessThan(const QModelIndex &i1, const QModelIndex &i2) c
case SUIT:
return lessThanHelper(strCmp(d1->suit, d2->suit), row_diff);
case CYLINDER:
- return lessThanHelper(strCmp(d1->cylinder[0].type.description, d2->cylinder[0].type.description), row_diff);
+ if (d1->cylinders.nr > 0 && d2->cylinders.nr > 0)
+ return lessThanHelper(strCmp(d1->cylinders.cylinders[0].type.description, d2->cylinders.cylinders[0].type.description), row_diff);
+ return d1->cylinders.nr - d2->cylinders.nr < 0;
case GAS:
return lessThanHelper(nitrox_sort_value(d1) - nitrox_sort_value(d2), row_diff);
case SAC:
diff --git a/qt-models/models.cpp b/qt-models/models.cpp
index f6b3e927f..ab80f95f0 100644
--- a/qt-models/models.cpp
+++ b/qt-models/models.cpp
@@ -26,10 +26,8 @@ GasSelectionModel *GasSelectionModel::instance()
static QStringList getGasList()
{
QStringList list;
- for (int i = 0; i < MAX_CYLINDERS; i++) {
- cylinder_t *cyl = &displayed_dive.cylinder[i];
- if (cylinder_nodata(cyl))
- break;
+ for (int i = 0; i < displayed_dive.cylinders.nr; i++) {
+ const cylinder_t *cyl = &displayed_dive.cylinders.cylinders[i];
/* Check if we have the same gasmix two or more times
* If yes return more verbose string */
int same_gas = same_gasmix_cylinder(cyl, i, &displayed_dive, true);