diff --git a/src/Insight/CMakeLists.txt b/src/Insight/CMakeLists.txt index 0dbf7685..4c361903 100755 --- a/src/Insight/CMakeLists.txt +++ b/src/Insight/CMakeLists.txt @@ -39,6 +39,7 @@ target_sources( ${CMAKE_CURRENT_SOURCE_DIR}/InsightWorker/Tasks/ConstructHexViewerTopLevelGroupItem.cpp ${CMAKE_CURRENT_SOURCE_DIR}/InsightWorker/Tasks/CaptureMemorySnapshot.cpp ${CMAKE_CURRENT_SOURCE_DIR}/InsightWorker/Tasks/RetrieveMemorySnapshots.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/InsightWorker/Tasks/DeleteMemorySnapshot.cpp # Task indicators ${CMAKE_CURRENT_SOURCE_DIR}/UserInterfaces/InsightWindow/Widgets/TaskIndicator/TaskIndicator.cpp diff --git a/src/Insight/InsightWorker/Tasks/DeleteMemorySnapshot.cpp b/src/Insight/InsightWorker/Tasks/DeleteMemorySnapshot.cpp new file mode 100644 index 00000000..753b5c1b --- /dev/null +++ b/src/Insight/InsightWorker/Tasks/DeleteMemorySnapshot.cpp @@ -0,0 +1,42 @@ +#include "DeleteMemorySnapshot.hpp" + +#include + +#include "src/Services/PathService.hpp" +#include "src/Helpers/EnumToStringMappings.hpp" +#include "src/Logger/Logger.hpp" + +namespace Bloom +{ + using Services::TargetControllerService; + + DeleteMemorySnapshot::DeleteMemorySnapshot( + const QString& snapshotId, + Targets::TargetMemoryType memoryType + ) + : snapshotId(snapshotId) + , memoryType(memoryType) + {} + + void DeleteMemorySnapshot::run(TargetControllerService&) { + using Targets::TargetMemorySize; + + Logger::info("Deleting snapshot " + this->snapshotId.toStdString()); + + const auto snapshotFilePath = QString::fromStdString(Services::PathService::projectSettingsDirPath()) + + "/memory_snapshots/" + EnumToStringMappings::targetMemoryTypes.at(this->memoryType) + "/" + + this->snapshotId + ".json"; + + auto snapshotFile = QFile(snapshotFilePath); + + if (!snapshotFile.exists()) { + Logger::warning( + "Could not find snapshot file for " + this->snapshotId.toStdString() + " - expected path: " + + snapshotFilePath.toStdString() + ); + return; + } + + snapshotFile.remove(); + } +} diff --git a/src/Insight/InsightWorker/Tasks/DeleteMemorySnapshot.hpp b/src/Insight/InsightWorker/Tasks/DeleteMemorySnapshot.hpp new file mode 100644 index 00000000..3dd84ef7 --- /dev/null +++ b/src/Insight/InsightWorker/Tasks/DeleteMemorySnapshot.hpp @@ -0,0 +1,29 @@ +#pragma once + +#include + +#include "InsightWorkerTask.hpp" + +#include "src/Targets/TargetMemory.hpp" + +namespace Bloom +{ + class DeleteMemorySnapshot: public InsightWorkerTask + { + Q_OBJECT + + public: + DeleteMemorySnapshot(const QString& snapshotId, Targets::TargetMemoryType memoryType); + + QString brief() const override { + return "Deleting memory snapshot " + this->snapshotId; + } + + protected: + void run(Services::TargetControllerService& targetControllerService) override; + + private: + QString snapshotId; + Targets::TargetMemoryType memoryType; + }; +} diff --git a/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/SnapshotManager/SnapshotManager.cpp b/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/SnapshotManager/SnapshotManager.cpp index de8a6725..dcf60acc 100644 --- a/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/SnapshotManager/SnapshotManager.cpp +++ b/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/SnapshotManager/SnapshotManager.cpp @@ -9,6 +9,7 @@ #include "src/Insight/InsightSignals.hpp" #include "src/Insight/InsightWorker/Tasks/RetrieveMemorySnapshots.hpp" #include "src/Insight/InsightWorker/Tasks/CaptureMemorySnapshot.hpp" +#include "src/Insight/InsightWorker/Tasks/DeleteMemorySnapshot.hpp" #include "src/Insight/InsightWorker/Tasks/WriteTargetMemory.hpp" #include "src/Insight/InsightWorker/InsightWorker.hpp" @@ -131,6 +132,17 @@ namespace Bloom::Widgets } ); + QObject::connect( + this->deleteSnapshotAction, + &QAction::triggered, + this, + [this] { + if (this->contextMenuSnapshotItem != nullptr) { + this->deleteSnapshot(this->contextMenuSnapshotItem->memorySnapshot.id, true); + } + } + ); + QObject::connect( this->restoreSnapshotAction, &QAction::triggered, @@ -263,6 +275,78 @@ namespace Bloom::Widgets snapshotViewer->activateWindow(); } + void SnapshotManager::deleteSnapshot(const QString& snapshotId, bool confirmationPromptEnabled) { + const auto& snapshotIt = this->snapshotsById.find(snapshotId); + assert(snapshotIt != this->snapshotsById.end()); + const auto& snapshot = snapshotIt.value(); + + if (confirmationPromptEnabled) { + auto* confirmationDialog = new ConfirmationDialog( + "Delete snapshot " + snapshot.id, + "This operation will permanently delete the selected snapshot.

Are you sure you want to proceed?", + "Proceed", + std::nullopt, + this + ); + + QObject::connect( + confirmationDialog, + &ConfirmationDialog::confirmed, + this, + [this, snapshotId] { + this->deleteSnapshot(snapshotId, false); + } + ); + + confirmationDialog->show(); + return; + } + + const auto deleteSnapshotTask = QSharedPointer( + new DeleteMemorySnapshot(snapshot.id, snapshot.memoryType), + &QObject::deleteLater + ); + + QObject::connect( + deleteSnapshotTask.get(), + &InsightWorkerTask::completed, + this, + [this, snapshotId] () { + const auto& snapshotViewerIt = this->snapshotViewersById.find(snapshotId); + const auto& snapshotItemIt = this->snapshotItemsById.find(snapshotId); + + if (snapshotItemIt != this->snapshotItemsById.end()) { + auto& snapshotItem = snapshotItemIt.value(); + this->snapshotListScene->removeListItem(snapshotItem); + this->snapshotListScene->refreshGeometry(); + + this->snapshotItemsById.erase(snapshotItemIt); + } + + if (snapshotViewerIt != this->snapshotViewersById.end()) { + auto& snapshotViewer = snapshotViewerIt.value(); + QObject::connect( + snapshotViewer, + &QObject::destroyed, + this, + [this, snapshotId] { + this->snapshotsById.remove(snapshotId); + } + ); + + snapshotViewer->deleteLater(); + this->snapshotViewersById.erase(snapshotViewerIt); + + } else { + this->snapshotsById.remove(snapshotId); + } + } + ); + + emit this->insightWorkerTaskCreated(deleteSnapshotTask); + InsightWorker::queueTask(deleteSnapshotTask); + } + void SnapshotManager::restoreSnapshot(const QString& snapshotId, bool confirmationPromptEnabled) { const auto& snapshotIt = this->snapshotsById.find(snapshotId); assert(snapshotIt != this->snapshotsById.end()); diff --git a/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/SnapshotManager/SnapshotManager.hpp b/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/SnapshotManager/SnapshotManager.hpp index 6e0e21d8..81c5027b 100644 --- a/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/SnapshotManager/SnapshotManager.hpp +++ b/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/SnapshotManager/SnapshotManager.hpp @@ -91,6 +91,7 @@ namespace Bloom::Widgets void addSnapshot(MemorySnapshot&& snapshotTmp); void onSnapshotItemSelected(MemorySnapshotItem* item); void openSnapshotViewer(const QString& snapshotId); + void deleteSnapshot(const QString& snapshotId, bool confirmationPromptEnabled); void restoreSnapshot(const QString& snapshotId, bool confirmationPromptEnabled); void onSnapshotItemDoubleClick(MemorySnapshotItem* item); void onSnapshotItemContextMenu(ListItem* item, QPoint sourcePosition);