diff --git a/src/Insight/CMakeLists.txt b/src/Insight/CMakeLists.txt index bc38d4ae..d27e6ca2 100755 --- a/src/Insight/CMakeLists.txt +++ b/src/Insight/CMakeLists.txt @@ -41,6 +41,7 @@ target_sources( # Task indicator ${CMAKE_CURRENT_SOURCE_DIR}/UserInterfaces/InsightWindow/Widgets/TaskIndicator/TaskIndicator.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/UserInterfaces/InsightWindow/Widgets/TaskProgressIndicator/TaskProgressIndicator.cpp # Error dialogue window ${CMAKE_CURRENT_SOURCE_DIR}/UserInterfaces/InsightWindow/Widgets/ErrorDialogue/ErrorDialogue.cpp diff --git a/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/SnapshotManager/SnapshotManager.cpp b/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/SnapshotManager/SnapshotManager.cpp index 1caf0ca9..7473e07b 100644 --- a/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/SnapshotManager/SnapshotManager.cpp +++ b/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/SnapshotManager/SnapshotManager.cpp @@ -6,7 +6,6 @@ #include "src/Insight/UserInterfaces/InsightWindow/Widgets/ErrorDialogue/ErrorDialogue.hpp" #include "src/Insight/InsightWorker/Tasks/RetrieveMemorySnapshots.hpp" -#include "src/Insight/InsightWorker/Tasks/CaptureMemorySnapshot.hpp" #include "src/Insight/InsightWorker/InsightWorker.hpp" #include "src/Services/PathService.hpp" @@ -161,6 +160,8 @@ namespace Bloom::Widgets } ); + emit this->captureTaskCreated(captureTask); + InsightWorker::queueTask(captureTask); } diff --git a/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/SnapshotManager/SnapshotManager.hpp b/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/SnapshotManager/SnapshotManager.hpp index b006dfc9..9980d620 100644 --- a/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/SnapshotManager/SnapshotManager.hpp +++ b/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/SnapshotManager/SnapshotManager.hpp @@ -14,6 +14,8 @@ #include "src/Targets/TargetMemory.hpp" #include "src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/MemorySnapshot.hpp" +#include "src/Insight/InsightWorker/Tasks/CaptureMemorySnapshot.hpp" + #include "./CreateSnapshotWindow/CreateSnapshotWindow.hpp" #include "MemorySnapshotItem.hpp" @@ -35,6 +37,9 @@ namespace Bloom::Widgets PanelWidget* parent = nullptr ); + signals: + void captureTaskCreated(const QSharedPointer& task); + protected: void resizeEvent(QResizeEvent* event) override; void showEvent(QShowEvent* event) override; diff --git a/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/TargetMemoryInspectionPane.cpp b/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/TargetMemoryInspectionPane.cpp index 18cd123c..fb08a0fa 100644 --- a/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/TargetMemoryInspectionPane.cpp +++ b/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/TargetMemoryInspectionPane.cpp @@ -69,16 +69,13 @@ namespace Bloom::Widgets this->container->setStyleSheet(stylesheetFile.readAll()); this->container->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); + this->subContainerLayout = this->container->findChild("container-sub-layout"); + this->titleBar = this->container->findChild("title-bar"); - this->titleBar->layout()->setContentsMargins(7, 0, 7, 0); - auto* titleLabel = this->titleBar->findChild("title"); - titleLabel->setText(memoryName); + this->bottomBar = this->container->findChild("bottom-bar"); + this->bottomBarLayout = this->bottomBar->findChild(); - // Quick sanity check to ensure the validity of persisted settings. - this->sanitiseSettings(); - - this->subContainerLayout = this->container->findChild("container-sub-layout"); this->manageMemoryRegionsButton = this->container->findChild("manage-memory-regions-btn"); this->manageMemorySnapshotsButton = this->container->findChild("manage-memory-snapshots-btn"); @@ -91,10 +88,17 @@ namespace Bloom::Widgets this->manageMemorySnapshotsButton->layout()->setContentsMargins(0, 0, 0, 0); + this->staleDataLabelContainer = this->container->findChild("stale-data-label"); + + this->titleBar->layout()->setContentsMargins(7, 0, 7, 0); + auto* titleLabel = this->titleBar->findChild("title"); + titleLabel->setText(memoryName); + auto* memoryCapacityLabel = this->container->findChild("memory-capacity-label"); memoryCapacityLabel->setText(QLocale(QLocale::English).toString(this->targetMemoryDescriptor.size()) + " Bytes"); - this->staleDataLabelContainer = this->container->findChild("stale-data-label"); + // Quick sanity check to ensure the validity of persisted settings. + this->sanitiseSettings(); this->hexViewerWidget = new HexViewerWidget( this->targetMemoryDescriptor, @@ -128,6 +132,9 @@ namespace Bloom::Widgets this->setRefreshOnTargetStopEnabled(this->settings.refreshOnTargetStop); this->setRefreshOnActivationEnabled(this->settings.refreshOnActivation); + this->bottomBarHorizontalSpacer = new QSpacerItem(1, 1, QSizePolicy::Expanding, QSizePolicy::Expanding); + this->bottomBarLayout->insertItem(5, this->bottomBarHorizontalSpacer); + QObject::connect( this, &PaneWidget::paneActivated, @@ -188,6 +195,13 @@ namespace Bloom::Widgets } ); + QObject::connect( + this->snapshotManager, + &SnapshotManager::captureTaskCreated, + this, + &TargetMemoryInspectionPane::onCaptureMemoryTaskCreated + ); + QObject::connect( this->refreshButton, &QToolButton::clicked, @@ -397,6 +411,7 @@ namespace Bloom::Widgets ); } + this->setTaskProgressIndicator(readMemoryTask); InsightWorker::queueTask(readMemoryTask); } @@ -612,6 +627,36 @@ namespace Bloom::Widgets } } + void TargetMemoryInspectionPane::onCaptureMemoryTaskCreated(const QSharedPointer& task) { + this->setTaskProgressIndicator(task); + } + + void TargetMemoryInspectionPane::setTaskProgressIndicator(const QSharedPointer& task) { + if (this->taskProgressIndicator != nullptr) { + this->bottomBarLayout->removeWidget(this->taskProgressIndicator); + this->taskProgressIndicator->deleteLater(); + this->taskProgressIndicator = nullptr; + } + + this->taskProgressIndicator = new TaskProgressIndicator(task, this); + + QObject::connect( + this->taskProgressIndicator, + &TaskProgressIndicator::taskComplete, + this, + [this] { + this->bottomBarLayout->removeWidget(this->taskProgressIndicator); + this->taskProgressIndicator->deleteLater(); + this->taskProgressIndicator = nullptr; + + this->bottomBarLayout->insertItem(5, this->bottomBarHorizontalSpacer); + } + ); + + this->bottomBarLayout->removeItem(this->bottomBarHorizontalSpacer); + this->bottomBarLayout->insertWidget(5, this->taskProgressIndicator); + } + void TargetMemoryInspectionPane::setStaleData(bool staleData) { this->staleData = staleData; this->staleDataLabelContainer->setVisible(this->staleData); diff --git a/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/TargetMemoryInspectionPane.hpp b/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/TargetMemoryInspectionPane.hpp index 35aa1308..47fdb70e 100644 --- a/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/TargetMemoryInspectionPane.hpp +++ b/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/TargetMemoryInspectionPane.hpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include "src/Insight/UserInterfaces/InsightWindow/Widgets/PaneWidget.hpp" @@ -16,6 +17,9 @@ #include "src/Insight/UserInterfaces/InsightWindow/Widgets/PanelWidget.hpp" #include "src/Insight/UserInterfaces/InsightWindow/Widgets/SvgToolButton.hpp" #include "src/Insight/UserInterfaces/InsightWindow/Widgets/Label.hpp" +#include "src/Insight/UserInterfaces/InsightWindow/Widgets/TaskProgressIndicator/TaskProgressIndicator.hpp" + +#include "src/Insight/InsightWorker/Tasks/CaptureMemorySnapshot.hpp" #include "HexViewerWidget/HexViewerWidget.hpp" #include "MemoryRegionManager/MemoryRegionManagerWindow.hpp" @@ -59,6 +63,9 @@ namespace Bloom::Widgets QHBoxLayout* subContainerLayout = nullptr; QWidget* titleBar = nullptr; + QWidget* bottomBar = nullptr; + QHBoxLayout* bottomBarLayout = nullptr; + SvgToolButton* manageMemoryRegionsButton = nullptr; QToolButton* manageMemorySnapshotsButton = nullptr; @@ -73,6 +80,8 @@ namespace Bloom::Widgets PanelWidget* rightPanel = nullptr; SnapshotManager* snapshotManager = nullptr; + TaskProgressIndicator* taskProgressIndicator = nullptr; + QSpacerItem* bottomBarHorizontalSpacer = nullptr; QWidget* staleDataLabelContainer = nullptr; Targets::TargetState targetState = Targets::TargetState::UNKNOWN; @@ -96,6 +105,8 @@ namespace Bloom::Widgets Bloom::Targets::TargetMemoryType memoryType, Targets::TargetMemoryAddressRange addressRange ); + void onCaptureMemoryTaskCreated(const QSharedPointer& task); + void setTaskProgressIndicator(const QSharedPointer& task); void setStaleData(bool staleData); }; } diff --git a/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/UiFiles/TargetMemoryInspectionPane.ui b/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/UiFiles/TargetMemoryInspectionPane.ui index 931e7786..2f96bc7b 100644 --- a/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/UiFiles/TargetMemoryInspectionPane.ui +++ b/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/UiFiles/TargetMemoryInspectionPane.ui @@ -366,6 +366,9 @@ Memory Capacity + + + @@ -385,8 +388,25 @@ - - Qt::Horizontal + + + 5 + + + + QSizePolicy::Fixed + + + + + + + + 15 + + + + QSizePolicy::Fixed @@ -395,6 +415,9 @@ false + + + 1 diff --git a/src/Insight/UserInterfaces/InsightWindow/Widgets/TaskProgressIndicator/TaskProgressIndicator.cpp b/src/Insight/UserInterfaces/InsightWindow/Widgets/TaskProgressIndicator/TaskProgressIndicator.cpp new file mode 100644 index 00000000..4e0e95b3 --- /dev/null +++ b/src/Insight/UserInterfaces/InsightWindow/Widgets/TaskProgressIndicator/TaskProgressIndicator.cpp @@ -0,0 +1,111 @@ +#include "TaskProgressIndicator.hpp" + +#include +#include +#include +#include + +namespace Bloom::Widgets +{ + TaskProgressIndicator::TaskProgressIndicator( + const QSharedPointer& task, + QWidget* parent + ) + : QWidget(parent) + , task(task) + { + this->setObjectName("task-progress-indicator"); + this->setFixedHeight(26); + this->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed); + + QObject::connect( + this->task.get(), + &InsightWorkerTask::progressUpdate, + this, + &TaskProgressIndicator::onTaskProgressUpdate + ); + + QObject::connect( + this->task.get(), + &InsightWorkerTask::failed, + this, + &TaskProgressIndicator::onTaskFailed + ); + + QObject::connect( + this->task.get(), + &InsightWorkerTask::finished, + this, + &TaskProgressIndicator::onTaskFinished + ); + } + + void TaskProgressIndicator::paintEvent(QPaintEvent* event) { + auto painter = QPainter(this); + + const auto size = this->size(); + + static constexpr auto backgroundBarColor = QColor(0x8E, 0x8B, 0x83, 40); + static constexpr auto barColor = QColor(0x8E, 0x8B, 0x83, 90); + static constexpr auto fontColor = QColor(0x99, 0x9a, 0x9d); + + static auto font = QFont("'Ubuntu', sans-serif", 9); + painter.setFont(font); + painter.setPen(fontColor); + + static constexpr auto barHeight = 3; + const auto barYPosition = size.height() - barHeight - 3; + + const auto percentage = std::max(this->taskProgressPercentage, 2); + + painter.drawText( + 0, + barYPosition - 5, + this->task->brief() + QString(this->taskFailed ? " - Failed" : (percentage == 100 ? " - Completed" : "")) + ); + + painter.setPen(Qt::PenStyle::NoPen); + painter.setBrush(backgroundBarColor); + + painter.drawRect( + 0, + barYPosition, + size.width(), + barHeight + ); + + painter.setBrush(barColor); + + painter.drawRect( + 0, + barYPosition, + static_cast(static_cast(size.width()) * (static_cast(percentage) / 100)), + barHeight + ); + } + + void TaskProgressIndicator::onTaskProgressUpdate(int taskProgressPercentage) { + this->taskProgressPercentage = taskProgressPercentage; + this->update(); + } + + void TaskProgressIndicator::onTaskFailed() { + this->taskFailed = true; + this->update(); + } + + void TaskProgressIndicator::onTaskFinished() { + this->taskProgressPercentage = 100; + this->update(); + + auto* finishedSignalTimer = new QTimer(); + finishedSignalTimer->setSingleShot(true); + finishedSignalTimer->setInterval(2500); + + QObject::connect(finishedSignalTimer, &QTimer::timeout, this, [this] { + emit this->taskComplete(); + }); + + finishedSignalTimer->start(); + } +} diff --git a/src/Insight/UserInterfaces/InsightWindow/Widgets/TaskProgressIndicator/TaskProgressIndicator.hpp b/src/Insight/UserInterfaces/InsightWindow/Widgets/TaskProgressIndicator/TaskProgressIndicator.hpp new file mode 100644 index 00000000..6dd794f3 --- /dev/null +++ b/src/Insight/UserInterfaces/InsightWindow/Widgets/TaskProgressIndicator/TaskProgressIndicator.hpp @@ -0,0 +1,35 @@ +#pragma once + +#include +#include +#include +#include +#include + +#include "src/Insight/InsightWorker/Tasks/InsightWorkerTask.hpp" + +namespace Bloom::Widgets +{ + class TaskProgressIndicator: public QWidget + { + Q_OBJECT + + public: + TaskProgressIndicator(const QSharedPointer& task, QWidget* parent); + + signals: + void taskComplete(); + + protected: + void paintEvent(QPaintEvent* event) override; + + private: + QSharedPointer task; + int taskProgressPercentage = 0; + bool taskFailed = false; + + void onTaskProgressUpdate(int progressPercentage); + void onTaskFailed(); + void onTaskFinished(); + }; +}