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

View File

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

View File

@@ -3,58 +3,79 @@
#include <QPainter>
#include <QColor>
#include <algorithm>
#include <QTimer>
namespace Bloom::Widgets
{
TaskProgressIndicator::TaskProgressIndicator(
const QSharedPointer<InsightWorkerTask>& task,
QWidget* parent
)
TaskProgressIndicator::TaskProgressIndicator(QWidget* parent)
: QWidget(parent)
, task(task)
{
this->setObjectName("task-progress-indicator");
this->setFixedHeight(26);
this->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
this->clearCompletedTasksTimer->setSingleShot(true);
this->clearCompletedTasksTimer->setInterval(2500);
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,
this,
&TaskProgressIndicator::onTaskStateChanged
&TaskProgressIndicator::refreshProgressPercentage
);
QObject::connect(
this->task.get(),
task.get(),
&InsightWorkerTask::finished,
this,
&TaskProgressIndicator::onTaskStateChanged
&TaskProgressIndicator::refreshProgressPercentage
);
QObject::connect(
this->task.get(),
task.get(),
&InsightWorkerTask::failed,
this,
&TaskProgressIndicator::onTaskStateChanged
&TaskProgressIndicator::refreshProgressPercentage
);
QObject::connect(
this->task.get(),
task.get(),
&InsightWorkerTask::finished,
this,
&TaskProgressIndicator::onTaskFinished
);
QObject::connect(
this->task.get(),
task.get(),
&InsightWorkerTask::progressUpdate,
this,
&TaskProgressIndicator::onTaskProgressUpdate
&TaskProgressIndicator::refreshProgressPercentage
);
this->refreshProgressPercentage();
}
void TaskProgressIndicator::paintEvent(QPaintEvent* event) {
const auto taskCount = this->tasksById.size();
if (taskCount < 1) {
return;
}
auto painter = QPainter(this);
const auto size = this->size();
@@ -63,28 +84,38 @@ namespace Bloom::Widgets
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);
static const 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(static_cast<int>(this->task->progressPercentage), 2);
const auto percentage = std::max(static_cast<int>(this->progressPercentage), 2);
const auto status = QString(
this->task->state == InsightWorkerTaskState::FAILED
? " - Failed"
: this->task->state == InsightWorkerTaskState::COMPLETED
? " - Completed"
: ""
);
if (taskCount == 1) {
auto* task = this->tasksById.begin()->second.get();
const auto status = QString(
task->state == InsightWorkerTaskState::FAILED
? " - Failed"
: task->state == InsightWorkerTaskState::COMPLETED
? " - Completed"
: ""
);
painter.drawText(
0,
barYPosition - 5,
this->task->brief() + status
);
painter.drawText(
0,
barYPosition - 5,
task->brief() + status
);
} else {
painter.drawText(
0,
barYPosition - 5,
"Processing " + QString::number(taskCount) + " tasks"
);
}
painter.setPen(Qt::PenStyle::NoPen);
painter.setBrush(backgroundBarColor);
@@ -106,23 +137,39 @@ namespace Bloom::Widgets
);
}
void TaskProgressIndicator::onTaskProgressUpdate() {
this->update();
void TaskProgressIndicator::clearCompletedTasks() {
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();
}
void TaskProgressIndicator::onTaskFinished() {
auto* finishedSignalTimer = new QTimer();
finishedSignalTimer->setSingleShot(true);
finishedSignalTimer->setInterval(2500);
if (this->tasksById.size() > 1) {
this->clearCompletedTasks();
return;
}
QObject::connect(finishedSignalTimer, &QTimer::timeout, this, [this] {
emit this->taskComplete();
});
finishedSignalTimer->start();
this->clearCompletedTasksTimer->start();
}
}

View File

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