summaryrefslogtreecommitdiffstats
path: root/profile-widget/profilewidget2.cpp
diff options
context:
space:
mode:
authorGravatar Berthold Stoeger <bstoeger@mail.tuwien.ac.at>2020-04-14 22:07:00 +0200
committerGravatar Dirk Hohndel <dirk@hohndel.org>2020-05-06 13:58:09 -0700
commite61641c79cd57bfa55d2371615a7eef7c73b4eb7 (patch)
tree85333dfed1630b1d968498495d1d1c151570e015 /profile-widget/profilewidget2.cpp
parentebdb3e3c3029d3762207e8dcadfa3a61bf0a9293 (diff)
downloadsubsurface-e61641c79cd57bfa55d2371615a7eef7c73b4eb7.tar.gz
undo: implement undo of setting a picture time by drag&drop
Even though the functionality is seemingly trivial, this is a bit invasive, as the code has to be split into two distinct parts: 1) Post undo command 2) React to changes to the divelist Don't compile that code on mobile. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Diffstat (limited to 'profile-widget/profilewidget2.cpp')
-rw-r--r--profile-widget/profilewidget2.cpp145
1 files changed, 71 insertions, 74 deletions
diff --git a/profile-widget/profilewidget2.cpp b/profile-widget/profilewidget2.cpp
index 71db3d66f..cea5a50f0 100644
--- a/profile-widget/profilewidget2.cpp
+++ b/profile-widget/profilewidget2.cpp
@@ -19,7 +19,7 @@
#include "core/pref.h"
#include "qt-models/diveplannermodel.h"
#include "qt-models/models.h"
-#include "qt-models/divepicturemodel.h"
+#include "qt-models/divepicturemodel.h" // TODO: remove once divepictures have been undo-ified
#include "core/divelist.h"
#include "core/errorhelper.h"
#ifndef SUBSURFACE_MOBILE
@@ -174,6 +174,7 @@ ProfileWidget2::ProfileWidget2(QWidget *parent) : QGraphicsView(parent),
connect(DivePictureModel::instance(), &DivePictureModel::modelReset, this, &ProfileWidget2::plotPictures);
connect(&diveListNotifier, &DiveListNotifier::cylinderEdited, this, &ProfileWidget2::profileChanged);
connect(&diveListNotifier, &DiveListNotifier::eventsChanged, this, &ProfileWidget2::profileChanged);
+ connect(&diveListNotifier, &DiveListNotifier::pictureOffsetChanged, this, &ProfileWidget2::pictureOffsetChanged);
#endif // SUBSURFACE_MOBILE
#if !defined(QT_NO_DEBUG) && defined(SHOW_PLOT_INFO_TABLE)
@@ -2175,86 +2176,16 @@ void ProfileWidget2::profileChanged(dive *d)
void ProfileWidget2::dropEvent(QDropEvent *event)
{
+#ifndef SUBSURFACE_MOBILE
if (event->mimeData()->hasFormat("application/x-subsurfaceimagedrop")) {
QByteArray itemData = event->mimeData()->data("application/x-subsurfaceimagedrop");
QDataStream dataStream(&itemData, QIODevice::ReadOnly);
QString filename;
- int diveId;
- dataStream >> filename >> diveId;
-
- // If the id of the drag & dropped picture belongs to a different dive, then
- // the offset we determine makes no sense what so ever. Simply ignore such an event.
- // In the future, we might think about duplicating the picture or moving the picture
- // from one dive to the other.
- if (!current_dive || displayed_dive.id != diveId) {
- event->ignore();
- return;
- }
-
-#ifndef SUBSURFACE_MOBILE
- // Calculate time in dive where picture was dropped and whether the new position is during the dive.
+ dataStream >> filename;
QPointF mappedPos = mapToScene(event->pos());
offset_t offset { (int32_t)lrint(timeAxis->valueAt(mappedPos)) };
- bool duringDive = current_dive && offset.seconds > 0 && offset.seconds < current_dive->duration.seconds;
-
- // A picture was drag&dropped onto the profile: We have four cases to consider:
- // 1a) The image was already shown on the profile and is moved to a different position on the profile.
- // Calculate the new position and move the picture.
- // 1b) The image was on the profile and is moved outside of the dive time.
- // Remove the picture.
- // 2a) The image was not on the profile and is moved into the dive time.
- // Add the picture to the profile.
- // 2b) The image was not on the profile and is moved outside of the dive time.
- // Do nothing.
- auto oldPos = std::find_if(pictures.begin(), pictures.end(), [filename](const PictureEntry &e)
- { return e.filename == filename; });
- if (oldPos != pictures.end()) {
- // Cases 1a) and 1b): picture is on profile
- if (duringDive) {
- // Case 1a): move to new position
- // First, find new position. Note that we also have to compare filenames,
- // because it is quite easy to generate equal offsets.
- auto newPos = std::find_if(pictures.begin(), pictures.end(), [offset, &filename](const PictureEntry &e)
- { return std::tie(e.offset.seconds, e.filename) > std::tie(offset.seconds, filename); });
- // Set new offset
- oldPos->offset.seconds = offset.seconds;
- updateThumbnailXPos(*oldPos);
-
- // Move image from old to new position
- int oldIndex = oldPos - pictures.begin();
- int newIndex = newPos - pictures.begin();
- moveInVector(pictures, oldIndex, oldIndex + 1, newIndex);
- } else {
- // Case 1b): remove picture
- pictures.erase(oldPos);
- }
-
- // In both cases the picture list changed, therefore we must recalculate the y-coordinatesA.
- calculatePictureYPositions();
- } else {
- // Cases 2a) and 2b): picture not on profile. We only have to take action for
- // the first case: picture is moved into dive-time.
- if (duringDive) {
- // Case 2a): add the picture at the appropriate position.
- // The case move from outside-to-outside of the profile plot was handled by
- // the "&& duringDive" condition in the if above.
- // As for case 1a), we have to also consider filenames in the case of equal offsets.
- auto newPos = std::find_if(pictures.begin(), pictures.end(), [offset, &filename](const PictureEntry &e)
- { return std::tie(e.offset.seconds, e.filename) > std::tie(offset.seconds, filename); });
- // emplace() constructs the element at the given position in the vector.
- // The parameters are passed directly to the contructor.
- // The call returns an iterator to the new element (which might differ from
- // the old iterator, since the buffer might have been reallocated).
- newPos = pictures.emplace(newPos, offset, filename, scene(), false);
- updateThumbnailXPos(*newPos);
- calculatePictureYPositions();
- }
- }
-
- // Only signal the drag&drop action if the picture actually belongs to the dive.
- DivePictureModel::instance()->updateDivePictureOffset(displayed_dive.id, filename, offset.seconds);
-#endif
+ Command::setPictureOffset(current_dive, filename, offset);
if (event->source() == this) {
event->setDropAction(Qt::MoveAction);
@@ -2265,7 +2196,73 @@ void ProfileWidget2::dropEvent(QDropEvent *event)
} else {
event->ignore();
}
+#endif
+}
+
+#ifndef SUBSURFACE_MOBILE
+void ProfileWidget2::pictureOffsetChanged(dive *d, QString filename, offset_t offset)
+{
+ if (d->id != displayed_dive.id)
+ return; // Picture of a different dive than the one shown changed.
+
+ // Calculate time in dive where picture was dropped and whether the new position is during the dive.
+ bool duringDive = current_dive && offset.seconds > 0 && offset.seconds < current_dive->duration.seconds;
+
+ // A picture was drag&dropped onto the profile: We have four cases to consider:
+ // 1a) The image was already shown on the profile and is moved to a different position on the profile.
+ // Calculate the new position and move the picture.
+ // 1b) The image was on the profile and is moved outside of the dive time.
+ // Remove the picture.
+ // 2a) The image was not on the profile and is moved into the dive time.
+ // Add the picture to the profile.
+ // 2b) The image was not on the profile and is moved outside of the dive time.
+ // Do nothing.
+ auto oldPos = std::find_if(pictures.begin(), pictures.end(), [filename](const PictureEntry &e)
+ { return e.filename == filename; });
+ if (oldPos != pictures.end()) {
+ // Cases 1a) and 1b): picture is on profile
+ if (duringDive) {
+ // Case 1a): move to new position
+ // First, find new position. Note that we also have to compare filenames,
+ // because it is quite easy to generate equal offsets.
+ auto newPos = std::find_if(pictures.begin(), pictures.end(), [offset, &filename](const PictureEntry &e)
+ { return std::tie(e.offset.seconds, e.filename) > std::tie(offset.seconds, filename); });
+ // Set new offset
+ oldPos->offset.seconds = offset.seconds;
+ updateThumbnailXPos(*oldPos);
+
+ // Move image from old to new position
+ int oldIndex = oldPos - pictures.begin();
+ int newIndex = newPos - pictures.begin();
+ moveInVector(pictures, oldIndex, oldIndex + 1, newIndex);
+ } else {
+ // Case 1b): remove picture
+ pictures.erase(oldPos);
+ }
+
+ // In both cases the picture list changed, therefore we must recalculate the y-coordinatesA.
+ calculatePictureYPositions();
+ } else {
+ // Cases 2a) and 2b): picture not on profile. We only have to take action for
+ // the first case: picture is moved into dive-time.
+ if (duringDive) {
+ // Case 2a): add the picture at the appropriate position.
+ // The case move from outside-to-outside of the profile plot was handled by
+ // the "&& duringDive" condition in the if above.
+ // As for case 1a), we have to also consider filenames in the case of equal offsets.
+ auto newPos = std::find_if(pictures.begin(), pictures.end(), [offset, &filename](const PictureEntry &e)
+ { return std::tie(e.offset.seconds, e.filename) > std::tie(offset.seconds, filename); });
+ // emplace() constructs the element at the given position in the vector.
+ // The parameters are passed directly to the contructor.
+ // The call returns an iterator to the new element (which might differ from
+ // the old iterator, since the buffer might have been reallocated).
+ newPos = pictures.emplace(newPos, offset, filename, scene(), false);
+ updateThumbnailXPos(*newPos);
+ calculatePictureYPositions();
+ }
+ }
}
+#endif
void ProfileWidget2::dragEnterEvent(QDragEnterEvent *event)
{