profile/planner: don't update dive in ProfileWidget2::plotDive()

In planner or profile-edit mode, the plotDive() function takes
the current plan and turns it into a dive profile. Not only
is this a layering violation (the display layer modifying the
dive), it is also fundamentally flawed. The control-flow is
out of control, if you wish. There are numerous reasons why
the profile needs to be replot, many of which do not need
a recalculated dive profile.

Move the code that updates the dive-profile to the
DivePlannerPointsModel. Thus, the profile recalculations
and replots can be pooled. This will break the planner, since
there now might be missing calls to the profile recalculation.
But it already has some positive effects: when removing
multiple points, the profile is only recalculated once.

This will need much more work, but it is a start.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
Berthold Stoeger 2021-02-27 22:06:05 +01:00 committed by Dirk Hohndel
parent 337d9318ad
commit 77a6bc6d62
3 changed files with 24 additions and 14 deletions

View file

@ -542,13 +542,7 @@ void ProfileWidget2::plotDive(const struct dive *dIn, int dcIn, bool force, bool
decoModelParameters->setText(QString("GF %1/%2").arg(prefs.gflow).arg(prefs.gfhigh)); decoModelParameters->setText(QString("GF %1/%2").arg(prefs.gflow).arg(prefs.gfhigh));
#ifndef SUBSURFACE_MOBILE #ifndef SUBSURFACE_MOBILE
} else { } else {
plannerModel->createTemporaryPlan();
plannerModel->recalcTemporaryPlan();
struct diveplan &diveplan = plannerModel->getDiveplan(); struct diveplan &diveplan = plannerModel->getDiveplan();
if (!diveplan.dp) {
plannerModel->deleteTemporaryPlan();
return;
}
if (decoMode(currentState == PLAN) == VPMB) if (decoMode(currentState == PLAN) == VPMB)
decoModelParameters->setText(QString("VPM-B +%1").arg(diveplan.vpmb_conservatism)); decoModelParameters->setText(QString("VPM-B +%1").arg(diveplan.vpmb_conservatism));
else else
@ -558,7 +552,7 @@ void ProfileWidget2::plotDive(const struct dive *dIn, int dcIn, bool force, bool
const struct divecomputer *currentdc = get_dive_dc_const(d, dc); const struct divecomputer *currentdc = get_dive_dc_const(d, dc);
if (!currentdc || !currentdc->samples) if (!currentdc || !currentdc->samples)
return setEmptyState(); return;
// special handling when switching from empty state // special handling when switching from empty state
animSpeed = instant || currentState == EMPTY ? 0 : qPrefDisplay::animation_speed(); animSpeed = instant || currentState == EMPTY ? 0 : qPrefDisplay::animation_speed();
@ -1742,8 +1736,9 @@ void ProfileWidget2::pointInserted(const QModelIndex &, int from, int to)
gases.emplace(gases.begin() + i, createGas()); gases.emplace(gases.begin() + i, createGas());
} }
if (plannerModel->recalcQ()) // Note: we don't replot the dive here, because when removing multiple
replot(); // points, these might trickle in one-by-one. Instead, the model will
// emit a data-changed signal.
} }
void ProfileWidget2::pointsRemoved(const QModelIndex &, int start, int end) void ProfileWidget2::pointsRemoved(const QModelIndex &, int start, int end)
@ -1752,7 +1747,10 @@ void ProfileWidget2::pointsRemoved(const QModelIndex &, int start, int end)
handles.erase(handles.begin() + start, handles.begin() + end + 1); handles.erase(handles.begin() + start, handles.begin() + end + 1);
gases.erase(gases.begin() + start, gases.begin() + end + 1); gases.erase(gases.begin() + start, gases.begin() + end + 1);
scene()->clearSelection(); scene()->clearSelection();
replot();
// Note: we don't replot the dive here, because when removing multiple
// points, these might trickle in one-by-one. Instead, the model will
// emit a data-changed signal.
} }
void ProfileWidget2::pointsMoved(const QModelIndex &, int start, int end, const QModelIndex &, int row) void ProfileWidget2::pointsMoved(const QModelIndex &, int start, int end, const QModelIndex &, int row)

View file

