diff --git a/commands/command.cpp b/commands/command.cpp index b466f1156..1772f9063 100644 --- a/commands/command.cpp +++ b/commands/command.cpp @@ -276,12 +276,12 @@ void pasteDives(const dive *d, dive_components what) void replanDive(dive *d) { - execute(new ReplanDive(d, false)); + execute(new ReplanDive(d)); } -void editProfile(dive *d) +void editProfile(const dive *d, EditProfileType type, int count) { - execute(new ReplanDive(d, true)); + execute(new EditProfile(d, type, count)); } int addWeight(bool currentDiveOnly) diff --git a/commands/command.h b/commands/command.h index 39af8e7fb..d5e22b135 100644 --- a/commands/command.h +++ b/commands/command.h @@ -93,8 +93,13 @@ int editTags(const QStringList &newList, bool currentDiveOnly); int editBuddies(const QStringList &newList, bool currentDiveOnly); int editDiveGuide(const QStringList &newList, bool currentDiveOnly); void pasteDives(const dive *d, dive_components what); -void replanDive(dive *d); // dive computer(s) and cylinder(s) will be reset! -void editProfile(dive *d); // dive computer(s) and cylinder(s) will be reset! +enum class EditProfileType { + ADD, + REMOVE, + MOVE, +}; +void replanDive(dive *d); // dive computer(s) and cylinder(s) of first argument will be consumed! +void editProfile(const dive *d, EditProfileType type, int count); int addWeight(bool currentDiveOnly); int removeWeight(int index, bool currentDiveOnly); int editWeight(int index, weightsystem_t ws, bool currentDiveOnly); diff --git a/commands/command_edit.cpp b/commands/command_edit.cpp index 5b89f24d3..5d835a8ee 100644 --- a/commands/command_edit.cpp +++ b/commands/command_edit.cpp @@ -794,7 +794,7 @@ void PasteDives::redo() } // ***** ReplanDive ***** -ReplanDive::ReplanDive(dive *source, bool edit_profile) : d(current_dive), +ReplanDive::ReplanDive(dive *source) : d(current_dive), when(0), maxdepth({0}), meandepth({0}), @@ -824,7 +824,7 @@ ReplanDive::ReplanDive(dive *source, bool edit_profile) : d(current_dive), std::swap(source->cylinders, cylinders); std::swap(source->dc, dc); - setText((edit_profile ? Command::Base::tr("Replan dive") : Command::Base::tr("Edit profile")) + diveNumberOrDate(d)); + setText(Command::Base::tr("Replan dive")); } ReplanDive::~ReplanDive() @@ -867,6 +867,77 @@ void ReplanDive::redo() undo(); } +// ***** EditProfile ***** +QString editProfileTypeToString(EditProfileType type, int count) +{ + switch (type) { + default: + case EditProfileType::ADD: return Command::Base::tr("Add stop"); + case EditProfileType::REMOVE: return Command::Base::tr("Remove %n stop(s)", "", count); + case EditProfileType::MOVE: return Command::Base::tr("Move %n stop(s)", "", count); + } +} + +EditProfile::EditProfile(const dive *source, EditProfileType type, int count) : d(current_dive), + dcNr(dc_number), + maxdepth({0}), + meandepth({0}), + dcmaxdepth({0}), + duration({0}), + dc({ 0 }) +{ + const struct divecomputer *sdc = get_dive_dc_const(source, dcNr); + if (!sdc) + d = nullptr; // Signal that we refuse to do anything. + if (!d) + return; + + maxdepth = source->maxdepth; + dcmaxdepth = sdc->maxdepth; + meandepth = source->meandepth; + duration = source->duration; + + copy_samples(sdc, &dc); + copy_events(sdc, &dc); + + setText(editProfileTypeToString(type, count) + diveNumberOrDate(d)); +} + +EditProfile::~EditProfile() +{ + free_dive_dcs(&dc); +} + +bool EditProfile::workToBeDone() +{ + return !!d; +} + +void EditProfile::undo() +{ + struct divecomputer *sdc = get_dive_dc(d, dcNr); + if (!sdc) + return; + std::swap(sdc->samples, dc.samples); + std::swap(sdc->alloc_samples, dc.alloc_samples); + std::swap(sdc->sample, dc.sample); + std::swap(sdc->maxdepth, dc.maxdepth); + std::swap(d->maxdepth, maxdepth); + std::swap(d->meandepth, meandepth); + std::swap(d->duration, duration); + fixup_dive(d); + invalidate_dive_cache(d); // Ensure that dive is written in git_save() + + QVector divesToNotify = { d }; + emit diveListNotifier.divesChanged(divesToNotify, DiveField::DURATION | DiveField::DEPTH); +} + +// Redo and undo do the same +void EditProfile::redo() +{ + undo(); +} + // ***** Add Weight ***** AddWeight::AddWeight(bool currentDiveOnly) : EditDivesBase(currentDiveOnly) diff --git a/commands/command_edit.h b/commands/command_edit.h index 0772f8d56..d2a2cb7db 100644 --- a/commands/command_edit.h +++ b/commands/command_edit.h @@ -334,8 +334,7 @@ class ReplanDive : public Base { int salinity; public: // Dive computer(s) and cylinders(s) of the source dive will be reset! - // If edit_profile is true, the text will be changed from "replan dive" to "edit profile". - ReplanDive(dive *source, bool edit_profile); + ReplanDive(dive *source); ~ReplanDive(); private: void undo() override; @@ -343,6 +342,23 @@ private: bool workToBeDone() override; }; +class EditProfile : public Base { + dive *d; + int dcNr; + + depth_t maxdepth, meandepth, dcmaxdepth; + duration_t duration; + struct divecomputer dc; +public: + // Note: source must be clean (i.e. fixup_dive must have been called on it). + EditProfile(const dive *source, EditProfileType type, int count); + ~EditProfile(); +private: + void undo() override; + void redo() override; + bool workToBeDone() override; +}; + class AddWeight : public EditDivesBase { public: AddWeight(bool currentDiveOnly); diff --git a/desktop-widgets/tab-widgets/maintab.cpp b/desktop-widgets/tab-widgets/maintab.cpp index fe3c93eb0..bf9deae26 100644 --- a/desktop-widgets/tab-widgets/maintab.cpp +++ b/desktop-widgets/tab-widgets/maintab.cpp @@ -498,7 +498,7 @@ void MainTab::acceptChanges() MainWindow::instance()->showProfile(); DivePlannerPointsModel::instance()->setPlanMode(DivePlannerPointsModel::NOTHING); - Command::editProfile(&displayed_dive); + Command::editProfile(&displayed_dive, Command::EditProfileType::MOVE, 0); int scrolledBy = MainWindow::instance()->diveList->verticalScrollBar()->sliderPosition(); MainWindow::instance()->diveList->reload();