Planner: Fix Editing of Plans in Multi-Divecomputer Dives.

Currently editing of planned dives that have been merged with actual
(logged) dives only works if the 'Planned dive' divecomputer is the
first divecomputer, and this divecomputer is selected when clicking
'Edit planned dive'. In other cases the profile of the first
divecomputer is overlaid with the profile of the planned dive, and the
first divecomputer's profile is overwritten when saving the dive plan.
Fix this problem.

Triggered by @SeppoTakalo's comment (https://github.com/subsurface/subsurface/issues/1913#issuecomment-2075562119): Users don't like that planned dives show up as their own entries in the dive list, so being able to merge them with the actual dive after it has been executed is a good feature - but this wasn't working well until now.

Signed-off-by: Michael Keller <github@ike.ch>
This commit is contained in:
Michael Keller 2024-04-26 08:16:08 +12:00
parent a83349015a
commit 528532572f
11 changed files with 114 additions and 106 deletions

View file

@ -23,7 +23,7 @@
#include <QBuffer>
#endif
DivePlannerWidget::DivePlannerWidget(dive &planned_dive, PlannerWidgets *parent)
DivePlannerWidget::DivePlannerWidget(dive &planned_dive, int dcNr, PlannerWidgets *parent)
{
DivePlannerPointsModel *plannerModel = DivePlannerPointsModel::instance();
CylindersModel *cylinders = DivePlannerPointsModel::instance()->cylindersModel();
@ -52,7 +52,7 @@ DivePlannerWidget::DivePlannerWidget(dive &planned_dive, PlannerWidgets *parent)
view->setColumnHidden(CylindersModel::SENSORS, true);
view->setItemDelegateForColumn(CylindersModel::TYPE, new TankInfoDelegate(this));
auto tankUseDelegate = new TankUseDelegate(this);
tankUseDelegate->setCurrentDC(get_dive_dc(&planned_dive, 0));
tankUseDelegate->setCurrentDC(get_dive_dc(&planned_dive, dcNr));
view->setItemDelegateForColumn(CylindersModel::USE, tankUseDelegate);
connect(ui.cylinderTableWidget, &TableView::addButtonClicked, plannerModel, &DivePlannerPointsModel::addCylinder_clicked);
connect(ui.tableWidget, &TableView::addButtonClicked, plannerModel, &DivePlannerPointsModel::addDefaultStop);
@ -539,7 +539,8 @@ void PlannerDetails::setPlanNotes(QString plan)
PlannerWidgets::PlannerWidgets() :
planned_dive(alloc_dive()),
plannerWidget(*planned_dive, this),
dcNr(0),
plannerWidget(*planned_dive, dcNr, this),
plannerSettingsWidget(this)
{
connect(plannerDetails.printPlan(), &QPushButton::pressed, this, &PlannerWidgets::printDecoPlan);
@ -556,21 +557,27 @@ struct dive *PlannerWidgets::getDive() const
return planned_dive.get();
}
divemode_t PlannerWidgets::getRebreatherMode() const
int PlannerWidgets::getDcNr()
{
return planned_dive->dc.divemode;
return dcNr;
}
void PlannerWidgets::preparePlanDive(const dive *currentDive)
divemode_t PlannerWidgets::getRebreatherMode() const
{
return get_dive_dc_const(planned_dive.get(), dcNr)->divemode;
}
void PlannerWidgets::preparePlanDive(const dive *currentDive, int currentDcNr)
{
DivePlannerPointsModel::instance()->setPlanMode(DivePlannerPointsModel::PLAN);
// create a simple starting dive, using the first gas from the just copied cylinders
DivePlannerPointsModel::instance()->createSimpleDive(planned_dive.get());
dcNr = 0;
// plan the dive in the same mode as the currently selected one
if (currentDive) {
plannerSettingsWidget.setDiveMode(currentDive->dc.divemode);
plannerSettingsWidget.setBailoutVisibility(currentDive->dc.divemode);
plannerSettingsWidget.setDiveMode(get_dive_dc_const(currentDive, currentDcNr)->divemode);
plannerSettingsWidget.setBailoutVisibility(get_dive_dc_const(currentDive, currentDcNr)->divemode);
if (currentDive->salinity)
plannerWidget.setSalinity(currentDive->salinity);
else // No salinity means salt water
@ -586,15 +593,16 @@ void PlannerWidgets::planDive()
plannerWidget.setupStartTime(timestampToDateTime(planned_dive->when)); // This will reload the profile!
}
void PlannerWidgets::prepareReplanDive(const dive *d)
void PlannerWidgets::prepareReplanDive(const dive *currentDive, int currentDcNr)
{
copy_dive(d, planned_dive.get());
copy_dive(currentDive, planned_dive.get());
dcNr = currentDcNr;
}
void PlannerWidgets::replanDive(int currentDC)
void PlannerWidgets::replanDive()
{
DivePlannerPointsModel::instance()->setPlanMode(DivePlannerPointsModel::PLAN);
DivePlannerPointsModel::instance()->loadFromDive(planned_dive.get(), currentDC);
DivePlannerPointsModel::instance()->loadFromDive(planned_dive.get(), dcNr);
plannerWidget.setReplanButton(true);
plannerWidget.setupStartTime(timestampToDateTime(planned_dive->when));
@ -603,7 +611,7 @@ void PlannerWidgets::replanDive(int currentDC)
if (planned_dive->salinity)
plannerWidget.setSalinity(planned_dive->salinity);
reset_cylinders(planned_dive.get(), true);
DivePlannerPointsModel::instance()->cylindersModel()->updateDive(planned_dive.get(), currentDC);
DivePlannerPointsModel::instance()->cylindersModel()->updateDive(planned_dive.get(), dcNr);
}
void PlannerWidgets::printDecoPlan()

View file

@ -18,7 +18,7 @@ struct dive;
class DivePlannerWidget : public QWidget {
Q_OBJECT
public:
explicit DivePlannerWidget(dive &planned_dive, PlannerWidgets *parent);
explicit DivePlannerWidget(dive &planned_dive, int dcNr, PlannerWidgets *parent);
~DivePlannerWidget();
void setReplanButton(bool replan);
public
@ -80,17 +80,20 @@ class PlannerWidgets : public QObject {
public:
PlannerWidgets();
~PlannerWidgets();
void preparePlanDive(const dive *currentDive); // Create a new planned dive
void preparePlanDive(const dive *currentDive, int currentDc); // Create a new planned dive
void planDive();
void prepareReplanDive(const dive *d); // Make a copy of the dive to be replanned
void replanDive(int currentDC);
void prepareReplanDive(const dive *currentDive, int currentDc); // Make a copy of the dive to be replanned
void replanDive();
struct dive *getDive() const;
int getDcNr();
divemode_t getRebreatherMode() const;
public
slots:
void printDecoPlan();
public:
private:
OwningDivePtr planned_dive;
int dcNr;
public:
DivePlannerWidget plannerWidget;
PlannerSettingsWidget plannerSettingsWidget;
PlannerDetails plannerDetails;

View file

@ -665,8 +665,8 @@ void MainWindow::on_actionReplanDive_triggered()
{
if (!plannerStateClean() || !current_dive || !userMayChangeAppState())
return;
else if (!is_dc_planner(&current_dive->dc)) {
if (QMessageBox::warning(this, tr("Warning"), tr("Trying to replan a dive that's not a planned dive."),
else if (!is_dc_planner(get_dive_dc(current_dive, profile->dc))) {
if (QMessageBox::warning(this, tr("Warning"), tr("Trying to replan a dive dive profile that is not a dive plan."),
QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Cancel)
return;
}
@ -675,9 +675,9 @@ void MainWindow::on_actionReplanDive_triggered()
setApplicationState(ApplicationState::PlanDive);
disableShortcuts(true);
plannerWidgets->prepareReplanDive(current_dive);
profile->setPlanState(plannerWidgets->getDive(), profile->dc);
plannerWidgets->replanDive(profile->dc);
plannerWidgets->prepareReplanDive(current_dive, profile->dc);
profile->setPlanState(plannerWidgets->getDive(), plannerWidgets->getDcNr());
plannerWidgets->replanDive();
}
void MainWindow::on_actionDivePlanner_triggered()
@ -689,8 +689,8 @@ void MainWindow::on_actionDivePlanner_triggered()
setApplicationState(ApplicationState::PlanDive);
disableShortcuts(true);
plannerWidgets->preparePlanDive(current_dive);
profile->setPlanState(plannerWidgets->getDive(), 0);
plannerWidgets->preparePlanDive(current_dive, profile->dc);
profile->setPlanState(plannerWidgets->getDive(), plannerWidgets->getDcNr());
plannerWidgets->planDive();
}

View file

@ -157,11 +157,11 @@ void ProfileWidget::setEnabledToolbar(bool enabled)
b->setEnabled(enabled);
}
void ProfileWidget::setDive(const struct dive *d)
void ProfileWidget::setDive(const struct dive *d, int dcNr)
{
stack->setCurrentIndex(1); // show profile
bool freeDiveMode = d->dc.divemode == FREEDIVE;
bool freeDiveMode = get_dive_dc_const(d, dcNr)->divemode == FREEDIVE;
ui.profCalcCeiling->setDisabled(freeDiveMode);
ui.profCalcCeiling->setDisabled(freeDiveMode);
ui.profCalcAllTissues ->setDisabled(freeDiveMode);
@ -217,12 +217,12 @@ void ProfileWidget::plotDive(dive *dIn, int dcIn)
setEnabledToolbar(d != nullptr);
if (editedDive) {
view->plotDive(editedDive.get(), editedDc);
setDive(editedDive.get());
setDive(editedDive.get(), dc);
} else if (d) {
view->setProfileState(d, dc);
view->resetZoom(); // when switching dive, reset the zoomLevel
view->plotDive(d, dc);
setDive(d);
setDive(d, dc);
} else {
view->clear();
stack->setCurrentIndex(0);
@ -274,11 +274,12 @@ void ProfileWidget::divesChanged(const QVector<dive *> &dives, DiveField field)
plotCurrentDive();
}
void ProfileWidget::setPlanState(const struct dive *d, int dc)
void ProfileWidget::setPlanState(const struct dive *d, int dcNr)
{
exitEditMode();
view->setPlanState(d, dc);
setDive(d);
dc = dcNr;
view->setPlanState(d, dcNr);
setDive(d, dcNr);
}
void ProfileWidget::unsetProfHR()

View file

@ -44,7 +44,7 @@ private:
std::vector<QAction *> toolbarActions;
Ui::ProfileWidget ui;
QStackedWidget *stack;
void setDive(const struct dive *d);
void setDive(const struct dive *d, int dcNr);
void editDive();
void exitEditMode();
void rotateDC(int dir);