mirror of
https://github.com/subsurface/subsurface.git
synced 2025-01-31 18:03:24 +00:00
planner: remove displayed_dive from DivePlannerModel
To remove global state, make the dive that DivePlannerModel works on a member variable. Pass the dive in createSimpleDive() and loadFromDive(). Moreover, this should pave the way to more fine-grained undo in the planner. Ultimately, the planner should not be modal. Attention: for now, the dive must still be displayed_dive, because of the convoluted way in which the profile and the planner work on the same dive. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
parent
e419ebf55a
commit
1ec0790d50
4 changed files with 72 additions and 63 deletions
|
@ -545,7 +545,7 @@ void PlannerWidgets::planDive()
|
|||
dc_number = 0;
|
||||
|
||||
// create a simple starting dive, using the first gas from the just copied cylinders
|
||||
DivePlannerPointsModel::instance()->createSimpleDive();
|
||||
DivePlannerPointsModel::instance()->createSimpleDive(&displayed_dive);
|
||||
|
||||
// plan the dive in the same mode as the currently selected one
|
||||
if (current_dive) {
|
||||
|
@ -563,17 +563,20 @@ void PlannerWidgets::planDive()
|
|||
|
||||
void PlannerWidgets::replanDive()
|
||||
{
|
||||
if (!current_dive)
|
||||
return;
|
||||
copy_dive(current_dive, &displayed_dive); // Planning works on a copy of the dive (for now).
|
||||
DivePlannerPointsModel::instance()->setPlanMode(DivePlannerPointsModel::PLAN);
|
||||
DivePlannerPointsModel::instance()->loadFromDive(&displayed_dive);
|
||||
|
||||
MainWindow::instance()->graphics->setPlanState();
|
||||
|
||||
plannerWidget.setReplanButton(true);
|
||||
plannerWidget.setupStartTime(timestampToDateTime(current_dive->when));
|
||||
if (current_dive->surface_pressure.mbar)
|
||||
plannerWidget.setSurfacePressure(current_dive->surface_pressure.mbar);
|
||||
if (current_dive->salinity)
|
||||
plannerWidget.setSalinity(current_dive->salinity);
|
||||
DivePlannerPointsModel::instance()->loadFromDive(current_dive);
|
||||
plannerWidget.setupStartTime(timestampToDateTime(displayed_dive.when));
|
||||
if (displayed_dive.surface_pressure.mbar)
|
||||
plannerWidget.setSurfacePressure(displayed_dive.surface_pressure.mbar);
|
||||
if (displayed_dive.salinity)
|
||||
plannerWidget.setSalinity(displayed_dive.salinity);
|
||||
reset_cylinders(&displayed_dive, true);
|
||||
DivePlannerPointsModel::instance()->cylindersModel()->updateDive(&displayed_dive);
|
||||
}
|
||||
|
|
|
@ -1514,10 +1514,11 @@ void MainWindow::editCurrentDive()
|
|||
return;
|
||||
|
||||
disableShortcuts();
|
||||
copy_dive(current_dive, &displayed_dive); // Work on a copy of the dive
|
||||
DivePlannerPointsModel::instance()->setPlanMode(DivePlannerPointsModel::ADD);
|
||||
graphics->setAddState();
|
||||
setApplicationState(ApplicationState::EditDive);
|
||||
DivePlannerPointsModel::instance()->loadFromDive(current_dive);
|
||||
DivePlannerPointsModel::instance()->loadFromDive(&displayed_dive);
|
||||
mainTab->enableEdition();
|
||||
}
|
||||
|
||||
|
|
|
@ -43,13 +43,14 @@ void DivePlannerPointsModel::removeSelectedPoints(const QVector<int> &rows)
|
|||
cylinders.updateTrashIcon();
|
||||
}
|
||||
|
||||
void DivePlannerPointsModel::createSimpleDive()
|
||||
void DivePlannerPointsModel::createSimpleDive(struct dive *dIn)
|
||||
{
|
||||
// clean out the dive and give it an id and the correct dc model
|
||||
clear_dive(&displayed_dive);
|
||||
displayed_dive.id = dive_getUniqID();
|
||||
displayed_dive.when = QDateTime::currentMSecsSinceEpoch() / 1000L + gettimezoneoffset() + 3600;
|
||||
displayed_dive.dc.model = strdup("planned dive"); // don't translate! this is stored in the XML file
|
||||
d = dIn;
|
||||
clear_dive(d);
|
||||
d->id = dive_getUniqID();
|
||||
d->when = QDateTime::currentMSecsSinceEpoch() / 1000L + gettimezoneoffset() + 3600;
|
||||
d->dc.model = strdup("planned dive"); // don't translate! this is stored in the XML file
|
||||
|
||||
clear();
|
||||
setupCylinders();
|
||||
|
@ -57,7 +58,7 @@ void DivePlannerPointsModel::createSimpleDive()
|
|||
|
||||
// initialize the start time in the plan
|
||||
diveplan.when = dateTimeToTimestamp(startTime);
|
||||
displayed_dive.when = diveplan.when;
|
||||
d->when = diveplan.when;
|
||||
|
||||
// Use gas from the first cylinder
|
||||
int cylinderid = 0;
|
||||
|
@ -92,8 +93,10 @@ void DivePlannerPointsModel::setupStartTime()
|
|||
}
|
||||
}
|
||||
|
||||
void DivePlannerPointsModel::loadFromDive(dive *d)
|
||||
void DivePlannerPointsModel::loadFromDive(dive *dIn)
|
||||
{
|
||||
d = dIn;
|
||||
|
||||
int depthsum = 0;
|
||||
int samplecount = 0;
|
||||
o2pressure_t last_sp;
|
||||
|
@ -102,7 +105,7 @@ void DivePlannerPointsModel::loadFromDive(dive *d)
|
|||
const struct event *evd = NULL;
|
||||
enum divemode_t current_divemode = UNDEF_COMP_TYPE;
|
||||
recalc = false;
|
||||
cylinders.updateDive(&displayed_dive);
|
||||
cylinders.updateDive(d);
|
||||
duration_t lasttime = { 0 };
|
||||
duration_t lastrecordedtime = {};
|
||||
duration_t newtime = {};
|
||||
|
@ -175,45 +178,45 @@ void DivePlannerPointsModel::loadFromDive(dive *d)
|
|||
// setup the cylinder widget accordingly
|
||||
void DivePlannerPointsModel::setupCylinders()
|
||||
{
|
||||
clear_cylinder_table(&displayed_dive.cylinders);
|
||||
clear_cylinder_table(&d->cylinders);
|
||||
if (mode == PLAN && current_dive) {
|
||||
// take the displayed cylinders from the selected dive as starting point
|
||||
copy_used_cylinders(current_dive, &displayed_dive, !prefs.display_unused_tanks);
|
||||
reset_cylinders(&displayed_dive, true);
|
||||
copy_used_cylinders(current_dive, d, !prefs.display_unused_tanks);
|
||||
reset_cylinders(d, true);
|
||||
|
||||
if (displayed_dive.cylinders.nr > 0) {
|
||||
cylinders.updateDive(&displayed_dive);
|
||||
if (d->cylinders.nr > 0) {
|
||||
cylinders.updateDive(d);
|
||||
return; // We have at least one cylinder
|
||||
}
|
||||
}
|
||||
if (!empty_string(prefs.default_cylinder)) {
|
||||
cylinder_t cyl = empty_cylinder;
|
||||
fill_default_cylinder(&displayed_dive, &cyl);
|
||||
fill_default_cylinder(d, &cyl);
|
||||
cyl.start = cyl.type.workingpressure;
|
||||
add_cylinder(&displayed_dive.cylinders, 0, cyl);
|
||||
add_cylinder(&d->cylinders, 0, cyl);
|
||||
} else {
|
||||
cylinder_t cyl = empty_cylinder;
|
||||
// roughly an AL80
|
||||
cyl.type.description = copy_qstring(tr("unknown"));
|
||||
cyl.type.size.mliter = 11100;
|
||||
cyl.type.workingpressure.mbar = 207000;
|
||||
add_cylinder(&displayed_dive.cylinders, 0, cyl);
|
||||
add_cylinder(&d->cylinders, 0, cyl);
|
||||
}
|
||||
reset_cylinders(&displayed_dive, false);
|
||||
cylinders.updateDive(&displayed_dive);
|
||||
reset_cylinders(d, false);
|
||||
cylinders.updateDive(d);
|
||||
}
|
||||
|
||||
// Update the dive's maximum depth. Returns true if max. depth changed
|
||||
bool DivePlannerPointsModel::updateMaxDepth()
|
||||
{
|
||||
int prevMaxDepth = displayed_dive.maxdepth.mm;
|
||||
displayed_dive.maxdepth.mm = 0;
|
||||
int prevMaxDepth = d->maxdepth.mm;
|
||||
d->maxdepth.mm = 0;
|
||||
for (int i = 0; i < rowCount(); i++) {
|
||||
divedatapoint p = at(i);
|
||||
if (p.depth.mm > displayed_dive.maxdepth.mm)
|
||||
displayed_dive.maxdepth.mm = p.depth.mm;
|
||||
if (p.depth.mm > d->maxdepth.mm)
|
||||
d->maxdepth.mm = p.depth.mm;
|
||||
}
|
||||
return displayed_dive.maxdepth.mm != prevMaxDepth;
|
||||
return d->maxdepth.mm != prevMaxDepth;
|
||||
}
|
||||
|
||||
void DivePlannerPointsModel::removeDeco()
|
||||
|
@ -289,13 +292,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(get_cylinder(&displayed_dive, p.cylinderid), p.cylinderid, &displayed_dive, true);
|
||||
int same_gas = same_gasmix_cylinder(get_cylinder(d, p.cylinderid), p.cylinderid, d, true);
|
||||
if (same_gas == -1)
|
||||
return get_gas_string(get_cylinder(&displayed_dive, p.cylinderid)->gasmix);
|
||||
return get_gas_string(get_cylinder(d, p.cylinderid)->gasmix);
|
||||
else
|
||||
return get_gas_string(get_cylinder(&displayed_dive, p.cylinderid)->gasmix) +
|
||||
return get_gas_string(get_cylinder(d, p.cylinderid)->gasmix) +
|
||||
QString(" (%1 %2 ").arg(tr("cyl.")).arg(p.cylinderid + 1) +
|
||||
get_cylinder(&displayed_dive, p.cylinderid)->type.description + ")";
|
||||
get_cylinder(d, p.cylinderid)->type.description + ")";
|
||||
}
|
||||
} else if (role == Qt::DecorationRole) {
|
||||
switch (index.column()) {
|
||||
|
@ -388,7 +391,7 @@ bool DivePlannerPointsModel::setData(const QModelIndex &index, const QVariant &v
|
|||
p.setpoint = p.divemode == CCR ? prefs.defaultsetpoint : 0;
|
||||
}
|
||||
if (index.row() == 0)
|
||||
displayed_dive.dc.divemode = (enum divemode_t) value.toInt();
|
||||
d->dc.divemode = (enum divemode_t) value.toInt();
|
||||
break;
|
||||
}
|
||||
editStop(index.row(), p);
|
||||
|
@ -450,6 +453,7 @@ int DivePlannerPointsModel::rowCount(const QModelIndex&) const
|
|||
}
|
||||
|
||||
DivePlannerPointsModel::DivePlannerPointsModel(QObject *parent) : QAbstractTableModel(parent),
|
||||
d(nullptr),
|
||||
cylinders(true),
|
||||
mode(NOTHING),
|
||||
recalc(false)
|
||||
|
@ -539,7 +543,7 @@ void DivePlannerPointsModel::setGFLow(const int gflow)
|
|||
void DivePlannerPointsModel::setRebreatherMode(int mode)
|
||||
{
|
||||
int i;
|
||||
displayed_dive.dc.divemode = (divemode_t) mode;
|
||||
d->dc.divemode = (divemode_t) mode;
|
||||
for (i=0; i < rowCount(); i++) {
|
||||
divepoints[i].setpoint = mode == CCR ? prefs.defaultsetpoint : 0;
|
||||
divepoints[i].divemode = (enum divemode_t) mode;
|
||||
|
@ -724,7 +728,7 @@ void DivePlannerPointsModel::setStartDate(const QDate &date)
|
|||
{
|
||||
startTime.setDate(date);
|
||||
diveplan.when = dateTimeToTimestamp(startTime);
|
||||
displayed_dive.when = diveplan.when;
|
||||
d->when = diveplan.when;
|
||||
emitDataChanged();
|
||||
}
|
||||
|
||||
|
@ -732,7 +736,7 @@ void DivePlannerPointsModel::setStartTime(const QTime &t)
|
|||
{
|
||||
startTime.setTime(t);
|
||||
diveplan.when = dateTimeToTimestamp(startTime);
|
||||
displayed_dive.when = diveplan.when;
|
||||
d->when = diveplan.when;
|
||||
emitDataChanged();
|
||||
}
|
||||
|
||||
|
@ -813,7 +817,7 @@ int DivePlannerPointsModel::addStop(int milimeters, int seconds, int cylinderid_
|
|||
}
|
||||
}
|
||||
if (divemode == UNDEF_COMP_TYPE)
|
||||
divemode = displayed_dive.dc.divemode;
|
||||
divemode = d->dc.divemode;
|
||||
|
||||
// add the new stop
|
||||
beginInsertRows(QModelIndex(), row, row);
|
||||
|
@ -1023,8 +1027,8 @@ void DivePlannerPointsModel::createTemporaryPlan()
|
|||
// what does the cache do???
|
||||
struct deco_state *cache = NULL;
|
||||
struct divedatapoint *dp = NULL;
|
||||
for (int i = 0; i < displayed_dive.cylinders.nr; i++) {
|
||||
cylinder_t *cyl = get_cylinder(&displayed_dive, i);
|
||||
for (int i = 0; i < d->cylinders.nr; i++) {
|
||||
cylinder_t *cyl = get_cylinder(d, i);
|
||||
if (cyl->depth.mm && cyl->cylinder_use != NOT_USED) {
|
||||
dp = create_dp(0, cyl->depth.mm, i, 0);
|
||||
if (diveplan.dp) {
|
||||
|
@ -1045,7 +1049,7 @@ void DivePlannerPointsModel::createTemporaryPlan()
|
|||
struct diveplan *plan_copy;
|
||||
|
||||
memset(&plan_deco_state, 0, sizeof(struct deco_state));
|
||||
plan(&plan_deco_state, &diveplan, &displayed_dive, DECOTIMESTEP, stoptable, &cache, isPlanner(), false);
|
||||
plan(&plan_deco_state, &diveplan, d, DECOTIMESTEP, stoptable, &cache, isPlanner(), false);
|
||||
plan_copy = (struct diveplan *)malloc(sizeof(struct diveplan));
|
||||
lock_planner();
|
||||
cloneDiveplan(&diveplan, plan_copy);
|
||||
|
@ -1059,12 +1063,12 @@ void DivePlannerPointsModel::createTemporaryPlan()
|
|||
computeVariations(plan_copy, &plan_deco_state);
|
||||
#endif
|
||||
final_deco_state = plan_deco_state;
|
||||
emit calculatedPlanNotes(QString(displayed_dive.notes));
|
||||
emit calculatedPlanNotes(QString(d->notes));
|
||||
}
|
||||
// throw away the cache
|
||||
free(cache);
|
||||
#if DEBUG_PLAN
|
||||
save_dive(stderr, &displayed_dive);
|
||||
save_dive(stderr, d);
|
||||
dump_plan(&diveplan);
|
||||
#endif
|
||||
}
|
||||
|
@ -1084,7 +1088,7 @@ void DivePlannerPointsModel::saveDuplicatePlan()
|
|||
createPlan(true);
|
||||
}
|
||||
|
||||
struct divedatapoint * DivePlannerPointsModel::cloneDiveplan(struct diveplan *plan_src, struct diveplan *plan_copy)
|
||||
struct divedatapoint *DivePlannerPointsModel::cloneDiveplan(struct diveplan *plan_src, struct diveplan *plan_copy)
|
||||
{
|
||||
divedatapoint *src, *last_segment;
|
||||
divedatapoint **dp;
|
||||
|
@ -1152,7 +1156,7 @@ void DivePlannerPointsModel::computeVariations(struct diveplan *original_plan, c
|
|||
return;
|
||||
|
||||
struct dive *dive = alloc_dive();
|
||||
copy_dive(&displayed_dive, dive);
|
||||
copy_dive(d, dive);
|
||||
struct decostop original[60], deeper[60], shallower[60], shorter[60], longer[60];
|
||||
struct deco_state *cache = NULL, *save = NULL;
|
||||
struct diveplan plan_copy;
|
||||
|
@ -1241,10 +1245,10 @@ finish:
|
|||
|
||||
void DivePlannerPointsModel::computeVariationsDone(QString variations)
|
||||
{
|
||||
QString notes = QString(displayed_dive.notes);
|
||||
free(displayed_dive.notes);
|
||||
displayed_dive.notes = copy_qstring(notes.replace("VARIATIONS", variations));
|
||||
emit calculatedPlanNotes(QString(displayed_dive.notes));
|
||||
QString notes = QString(d->notes);
|
||||
free(d->notes);
|
||||
d->notes = copy_qstring(notes.replace("VARIATIONS", variations));
|
||||
emit calculatedPlanNotes(QString(d->notes));
|
||||
}
|
||||
|
||||
void DivePlannerPointsModel::createPlan(bool replanCopy)
|
||||
|
@ -1258,7 +1262,7 @@ void DivePlannerPointsModel::createPlan(bool replanCopy)
|
|||
|
||||
//TODO: C-based function here?
|
||||
struct decostop stoptable[60];
|
||||
plan(&ds_after_previous_dives, &diveplan, &displayed_dive, DECOTIMESTEP, stoptable, &cache, isPlanner(), true);
|
||||
plan(&ds_after_previous_dives, &diveplan, d, DECOTIMESTEP, stoptable, &cache, isPlanner(), true);
|
||||
struct diveplan *plan_copy;
|
||||
plan_copy = (struct diveplan *)malloc(sizeof(struct diveplan));
|
||||
lock_planner();
|
||||
|
@ -1269,7 +1273,7 @@ void DivePlannerPointsModel::createPlan(bool replanCopy)
|
|||
free(cache);
|
||||
|
||||
// Fixup planner notes.
|
||||
if (current_dive && displayed_dive.id == current_dive->id) {
|
||||
if (current_dive && d->id == current_dive->id) {
|
||||
// Try to identify old planner output and remove only this part
|
||||
// Treat user provided text as plain text.
|
||||
QTextDocument notesDocument;
|
||||
|
@ -1295,8 +1299,8 @@ void DivePlannerPointsModel::createPlan(bool replanCopy)
|
|||
}
|
||||
// Deal with line breaks
|
||||
oldnotes.replace("\n", "<br>");
|
||||
oldnotes.append(displayed_dive.notes);
|
||||
displayed_dive.notes = copy_qstring(oldnotes);
|
||||
oldnotes.append(d->notes);
|
||||
d->notes = copy_qstring(oldnotes);
|
||||
// If we save as new create a copy of the dive here
|
||||
}
|
||||
|
||||
|
@ -1305,24 +1309,24 @@ void DivePlannerPointsModel::createPlan(bool replanCopy)
|
|||
// so that the Undo-commands update the display accordingly (see condition in updateDiveInfo().
|
||||
|
||||
// Now, add or modify the dive.
|
||||
if (!current_dive || displayed_dive.id != current_dive->id) {
|
||||
if (!current_dive || d->id != current_dive->id) {
|
||||
// we were planning a new dive, not re-planning an existing one
|
||||
displayed_dive.divetrip = nullptr; // Should not be necessary, just in case!
|
||||
d->divetrip = nullptr; // Should not be necessary, just in case!
|
||||
#if !defined(SUBSURFACE_TESTING)
|
||||
Command::addDive(&displayed_dive, autogroup, true);
|
||||
Command::addDive(d, autogroup, true);
|
||||
#endif // !SUBSURFACE_TESTING
|
||||
} else {
|
||||
copy_events_until(current_dive, &displayed_dive, preserved_until.seconds);
|
||||
copy_events_until(current_dive, d, preserved_until.seconds);
|
||||
if (replanCopy) {
|
||||
// we were planning an old dive and save as a new dive
|
||||
displayed_dive.id = dive_getUniqID(); // Things will break horribly if we create dives with the same id.
|
||||
d->id = dive_getUniqID(); // Things will break horribly if we create dives with the same id.
|
||||
#if !defined(SUBSURFACE_TESTING)
|
||||
Command::addDive(&displayed_dive, false, false);
|
||||
Command::addDive(d, false, false);
|
||||
#endif // !SUBSURFACE_TESTING
|
||||
} else {
|
||||
// we were planning an old dive and rewrite the plan
|
||||
#if !defined(SUBSURFACE_TESTING)
|
||||
Command::replanDive(&displayed_dive);
|
||||
Command::replanDive(d);
|
||||
#endif // !SUBSURFACE_TESTING
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ public:
|
|||
void removeSelectedPoints(const QVector<int> &rows);
|
||||
void setPlanMode(Mode mode);
|
||||
bool isPlanner() const;
|
||||
void createSimpleDive();
|
||||
void createSimpleDive(struct dive *d);
|
||||
Mode currentMode() const;
|
||||
bool setRecalc(bool recalc);
|
||||
bool recalcQ() const;
|
||||
|
@ -130,6 +130,7 @@ private:
|
|||
void computeVariations(struct diveplan *diveplan, const struct deco_state *ds);
|
||||
void computeVariationsFreeDeco(struct diveplan *diveplan, struct deco_state *ds);
|
||||
int analyzeVariations(struct decostop *min, struct decostop *mid, struct decostop *max, const char *unit);
|
||||
struct dive *d;
|
||||
CylindersModel cylinders;
|
||||
Mode mode;
|
||||
bool recalc;
|
||||
|
|
Loading…
Add table
Reference in a new issue