summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/dive.c43
-rw-r--r--core/dive.h2
-rw-r--r--desktop-widgets/command.cpp5
-rw-r--r--desktop-widgets/command.h1
-rw-r--r--desktop-widgets/command_divelist.cpp52
-rw-r--r--desktop-widgets/command_divelist.h17
-rw-r--r--profile-widget/profilewidget2.cpp9
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 = &current_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()