@ -40,6 +40,8 @@ void DivePlannerPointsModel::removeSelectedPoints(const QVector<int> &rows)
divepoints.erase(divepoints.begin() + v2[i]); divepoints.erase(divepoints.begin() + v2[i]);
endRemoveRows(); endRemoveRows();
} }
updateDiveProfile();
emitDataChanged();
cylinders.updateTrashIcon(); cylinders.updateTrashIcon();
} }
@ -73,7 +75,7 @@ void DivePlannerPointsModel::createSimpleDive(struct dive *dIn)
addStop(M_OR_FT(5, 15), 42 * 60, 0, cylinderid, true, UNDEF_COMP_TYPE); addStop(M_OR_FT(5, 15), 42 * 60, 0, cylinderid, true, UNDEF_COMP_TYPE);
addStop(M_OR_FT(5, 15), 45 * 60, 0, cylinderid, true, UNDEF_COMP_TYPE); addStop(M_OR_FT(5, 15), 45 * 60, 0, cylinderid, true, UNDEF_COMP_TYPE);
} }
updateMaxDepth(); updateDiveProfile();
GasSelectionModel::instance()->repopulate(); GasSelectionModel::instance()->repopulate();
DiveTypeSelectionModel::instance()->repopulate(); DiveTypeSelectionModel::instance()->repopulate();
} }
@ -170,6 +172,8 @@ void DivePlannerPointsModel::loadFromDive(dive *dIn)
recalc = oldRec; recalc = oldRec;
DiveTypeSelectionModel::instance()->repopulate(); DiveTypeSelectionModel::instance()->repopulate();
preserved_until = d->duration; preserved_until = d->duration;
updateDiveProfile();
emitDataChanged(); emitDataChanged();
} }
@ -753,6 +757,7 @@ void DivePlannerPointsModel::addDefaultStop()
void DivePlannerPointsModel::addStop(int milimeters, int seconds) void DivePlannerPointsModel::addStop(int milimeters, int seconds)
{ {
addStop(milimeters, seconds, -1, 0, true, UNDEF_COMP_TYPE); addStop(milimeters, seconds, -1, 0, true, UNDEF_COMP_TYPE);
updateDiveProfile();
} }
// cylinderid_in == -1 means same gas as before. // cylinderid_in == -1 means same gas as before.
@ -887,6 +892,7 @@ void DivePlannerPointsModel::editStop(int row, divedatapoint newData)
if (divepoints[0].cylinderid != old_first_cylid) if (divepoints[0].cylinderid != old_first_cylid)
cylinders.moveAtFirst(divepoints[0].cylinderid); cylinders.moveAtFirst(divepoints[0].cylinderid);
updateDiveProfile();
emit dataChanged(createIndex(row, 0), createIndex(row, COLUMNS - 1)); emit dataChanged(createIndex(row, 0), createIndex(row, COLUMNS - 1));
} }
@ -932,10 +938,14 @@ void DivePlannerPointsModel::remove(const QModelIndex &index)
beginRemoveRows(QModelIndex(), index.row(), index.row()); beginRemoveRows(QModelIndex(), index.row(), index.row());
divepoints.remove(index.row()); divepoints.remove(index.row());
} }
endRemoveRows(); endRemoveRows();
cylinders.updateTrashIcon(); cylinders.updateTrashIcon();
if (divepoints[0].cylinderid != old_first_cylid) if (divepoints[0].cylinderid != old_first_cylid)
cylinders.moveAtFirst(divepoints[0].cylinderid); cylinders.moveAtFirst(divepoints[0].cylinderid);
updateDiveProfile();
emitDataChanged();
} }
struct diveplan &DivePlannerPointsModel::getDiveplan() struct diveplan &DivePlannerPointsModel::getDiveplan()
@ -1035,8 +1045,9 @@ void DivePlannerPointsModel::createTemporaryPlan()
#endif #endif
} }
void DivePlannerPointsModel::recalcTemporaryPlan() void DivePlannerPointsModel::updateDiveProfile()
{ {
createTemporaryPlan();
if (diveplan_empty(&diveplan)) if (diveplan_empty(&diveplan))
return; return;
@ -1047,6 +1058,7 @@ void DivePlannerPointsModel::recalcTemporaryPlan()
memset(&plan_deco_state, 0, sizeof(struct deco_state)); memset(&plan_deco_state, 0, sizeof(struct deco_state));
plan(&plan_deco_state, &diveplan, d, DECOTIMESTEP, stoptable, &cache, isPlanner(), false); plan(&plan_deco_state, &diveplan, d, DECOTIMESTEP, stoptable, &cache, isPlanner(), false);
updateMaxDepth();
plan_copy = (struct diveplan *)malloc(sizeof(struct diveplan)); plan_copy = (struct diveplan *)malloc(sizeof(struct diveplan));
lock_planner(); lock_planner();
cloneDiveplan(&diveplan, plan_copy); cloneDiveplan(&diveplan, plan_copy);

View file

@ -89,8 +89,6 @@ slots:
void remove(const QModelIndex &index); void remove(const QModelIndex &index);
void cancelPlan(); void cancelPlan();
void removeDeco(); void removeDeco();
void createTemporaryPlan();
void recalcTemporaryPlan(); // Writes the plan into the dive.
void deleteTemporaryPlan(); void deleteTemporaryPlan();
void emitDataChanged(); void emitDataChanged();
void setRebreatherMode(int mode); void setRebreatherMode(int mode);
@ -123,6 +121,8 @@ private:
int lastEnteredPoint() const; int lastEnteredPoint() const;
bool updateMaxDepth(); bool updateMaxDepth();
void createPlan(bool replanCopy); void createPlan(bool replanCopy);
void updateDiveProfile(); // Creates a temporary plan and updates the dive profile with it.
void createTemporaryPlan();
struct diveplan diveplan; struct diveplan diveplan;
struct divedatapoint *cloneDiveplan(struct diveplan *plan_src, struct diveplan *plan_copy); struct divedatapoint *cloneDiveplan(struct diveplan *plan_src, struct diveplan *plan_copy);
void computeVariationsDone(QString text); void computeVariationsDone(QString text);