summaryrefslogtreecommitdiffstats
path: root/commands
diff options
context:
space:
mode:
Diffstat (limited to 'commands')
-rw-r--r--commands/command.cpp5
-rw-r--r--commands/command.h10
-rw-r--r--commands/command_pictures.cpp106
-rw-r--r--commands/command_pictures.h13
4 files changed, 134 insertions, 0 deletions
diff --git a/commands/command.cpp b/commands/command.cpp
index 8195fbd22..d67009978 100644
--- a/commands/command.cpp
+++ b/commands/command.cpp
@@ -367,4 +367,9 @@ void setPictureOffset(dive *d, const QString &filename, offset_t offset)
execute(new SetPictureOffset(d, filename, offset));
}
+void removePictures(const std::vector<PictureListForDeletion> &pictures)
+{
+ execute(new RemovePictures(pictures));
+}
+
} // namespace Command
diff --git a/commands/command.h b/commands/command.h
index 5d92eec03..e4c3b05d2 100644
--- a/commands/command.h
+++ b/commands/command.h
@@ -3,6 +3,7 @@
#define COMMAND_H
#include "core/dive.h"
+#include "core/pictureobj.h"
#include <QVector>
#include <QAction>
#include <vector>
@@ -120,7 +121,16 @@ void addGasSwitch(struct dive *d, int dcNr, int seconds, int tank);
// 7) Picture (media) commands
+struct PictureListForDeletion {
+ dive *d;
+ std::vector<std::string> filenames;
+};
+struct PictureListForAddition {
+ dive *d;
+ std::vector<PictureObj> pics;
+};
void setPictureOffset(dive *d, const QString &filename, offset_t offset);
+void removePictures(const std::vector<PictureListForDeletion> &pictures);
} // namespace Command
diff --git a/commands/command_pictures.cpp b/commands/command_pictures.cpp
index b7f03b193..2e40c0362 100644
--- a/commands/command_pictures.cpp
+++ b/commands/command_pictures.cpp
@@ -47,4 +47,110 @@ bool SetPictureOffset::workToBeDone()
return !!d;
}
+// Filter out pictures that don't exist and sort them according to the backend
+static PictureListForDeletion filterPictureListForDeletion(const PictureListForDeletion &p)
+{
+ PictureListForDeletion res;
+ res.d = p.d;
+ res.filenames.reserve(p.filenames.size());
+ for (int i = 0; i < p.d->pictures.nr; ++i) {
+ std::string fn = p.d->pictures.pictures[i].filename;
+ if (std::find(p.filenames.begin(), p.filenames.end(), fn) != p.filenames.end())
+ res.filenames.push_back(fn);
+ }
+ return res;
+}
+
+// Helper function to remove pictures. Clears the passed-in vector.
+static std::vector<PictureListForAddition> removePictures(std::vector<PictureListForDeletion> &picturesToRemove)
+{
+ std::vector<PictureListForAddition> res;
+ for (const PictureListForDeletion &list: picturesToRemove) {
+ QVector<QString> filenames;
+ PictureListForAddition toAdd;
+ toAdd.d = list.d;
+ for (const std::string &fn: list.filenames) {
+ int idx = get_picture_idx(&list.d->pictures, fn.c_str());
+ if (idx < 0) {
+ fprintf(stderr, "removePictures(): picture disappeared!");
+ continue; // Huh? We made sure that this can't happen by filtering out non-existant pictures.
+ }
+ filenames.push_back(QString::fromStdString(fn));
+ toAdd.pics.emplace_back(list.d->pictures.pictures[idx]);
+ remove_from_picture_table(&list.d->pictures, idx);
+ }
+ if (!toAdd.pics.empty())
+ res.push_back(toAdd);
+ invalidate_dive_cache(list.d);
+ emit diveListNotifier.picturesRemoved(list.d, filenames);
+ }
+ picturesToRemove.clear();
+ return res;
+}
+
+// Helper function to add pictures. Clears the passed-in vector.
+static std::vector<PictureListForDeletion> addPictures(std::vector<PictureListForAddition> &picturesToAdd)
+{
+ // We play it extra safe here and again filter out those pictures that
+ // are already added to the dive. There should be no way for this to
+ // happen, as we checked that before.
+ std::vector<PictureListForDeletion> res;
+ for (const PictureListForAddition &list: picturesToAdd) {
+ QVector<PictureObj> picsForSignal;
+ PictureListForDeletion toRemove;
+ toRemove.d = list.d;
+ for (const PictureObj &pic: list.pics) {
+ int idx = get_picture_idx(&list.d->pictures, pic.filename.c_str()); // This should *not* already exist!
+ if (idx >= 0) {
+ fprintf(stderr, "addPictures(): picture disappeared!");
+ continue; // Huh? We made sure that this can't happen by filtering out existing pictures.
+ }
+ picsForSignal.push_back(pic);
+ add_picture(&list.d->pictures, pic.toCore());
+ toRemove.filenames.push_back(pic.filename);
+ }
+ if (!toRemove.filenames.empty())
+ res.push_back(toRemove);
+ invalidate_dive_cache(list.d);
+ emit diveListNotifier.picturesAdded(list.d, picsForSignal);
+ }
+ picturesToAdd.clear();
+ return res;
+}
+
+RemovePictures::RemovePictures(const std::vector<PictureListForDeletion> &pictures) : picturesToRemove(pictures)
+{
+ // Filter out the pictures that don't actually exist. In principle this shouldn't be necessary.
+ // Nevertheless, let's play it save. This has the additional benefit of sorting the pictures
+ // according to the backend if, for some reason, the caller passed the pictures in in random order.
+ picturesToRemove.reserve(pictures.size());
+ size_t count = 0;
+ for (const PictureListForDeletion &p: pictures) {
+ PictureListForDeletion filtered = filterPictureListForDeletion(p);
+ if (filtered.filenames.size())
+ picturesToRemove.push_back(p);
+ count += filtered.filenames.size();
+ }
+ if (count == 0) {
+ picturesToRemove.clear(); // This signals that nothing is to be done
+ return;
+ }
+ setText(Command::Base::tr("remove %n pictures(s)", "", count));
+}
+
+bool RemovePictures::workToBeDone()
+{
+ return !picturesToRemove.empty();
+}
+
+void RemovePictures::undo()
+{
+ picturesToRemove = addPictures(picturesToAdd);
+}
+
+void RemovePictures::redo()
+{
+ picturesToAdd = removePictures(picturesToRemove);
+}
+
} // namespace Command
diff --git a/commands/command_pictures.h b/commands/command_pictures.h
index f2381d111..802c63c6c 100644
--- a/commands/command_pictures.h
+++ b/commands/command_pictures.h
@@ -5,6 +5,7 @@
#define COMMAND_PICTURES_H
#include "command_base.h"
+#include "command.h" // for PictureListForDeletion/Addition
// We put everything in a namespace, so that we can shorten names without polluting the global namespace
namespace Command {
@@ -22,5 +23,17 @@ private:
bool workToBeDone() override;
};
+class RemovePictures final : public Base {
+public:
+ RemovePictures(const std::vector<PictureListForDeletion> &pictures);
+private:
+ std::vector<PictureListForDeletion> picturesToRemove; // for redo
+ std::vector<PictureListForAddition> picturesToAdd; // for undo
+
+ void undo() override;
+ void redo() override;
+ bool workToBeDone() override;
+};
+
} // namespace Command
#endif