New background tasks window
This commit is contained in:
@@ -13,6 +13,8 @@ namespace Bloom::Widgets
|
||||
this->setObjectName("task-indicator");
|
||||
this->setFixedSize(50, 26);
|
||||
|
||||
this->taskWindow = new TaskWindow(this);
|
||||
|
||||
auto* insightSignals = InsightSignals::instance();
|
||||
|
||||
QObject::connect(
|
||||
@@ -42,6 +44,11 @@ namespace Bloom::Widgets
|
||||
this->update();
|
||||
}
|
||||
|
||||
void TaskIndicator::mousePressEvent(QMouseEvent* event) {
|
||||
this->taskWindow->show();
|
||||
this->taskWindow->activateWindow();
|
||||
}
|
||||
|
||||
void TaskIndicator::paintEvent(QPaintEvent* event) {
|
||||
auto painter = QPainter(this);
|
||||
painter.setPen(Qt::PenStyle::NoPen);
|
||||
|
||||
@@ -4,8 +4,10 @@
|
||||
#include <QSharedPointer>
|
||||
#include <unordered_map>
|
||||
#include <QEvent>
|
||||
#include <QMouseEvent>
|
||||
|
||||
#include "src/Insight/InsightWorker/Tasks/InsightWorkerTask.hpp"
|
||||
#include "src/Insight/UserInterfaces/InsightWindow/Widgets/TaskWindow/TaskWindow.hpp"
|
||||
|
||||
namespace Bloom::Widgets
|
||||
{
|
||||
@@ -19,12 +21,15 @@ namespace Bloom::Widgets
|
||||
protected:
|
||||
void enterEvent(QEnterEvent* event) override;
|
||||
void leaveEvent(QEvent* event) override;
|
||||
void mousePressEvent(QMouseEvent* event) override;
|
||||
void paintEvent(QPaintEvent* event) override;
|
||||
|
||||
private:
|
||||
std::unordered_map<InsightWorkerTask::IdType, QSharedPointer<InsightWorkerTask>> activeTasksById;
|
||||
bool hovered = false;
|
||||
|
||||
TaskWindow* taskWindow = nullptr;
|
||||
|
||||
void onTaskQueued(QSharedPointer<InsightWorkerTask> task);
|
||||
void onTaskFinished(QSharedPointer<InsightWorkerTask> task);
|
||||
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
#task-window,
|
||||
#task-window #container {
|
||||
background-color: #373835;
|
||||
border: none;
|
||||
}
|
||||
|
||||
#loading-placeholder-label {
|
||||
color: #737375;
|
||||
font-size: 14px;
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
#include "Task.hpp"
|
||||
|
||||
#include <QPainter>
|
||||
#include <QColor>
|
||||
#include <QTimer>
|
||||
|
||||
namespace Bloom::Widgets
|
||||
{
|
||||
Task::Task(
|
||||
const QSharedPointer<InsightWorkerTask>& task,
|
||||
QWidget* parent
|
||||
)
|
||||
: QWidget(parent)
|
||||
, task(task)
|
||||
{
|
||||
this->setObjectName("task");
|
||||
this->setFixedHeight(80);
|
||||
this->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
|
||||
|
||||
this->setContentsMargins(15, 0, 15, 0);
|
||||
|
||||
QObject::connect(
|
||||
this->task.get(),
|
||||
&InsightWorkerTask::started,
|
||||
this,
|
||||
&Task::onTaskStateChanged
|
||||
);
|
||||
|
||||
QObject::connect(
|
||||
this->task.get(),
|
||||
&InsightWorkerTask::finished,
|
||||
this,
|
||||
&Task::onTaskStateChanged
|
||||
);
|
||||
|
||||
QObject::connect(
|
||||
this->task.get(),
|
||||
&InsightWorkerTask::failed,
|
||||
this,
|
||||
&Task::onTaskStateChanged
|
||||
);
|
||||
|
||||
QObject::connect(
|
||||
this->task.get(),
|
||||
&InsightWorkerTask::finished,
|
||||
this,
|
||||
&Task::onTaskFinished
|
||||
);
|
||||
|
||||
QObject::connect(
|
||||
this->task.get(),
|
||||
&InsightWorkerTask::progressUpdate,
|
||||
this,
|
||||
&Task::onTaskProgressUpdate
|
||||
);
|
||||
}
|
||||
|
||||
void Task::paintEvent(QPaintEvent* event) {
|
||||
auto painter = QPainter(this);
|
||||
|
||||
const auto margins = this->contentsMargins();
|
||||
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 constexpr auto statusFontColor = QColor(0x99, 0x9a, 0x9d, 200);
|
||||
|
||||
static auto font = QFont("'Ubuntu', sans-serif");
|
||||
font.setPixelSize(14);
|
||||
|
||||
static auto statusFont = QFont("'Ubuntu', sans-serif");
|
||||
statusFont.setPixelSize(12);
|
||||
|
||||
painter.setFont(font);
|
||||
painter.setPen(fontColor);
|
||||
|
||||
static constexpr auto barHeight = 5;
|
||||
const auto barYPosition = 35;
|
||||
|
||||
painter.drawText(
|
||||
margins.left(),
|
||||
barYPosition - 12,
|
||||
this->task->brief()
|
||||
);
|
||||
|
||||
const auto status = QString(
|
||||
this->task->state == InsightWorkerTaskState::FAILED
|
||||
? "Failed"
|
||||
: this->task->state == InsightWorkerTaskState::COMPLETED
|
||||
? "Completed"
|
||||
: this->task->state == InsightWorkerTaskState::STARTED
|
||||
? "Running"
|
||||
: "Queued"
|
||||
);
|
||||
|
||||
painter.setFont(statusFont);
|
||||
painter.setPen(statusFontColor);
|
||||
painter.drawText(
|
||||
margins.left(),
|
||||
barYPosition + barHeight + 20,
|
||||
status
|
||||
);
|
||||
|
||||
painter.setPen(Qt::PenStyle::NoPen);
|
||||
painter.setBrush(backgroundBarColor);
|
||||
|
||||
painter.drawRect(
|
||||
margins.left(),
|
||||
barYPosition,
|
||||
size.width() - margins.left() - margins.right(),
|
||||
barHeight
|
||||
);
|
||||
|
||||
painter.setBrush(barColor);
|
||||
|
||||
painter.drawRect(
|
||||
margins.left(),
|
||||
barYPosition,
|
||||
static_cast<int>(
|
||||
static_cast<float>(size.width() - margins.left() - margins.right())
|
||||
* (static_cast<float>(this->task->progressPercentage) / 100)
|
||||
),
|
||||
barHeight
|
||||
);
|
||||
|
||||
painter.setPen(backgroundBarColor);
|
||||
|
||||
painter.drawLine(
|
||||
0,
|
||||
size.height() - 1,
|
||||
size.width(),
|
||||
size.height() - 1
|
||||
);
|
||||
}
|
||||
|
||||
void Task::onTaskProgressUpdate() {
|
||||
this->update();
|
||||
}
|
||||
|
||||
void Task::onTaskStateChanged() {
|
||||
this->update();
|
||||
}
|
||||
|
||||
void Task::onTaskFinished() {
|
||||
emit this->taskComplete(this->task->id);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
|
||||
#include <QWidget>
|
||||
#include <QSharedPointer>
|
||||
#include <QEvent>
|
||||
|
||||
#include "src/Insight/InsightWorker/Tasks/InsightWorkerTask.hpp"
|
||||
|
||||
namespace Bloom::Widgets
|
||||
{
|
||||
class Task: public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Task(const QSharedPointer<InsightWorkerTask>& task, QWidget* parent);
|
||||
|
||||
signals:
|
||||
void taskComplete(InsightWorkerTask::IdType taskId);
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent* event) override;
|
||||
|
||||
private:
|
||||
QSharedPointer<InsightWorkerTask> task;
|
||||
|
||||
void onTaskProgressUpdate();
|
||||
void onTaskStateChanged();
|
||||
void onTaskFinished();
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
#include "TaskWindow.hpp"
|
||||
|
||||
#include <QScrollArea>
|
||||
#include <QTimer>
|
||||
|
||||
#include "src/Insight/UserInterfaces/InsightWindow/UiLoader.hpp"
|
||||
|
||||
#include "src/Insight/InsightSignals.hpp"
|
||||
|
||||
#include "src/Services/PathService.hpp"
|
||||
#include "src/Exceptions/Exception.hpp"
|
||||
|
||||
namespace Bloom::Widgets
|
||||
{
|
||||
TaskWindow::TaskWindow(QWidget* parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
this->setObjectName("task-window");
|
||||
this->setMinimumSize(900, 500);
|
||||
|
||||
this->setWindowFlag(Qt::Window);
|
||||
this->setWindowTitle("Background Tasks");
|
||||
|
||||
auto windowUiFile = QFile(
|
||||
QString::fromStdString(Services::PathService::compiledResourcesPath()
|
||||
+ "/src/Insight/UserInterfaces/InsightWindow/Widgets/TaskWindow/UiFiles/TaskWindow.ui"
|
||||
)
|
||||
);
|
||||
|
||||
auto stylesheetFile = QFile(
|
||||
QString::fromStdString(Services::PathService::compiledResourcesPath()
|
||||
+ "/src/Insight/UserInterfaces/InsightWindow/Widgets/TaskWindow/Stylesheets/TaskWindow.qss"
|
||||
)
|
||||
);
|
||||
|
||||
if (!windowUiFile.open(QFile::ReadOnly)) {
|
||||
throw Exceptions::Exception("Failed to open TaskWindow UI file");
|
||||
}
|
||||
|
||||
if (!stylesheetFile.open(QFile::ReadOnly)) {
|
||||
throw Exceptions::Exception("Failed to open TaskWindow stylesheet file");
|
||||
}
|
||||
|
||||
auto uiLoader = UiLoader(this);
|
||||
this->container = uiLoader.load(&windowUiFile, this);
|
||||
this->container->setStyleSheet(stylesheetFile.readAll());
|
||||
|
||||
this->container->setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
this->taskWidgetLayout = this->container->findChild<QVBoxLayout*>();
|
||||
this->taskPlaceholderLabel = this->container->findChild<Label*>("loading-placeholder-label");
|
||||
|
||||
auto* insightSignals = InsightSignals::instance();
|
||||
|
||||
QObject::connect(
|
||||
insightSignals,
|
||||
&InsightSignals::taskQueued,
|
||||
this,
|
||||
&TaskWindow::onTaskQueued
|
||||
);
|
||||
}
|
||||
|
||||
void TaskWindow::resizeEvent(QResizeEvent* event) {
|
||||
this->container->setFixedSize(this->size());
|
||||
}
|
||||
|
||||
void TaskWindow::onTaskQueued(const QSharedPointer<InsightWorkerTask>& task) {
|
||||
auto* taskWidget = new Task(task, this);
|
||||
this->taskWidgetLayout->insertWidget(0, taskWidget);
|
||||
|
||||
QObject::connect(taskWidget, &Task::taskComplete, this, [this] (InsightWorkerTask::IdType taskId) {
|
||||
auto* finishedSignalTimer = new QTimer();
|
||||
finishedSignalTimer->setSingleShot(true);
|
||||
finishedSignalTimer->setInterval(10000);
|
||||
|
||||
QObject::connect(finishedSignalTimer, &QTimer::timeout, this, [this, taskId] {
|
||||
const auto& taskWidgetIt = this->taskWidgetsByTaskId.find(taskId);
|
||||
|
||||
if (taskWidgetIt == this->taskWidgetsByTaskId.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto* taskWidget = taskWidgetIt->second;
|
||||
this->taskWidgetLayout->removeWidget(taskWidget);
|
||||
taskWidget->deleteLater();
|
||||
this->taskWidgetsByTaskId.erase(taskWidgetIt);
|
||||
|
||||
if (this->taskWidgetsByTaskId.empty()) {
|
||||
this->taskPlaceholderLabel->show();
|
||||
}
|
||||
});
|
||||
|
||||
finishedSignalTimer->start();
|
||||
});
|
||||
|
||||
this->taskWidgetsByTaskId.emplace(task->id, taskWidget);
|
||||
|
||||
this->taskPlaceholderLabel->hide();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
|
||||
#include <QWidget>
|
||||
#include <QSharedPointer>
|
||||
#include <QVBoxLayout>
|
||||
#include <unordered_map>
|
||||
#include <QEvent>
|
||||
|
||||
#include "Task.hpp"
|
||||
|
||||
#include "src/Insight/UserInterfaces/InsightWindow/Widgets/Label.hpp"
|
||||
#include "src/Insight/InsightWorker/Tasks/InsightWorkerTask.hpp"
|
||||
|
||||
namespace Bloom::Widgets
|
||||
{
|
||||
class TaskWindow: public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
TaskWindow(QWidget* parent);
|
||||
|
||||
protected:
|
||||
void resizeEvent(QResizeEvent* event) override;
|
||||
|
||||
private:
|
||||
QWidget* container = nullptr;
|
||||
QVBoxLayout* taskWidgetLayout = nullptr;
|
||||
|
||||
Label* taskPlaceholderLabel = nullptr;
|
||||
|
||||
std::unordered_map<InsightWorkerTask::IdType, Task*> taskWidgetsByTaskId;
|
||||
|
||||
void onTaskQueued(const QSharedPointer<InsightWorkerTask>& task);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<widget class="QScrollArea" name="container">
|
||||
<property name="widgetResizable"><bool>true</bool></property>
|
||||
<property name="verticalScrollBarPolicy"><enum>Qt::ScrollBarAsNeeded</enum></property>
|
||||
<property name="sizeAdjustPolicy"><enum>QAbstractScrollArea::AdjustToContents</enum></property>
|
||||
<property name="horizontalScrollBarPolicy"><enum>Qt::ScrollBarAlwaysOff</enum></property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding"/>
|
||||
</property>
|
||||
<widget class="QWidget" name="item-container">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding"/>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="item-container-layout">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetMinAndMaxSize</enum>
|
||||
</property>
|
||||
<item alignment="Qt::AlignHCenter">
|
||||
<widget class="Label" name="loading-placeholder-label">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding"/>
|
||||
</property>
|
||||
<property name="visible">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<enum>Qt::AlignCenter</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>No background tasks</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
|
||||
</ui>
|
||||
Reference in New Issue
Block a user