Refactored TaskProgressIndicator widget to remain in place and support multiple tasks

This commit is contained in:
Nav
2023-04-11 22:23:48 +01:00
parent fb0a5fef3b
commit 73b31fd22b
4 changed files with 102 additions and 80 deletions

View File

@@ -134,8 +134,8 @@ namespace Bloom::Widgets
this->setRefreshOnTargetStopEnabled(this->settings.refreshOnTargetStop); this->setRefreshOnTargetStopEnabled(this->settings.refreshOnTargetStop);
this->setRefreshOnActivationEnabled(this->settings.refreshOnActivation); this->setRefreshOnActivationEnabled(this->settings.refreshOnActivation);
this->bottomBarHorizontalSpacer = new QSpacerItem(1, 1, QSizePolicy::Expanding, QSizePolicy::Expanding); this->taskProgressIndicator = new TaskProgressIndicator(this);
this->bottomBarLayout->insertItem(5, this->bottomBarHorizontalSpacer); this->bottomBarLayout->insertWidget(5, this->taskProgressIndicator);
QObject::connect( QObject::connect(
this, this,
@@ -370,7 +370,7 @@ namespace Bloom::Widgets
); );
} }
this->setTaskProgressIndicator(readStackPointerTask); this->taskProgressIndicator->addTask(readStackPointerTask);
InsightWorker::queueTask(readStackPointerTask); InsightWorker::queueTask(readStackPointerTask);
} }
} }
@@ -415,7 +415,7 @@ namespace Bloom::Widgets
); );
} }
this->setTaskProgressIndicator(readMemoryTask); this->taskProgressIndicator->addTask(readMemoryTask);
InsightWorker::queueTask(readMemoryTask); InsightWorker::queueTask(readMemoryTask);
} }
@@ -632,33 +632,7 @@ namespace Bloom::Widgets
} }
void TargetMemoryInspectionPane::onSubtaskCreated(const QSharedPointer<InsightWorkerTask>& task) { void TargetMemoryInspectionPane::onSubtaskCreated(const QSharedPointer<InsightWorkerTask>& task) {
this->setTaskProgressIndicator(task); this->taskProgressIndicator->addTask(task);
}
void TargetMemoryInspectionPane::setTaskProgressIndicator(const QSharedPointer<InsightWorkerTask>& 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) { void TargetMemoryInspectionPane::setStaleData(bool staleData) {

View File

@@ -81,7 +81,6 @@ namespace Bloom::Widgets
SnapshotManager* snapshotManager = nullptr; SnapshotManager* snapshotManager = nullptr;
TaskProgressIndicator* taskProgressIndicator = nullptr; TaskProgressIndicator* taskProgressIndicator = nullptr;
QSpacerItem* bottomBarHorizontalSpacer = nullptr;
QWidget* staleDataLabelContainer = nullptr; QWidget* staleDataLabelContainer = nullptr;
Targets::TargetState targetState = Targets::TargetState::UNKNOWN; Targets::TargetState targetState = Targets::TargetState::UNKNOWN;
@@ -106,7 +105,6 @@ namespace Bloom::Widgets
Targets::TargetMemoryAddressRange addressRange Targets::TargetMemoryAddressRange addressRange
); );
void onSubtaskCreated(const QSharedPointer<InsightWorkerTask>& task); void onSubtaskCreated(const QSharedPointer<InsightWorkerTask>& task);
void setTaskProgressIndicator(const QSharedPointer<InsightWorkerTask>& task);
void setStaleData(bool staleData); void setStaleData(bool staleData);
}; };
} }

View File

