diff options
-rw-r--r-- | core/dive.c | 43 | ||||
-rw-r--r-- | core/dive.h | 2 | ||||
-rw-r--r-- | desktop-widgets/command.cpp | 5 | ||||
-rw-r--r-- | desktop-widgets/command.h | 1 | ||||
-rw-r--r-- | desktop-widgets/command_divelist.cpp | 52 | ||||
-rw-r--r-- | desktop-widgets/command_divelist.h | 17 | ||||
-rw-r--r-- | profile-widget/profilewidget2.cpp | 9 |
7 files changed, 106 insertions, 23 deletions
diff --git a/core/dive.c b/core/dive.c index ed0c5a757..e6b27e0bb 100644 --- a/core/dive.c +++ b/core/dive.c @@ -4151,27 +4151,42 @@ bool dive_remove_picture(struct dive *d, const char *filename) return false; } -/* this always acts on the current divecomputer of the current dive */ -void make_first_dc() +/* clones a dive and moves given dive computer to front */ +struct dive *make_first_dc(const struct dive *d, int dc_number) { - struct divecomputer *dc = ¤t_dive->dc; - struct divecomputer *newdc = malloc(sizeof(*newdc)); - struct divecomputer *cur_dc = current_dc; /* needs to be in a local variable so the macro isn't re-executed */ + struct dive *res; + struct divecomputer *dc, *newdc, *old_dc; + + /* copy the dive */ + res = alloc_dive(); + copy_dive(d, res); + + /* make a new unique id, since we still can't handle two equal ids */ + res->id = dive_getUniqID(); + invalidate_dive_cache(res); + + if (dc_number == 0) + return res; + + dc = &res->dc; + newdc = malloc(sizeof(*newdc)); + old_dc = get_dive_dc(res, dc_number); /* skip the current DC in the linked list */ - while (dc && dc->next != cur_dc) - dc = dc->next; + for (dc = &res->dc; dc && dc->next != old_dc; dc = dc->next) + ; if (!dc) { free(newdc); fprintf(stderr, "data inconsistent: can't find the current DC"); - return; + return res; } - dc->next = cur_dc->next; - *newdc = current_dive->dc; - current_dive->dc = *cur_dc; - current_dive->dc.next = newdc; - free(cur_dc); - invalidate_dive_cache(current_dive); + dc->next = old_dc->next; + *newdc = res->dc; + res->dc = *old_dc; + res->dc.next = newdc; + free(old_dc); + + return res; } /* always acts on the current dive */ diff --git a/core/dive.h b/core/dive.h index 7aea050b6..ebc127bd7 100644 --- a/core/dive.h +++ b/core/dive.h @@ -434,7 +434,7 @@ extern unsigned int number_of_computers(const struct dive *dive); extern struct divecomputer *get_dive_dc(struct dive *dive, int nr); extern timestamp_t dive_endtime(const struct dive *dive); -extern void make_first_dc(void); +extern struct dive *make_first_dc(const struct dive *d, int dc_number); extern unsigned int count_divecomputers(void); extern void delete_current_divecomputer(void); void split_divecomputer(const struct dive *src, int num, struct dive **out1, struct dive **out2); diff --git a/desktop-widgets/command.cpp b/desktop-widgets/command.cpp index e5244e92a..b6283ec8d 100644 --- a/desktop-widgets/command.cpp +++ b/desktop-widgets/command.cpp @@ -74,6 +74,11 @@ void splitDiveComputer(dive *d, int dc_num) execute(new SplitDiveComputer(d, dc_num)); } +void moveDiveComputerToFront(dive *d, int dc_num) +{ + execute(new MoveDiveComputerToFront(d, dc_num)); +} + void mergeDives(const QVector <dive *> &dives) { execute(new MergeDives(dives)); diff --git a/desktop-widgets/command.h b/desktop-widgets/command.h index 2686255ee..543e3bcae 100644 --- a/desktop-widgets/command.h +++ b/desktop-widgets/command.h @@ -36,6 +36,7 @@ void autogroupDives(); void mergeTrips(dive_trip *trip1, dive_trip *trip2); void splitDives(dive *d, duration_t time); void splitDiveComputer(dive *d, int dc_num); +void moveDiveComputerToFront(dive *d, int dc_num); void mergeDives(const QVector <dive *> &dives); // 3) Dive-site related commands diff --git a/desktop-widgets/command_divelist.cpp b/desktop-widgets/command_divelist.cpp index c49159f5a..4c4a7e7d3 100644 --- a/desktop-widgets/command_divelist.cpp +++ b/desktop-widgets/command_divelist.cpp @@ -9,6 +9,7 @@ #include "core/qthelper.h" #include "core/subsurface-qt/DiveListNotifier.h" #include "qt-models/filtermodels.h" +#include "../profile-widget/profilewidget2.h" #include <array> @@ -802,6 +803,57 @@ SplitDiveComputer::SplitDiveComputer(dive *d, int dc_num) : SplitDivesBase(d, sp setText(tr("split dive computer")); } +MoveDiveComputerToFront::MoveDiveComputerToFront(dive *d, int dc_num) +{ + setText(tr("move dive computer to front")); + + dive *new_dive = make_first_dc(d, dc_num); + if (!new_dive) + return; + + diveToRemove.dives.push_back(d); + + // Currently, the core code selects the dive -> this is not what we want, as + // we manually manage the selection post-command. + // TODO: Reset selection in core. + new_dive->selected = false; + + // Reset references to trip and site in the new dive, as the undo command + // will add the dive to the trip and site. + new_dive->divetrip = nullptr; + new_dive->dive_site = nullptr; + + diveToAdd.dives.resize(1); + diveToAdd.dives[0].dive.reset(new_dive); + diveToAdd.dives[0].trip = d->divetrip; + diveToAdd.dives[0].site = d->dive_site; +} + +bool MoveDiveComputerToFront::workToBeDone() +{ + return !diveToRemove.dives.empty() || !diveToAdd.dives.empty(); +} + +void MoveDiveComputerToFront::redoit() +{ + DivesAndSitesToRemove addedDive = addDives(diveToAdd); + diveToAdd = removeDives(diveToRemove); + diveToRemove = std::move(addedDive); + + // Select added dive and make it current + restoreSelection(diveToRemove.dives, diveToRemove.dives[0]); + + // Update the profile to show the first dive computer + dc_number = 0; + MainWindow::instance()->graphics->replot(current_dive); +} + +void MoveDiveComputerToFront::undoit() +{ + // Undo and redo do the same + redoit(); +} + MergeDives::MergeDives(const QVector <dive *> &dives) { setText(tr("merge dive")); diff --git a/desktop-widgets/command_divelist.h b/desktop-widgets/command_divelist.h index 2d3ee8db1..d46697454 100644 --- a/desktop-widgets/command_divelist.h +++ b/desktop-widgets/command_divelist.h @@ -236,6 +236,23 @@ public: SplitDiveComputer(dive *d, int dc_num); }; +// When moving the dive computer to the front, we go the ineffective, +// but easy way: We keep two full copies of the dive (before and after). +// Removing and readding assures that the dive stays at the correct +// position in the list (the dive computer list is used for sorting dives). +class MoveDiveComputerToFront : public DiveListBase { +public: + MoveDiveComputerToFront(dive *d, int dc_num); +private: + void undoit() override; + void redoit() override; + bool workToBeDone() override; + + // For redo and undo + DivesAndTripsToAdd diveToAdd; + DivesAndSitesToRemove diveToRemove; +}; + class MergeDives : public DiveListBase { public: MergeDives(const QVector<dive *> &dives); diff --git a/profile-widget/profilewidget2.cpp b/profile-widget/profilewidget2.cpp index f9655127e..46a1eb1a0 100644 --- a/profile-widget/profilewidget2.cpp +++ b/profile-widget/profilewidget2.cpp @@ -1590,14 +1590,7 @@ void ProfileWidget2::splitCurrentDC() void ProfileWidget2::makeFirstDC() { - make_first_dc(); - mark_divelist_changed(true); - // this is now the first DC, so we need to redraw the profile and refresh the dive list - // (and no, it's not just enough to rewrite the text - the first DC is special so values in the - // dive list may change). - // As a side benefit, this returns focus to the dive list. - dc_number = 0; - emit refreshDisplay(true); + Command::moveDiveComputerToFront(current_dive, dc_number); } void ProfileWidget2::hideEvents() |