@@ -3,58 +3,79 @@
#include <QPainter> #include <QPainter>
#include <QColor> #include <QColor>
#include <algorithm> #include <algorithm>
#include <QTimer>
namespace Bloom::Widgets namespace Bloom::Widgets
{ {
TaskProgressIndicator::TaskProgressIndicator( TaskProgressIndicator::TaskProgressIndicator(QWidget* parent)
const QSharedPointer<InsightWorkerTask>& task,
QWidget* parent
)
: QWidget(parent) : QWidget(parent)
, task(task)
{ {
this->setObjectName("task-progress-indicator"); this->setObjectName("task-progress-indicator");
this->setFixedHeight(26); this->setFixedHeight(26);
this->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed); this->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
this->clearCompletedTasksTimer->setSingleShot(true);
this->clearCompletedTasksTimer->setInterval(2500);
QObject::connect( QObject::connect(
this->task.get(), this->clearCompletedTasksTimer,
&QTimer::timeout,
this,
&TaskProgressIndicator::clearCompletedTasks
);
}
void TaskProgressIndicator::addTask(const QSharedPointer<InsightWorkerTask>& task) {
if (this->tasksById.contains(task->id)) {
return;
}
this->tasksById.emplace(task->id, task);
QObject::connect(
task.get(),
&InsightWorkerTask::started, &InsightWorkerTask::started,
this, this,
&TaskProgressIndicator::onTaskStateChanged &TaskProgressIndicator::refreshProgressPercentage
); );
QObject::connect( QObject::connect(
this->task.get(), task.get(),
&InsightWorkerTask::finished, &InsightWorkerTask::finished,
this, this,
&TaskProgressIndicator::onTaskStateChanged &TaskProgressIndicator::refreshProgressPercentage
); );
QObject::connect( QObject::connect(
this->task.get(), task.get(),
&InsightWorkerTask::failed, &InsightWorkerTask::failed,
this, this,
&TaskProgressIndicator::onTaskStateChanged &TaskProgressIndicator::refreshProgressPercentage
); );
QObject::connect( QObject::connect(
this->task.get(), task.get(),
&InsightWorkerTask::finished, &InsightWorkerTask::finished,
this, this,
&TaskProgressIndicator::onTaskFinished &TaskProgressIndicator::onTaskFinished
); );
QObject::connect( QObject::connect(
this->task.get(), task.get(),
&InsightWorkerTask::progressUpdate, &InsightWorkerTask::progressUpdate,
this, this,
&TaskProgressIndicator::onTaskProgressUpdate &TaskProgressIndicator::refreshProgressPercentage
); );
this->refreshProgressPercentage();
} }
void TaskProgressIndicator::paintEvent(QPaintEvent* event) { void TaskProgressIndicator::paintEvent(QPaintEvent* event) {
const auto taskCount = this->tasksById.size();
if (taskCount < 1) {
return;
}
auto painter = QPainter(this); auto painter = QPainter(this);
const auto size = this->size(); const auto size = this->size();
@@ -63,28 +84,38 @@ namespace Bloom::Widgets
static constexpr auto barColor = QColor(0x8E, 0x8B, 0x83, 90); static constexpr auto barColor = QColor(0x8E, 0x8B, 0x83, 90);
static constexpr auto fontColor = QColor(0x99, 0x9a, 0x9d); static constexpr auto fontColor = QColor(0x99, 0x9a, 0x9d);
static auto font = QFont("'Ubuntu', sans-serif", 9); static const auto font = QFont("'Ubuntu', sans-serif", 9);
painter.setFont(font); painter.setFont(font);
painter.setPen(fontColor); painter.setPen(fontColor);
static constexpr auto barHeight = 3; static constexpr auto barHeight = 3;
const auto barYPosition = size.height() - barHeight - 3; const auto barYPosition = size.height() - barHeight - 3;
const auto percentage = std::max(static_cast<int>(this->task->progressPercentage), 2); const auto percentage = std::max(static_cast<int>(this->progressPercentage), 2);
const auto status = QString( if (taskCount == 1) {
this->task->state == InsightWorkerTaskState::FAILED auto* task = this->tasksById.begin()->second.get();
? " - Failed" const auto status = QString(
: this->task->state == InsightWorkerTaskState::COMPLETED task->state == InsightWorkerTaskState::FAILED
? " - Completed" ? " - Failed"
: "" : task->state == InsightWorkerTaskState::COMPLETED
); ? " - Completed"
: ""
);
painter.drawText( painter.drawText(
0, 0,
barYPosition - 5, barYPosition - 5,
this->task->brief() + status task->brief() + status
); );
} else {
painter.drawText(
0,
barYPosition - 5,
"Processing " + QString::number(taskCount) + " tasks"
);
}
painter.setPen(Qt::PenStyle::NoPen); painter.setPen(Qt::PenStyle::NoPen);
painter.setBrush(backgroundBarColor); painter.setBrush(backgroundBarColor);
@@ -106,23 +137,39 @@ namespace Bloom::Widgets
); );
} }
void TaskProgressIndicator::onTaskProgressUpdate() { void TaskProgressIndicator::clearCompletedTasks() {
this->update(); std::erase_if(
this->tasksById,
[] (const decltype(this->tasksById)::value_type& pair) {
return
pair.second->state == InsightWorkerTaskState::COMPLETED
|| pair.second->state == InsightWorkerTaskState::FAILED;
}
);
this->refreshProgressPercentage();
} }
void TaskProgressIndicator::onTaskStateChanged() { void TaskProgressIndicator::refreshProgressPercentage() {
unsigned int percentageSum = 0;
for (const auto& [taskId, task] : this->tasksById) {
percentageSum += task->progressPercentage;
}
this->progressPercentage = static_cast<std::uint8_t>(
static_cast<float>(percentageSum) / static_cast<float>(this->tasksById.size())
);
this->update(); this->update();
} }
void TaskProgressIndicator::onTaskFinished() { void TaskProgressIndicator::onTaskFinished() {
auto* finishedSignalTimer = new QTimer(); if (this->tasksById.size() > 1) {
finishedSignalTimer->setSingleShot(true); this->clearCompletedTasks();
finishedSignalTimer->setInterval(2500); return;
}
QObject::connect(finishedSignalTimer, &QTimer::timeout, this, [this] { this->clearCompletedTasksTimer->start();
emit this->taskComplete();
});
finishedSignalTimer->start();
} }
} }

View File

@@ -1,10 +1,11 @@
#pragma once #pragma once
#include <QWidget> #include <QWidget>
#include <unordered_map>
#include <QSharedPointer> #include <QSharedPointer>
#include <cstdint> #include <cstdint>
#include <unordered_map>
#include <QEvent> #include <QEvent>
#include <QTimer>
#include "src/Insight/InsightWorker/Tasks/InsightWorkerTask.hpp" #include "src/Insight/InsightWorker/Tasks/InsightWorkerTask.hpp"
@@ -15,19 +16,21 @@ namespace Bloom::Widgets
Q_OBJECT Q_OBJECT
public: public:
TaskProgressIndicator(const QSharedPointer<InsightWorkerTask>& task, QWidget* parent); TaskProgressIndicator(QWidget* parent);
signals: void addTask(const QSharedPointer<InsightWorkerTask>& task);
void taskComplete();
protected: protected:
void paintEvent(QPaintEvent* event) override; void paintEvent(QPaintEvent* event) override;
private: private:
QSharedPointer<InsightWorkerTask> task; std::unordered_map<InsightWorkerTask::IdType, QSharedPointer<InsightWorkerTask>> tasksById;
void onTaskProgressUpdate(); std::uint8_t progressPercentage = 0;
void onTaskStateChanged(); QTimer* clearCompletedTasksTimer = new QTimer(this);
void clearCompletedTasks();
void refreshProgressPercentage();
void onTaskFinished(); void onTaskFinished();
}; };
} }