From 4f21a930dd4e42d590a60e252edc3aaf06e3c5a2 Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Sun, 24 May 2020 18:09:27 +1000 Subject: [PATCH] tasks: added elapsed/remaining time displays for all tasks --- app/dialog/progress/progress.cpp | 6 ++ app/dialog/progress/progress.h | 3 + app/dialog/task/task.cpp | 2 +- app/task/task.h | 24 +++++- app/task/taskmanager.cpp | 2 +- app/widget/taskview/CMakeLists.txt | 2 + app/widget/taskview/elapsedcounterwidget.cpp | 88 ++++++++++++++++++++ app/widget/taskview/elapsedcounterwidget.h | 61 ++++++++++++++ app/widget/taskview/taskviewitem.cpp | 27 ++++-- app/widget/taskview/taskviewitem.h | 7 +- 10 files changed, 210 insertions(+), 12 deletions(-) create mode 100644 app/widget/taskview/elapsedcounterwidget.cpp create mode 100644 app/widget/taskview/elapsedcounterwidget.h diff --git a/app/dialog/progress/progress.cpp b/app/dialog/progress/progress.cpp index 90c3b72e0..f1f860f57 100644 --- a/app/dialog/progress/progress.cpp +++ b/app/dialog/progress/progress.cpp @@ -46,6 +46,9 @@ ProgressDialog::ProgressDialog(const QString& message, const QString& title, QWi bar_->setMaximum(100); layout->addWidget(bar_); + elapsed_timer_lbl_ = new ElapsedCounterWidget(); + layout->addWidget(elapsed_timer_lbl_); + QHBoxLayout* cancel_layout = new QHBoxLayout(); layout->addLayout(cancel_layout); cancel_layout->setMargin(0); @@ -63,6 +66,8 @@ void ProgressDialog::showEvent(QShowEvent *e) { QDialog::showEvent(e); + elapsed_timer_lbl_->Start(); + #ifdef Q_OS_WINDOWS Core::instance()->main_window()->SetTaskbarButtonState(TBPF_NORMAL); #endif @@ -82,6 +87,7 @@ void ProgressDialog::SetProgress(double value) int percent = qRound(100.0 * value); bar_->setValue(percent); + elapsed_timer_lbl_->SetProgress(value); #ifdef Q_OS_WINDOWS Core::instance()->main_window()->SetTaskbarButtonProgress(percent, 100); diff --git a/app/dialog/progress/progress.h b/app/dialog/progress/progress.h index a4a233e19..401afe839 100644 --- a/app/dialog/progress/progress.h +++ b/app/dialog/progress/progress.h @@ -25,6 +25,7 @@ #include #include "common/debug.h" +#include "widget/taskview/elapsedcounterwidget.h" OLIVE_NAMESPACE_ENTER @@ -51,6 +52,8 @@ protected: private: QProgressBar* bar_; + ElapsedCounterWidget* elapsed_timer_lbl_; + }; OLIVE_NAMESPACE_EXIT diff --git a/app/dialog/task/task.cpp b/app/dialog/task/task.cpp index cad6e32a6..e3e1f673b 100644 --- a/app/dialog/task/task.cpp +++ b/app/dialog/task/task.cpp @@ -52,7 +52,7 @@ void TaskDialog::showEvent(QShowEvent *e) this, &TaskDialog::TaskFinished, Qt::QueuedConnection); // Run task in another thread with QtConcurrent - task_watcher->setFuture(QtConcurrent::run(task_, &Task::Run)); + task_watcher->setFuture(QtConcurrent::run(task_, &Task::Start)); } void TaskDialog::closeEvent(QCloseEvent *e) diff --git a/app/task/task.h b/app/task/task.h index 43d271a2c..fc4118fc5 100644 --- a/app/task/task.h +++ b/app/task/task.h @@ -22,6 +22,7 @@ #define TASK_H #include +#include #include #include "common/cancelableobject.h" @@ -54,14 +55,15 @@ public: */ Task() : title_(tr("Task")), - error_(tr("Unknown error")) + error_(tr("Unknown error")), + start_time_(0) { } /** * @brief Retrieve the current title of this Task */ - const QString& GetTitle() + const QString& GetTitle() const { return title_; } @@ -69,11 +71,16 @@ public: /** * @brief Returns the error that occurred if Run() returns false */ - const QString& GetError() + const QString& GetError() const { return error_; } + const qint64& GetStartTime() const + { + return start_time_; + } + public slots: /** * @brief Run this task @@ -82,7 +89,12 @@ public slots: * * \see GetError() if this returns false. */ - virtual bool Run() = 0; + bool Start() + { + start_time_ = QDateTime::currentMSecsSinceEpoch(); + + return Run(); + } /** * @brief Reset state so that Run() can be called again. @@ -104,6 +116,8 @@ public slots: } protected: + virtual bool Run() = 0; + /** * @brief Set the error message * @@ -144,6 +158,8 @@ private: QString error_; + qint64 start_time_; + }; OLIVE_NAMESPACE_EXIT diff --git a/app/task/taskmanager.cpp b/app/task/taskmanager.cpp index a65888bee..ed3aa9852 100644 --- a/app/task/taskmanager.cpp +++ b/app/task/taskmanager.cpp @@ -93,7 +93,7 @@ void TaskManager::AddTask(Task* t) tasks_.insert(watcher, t); // Run task concurrently - watcher->setFuture(QtConcurrent::run(t, &Task::Run)); + watcher->setFuture(QtConcurrent::run(t, &Task::Start)); // Emit signal that a Task was added emit TaskAdded(t); diff --git a/app/widget/taskview/CMakeLists.txt b/app/widget/taskview/CMakeLists.txt index 99ecf3a8f..26bcced3f 100644 --- a/app/widget/taskview/CMakeLists.txt +++ b/app/widget/taskview/CMakeLists.txt @@ -16,6 +16,8 @@ set(OLIVE_SOURCES ${OLIVE_SOURCES} + widget/taskview/elapsedcounterwidget.h + widget/taskview/elapsedcounterwidget.cpp widget/taskview/taskview.h widget/taskview/taskview.cpp widget/taskview/taskviewitem.h diff --git a/app/widget/taskview/elapsedcounterwidget.cpp b/app/widget/taskview/elapsedcounterwidget.cpp new file mode 100644 index 000000000..b5ce95abb --- /dev/null +++ b/app/widget/taskview/elapsedcounterwidget.cpp @@ -0,0 +1,88 @@ +/*** + + Olive - Non-Linear Video Editor + Copyright (C) 2019 Olive Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +***/ + +#include "elapsedcounterwidget.h" + +#include +#include + +#include "common/timecodefunctions.h" + +OLIVE_NAMESPACE_ENTER + +ElapsedCounterWidget::ElapsedCounterWidget(QWidget* parent) : + QWidget(parent), + last_progress_(0), + start_time_(0) +{ + QHBoxLayout* layout = new QHBoxLayout(this); + layout->setSpacing(0); + layout->setMargin(0); + + elapsed_lbl_ = new QLabel(); + layout->addWidget(elapsed_lbl_); + + remaining_lbl_ = new QLabel(); + layout->addWidget(remaining_lbl_); + + elapsed_timer_.setInterval(500); + connect(&elapsed_timer_, &QTimer::timeout, this, &ElapsedCounterWidget::UpdateTimers); + UpdateTimers(); +} + +void ElapsedCounterWidget::SetProgress(double d) +{ + last_progress_ = d; + UpdateTimers(); +} + +void ElapsedCounterWidget::Start() +{ + Start(QDateTime::currentMSecsSinceEpoch()); +} + +void ElapsedCounterWidget::Start(qint64 start_time) +{ + start_time_ = start_time; + elapsed_timer_.start(); + UpdateTimers(); +} + +void ElapsedCounterWidget::UpdateTimers() +{ + int64_t elapsed_ms, remaining_ms; + + if (last_progress_ > 0) { + elapsed_ms = QDateTime::currentMSecsSinceEpoch() - start_time_; + + double ms_per_progress_unit = elapsed_ms / last_progress_; + double remaining_progress = 1.0 - last_progress_; + + remaining_ms = qRound64(ms_per_progress_unit * remaining_progress); + } else { + elapsed_ms = 0; + remaining_ms = 0; + } + + elapsed_lbl_->setText(tr("Elapsed: %1").arg(Timecode::TimeToString(elapsed_ms))); + remaining_lbl_->setText(tr("Remaining: %1").arg(Timecode::TimeToString(remaining_ms))); +} + +OLIVE_NAMESPACE_EXIT diff --git a/app/widget/taskview/elapsedcounterwidget.h b/app/widget/taskview/elapsedcounterwidget.h new file mode 100644 index 000000000..fcfdff43a --- /dev/null +++ b/app/widget/taskview/elapsedcounterwidget.h @@ -0,0 +1,61 @@ +/*** + + Olive - Non-Linear Video Editor + Copyright (C) 2019 Olive Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +***/ + +#ifndef ELAPSEDCOUNTERWIDGET_H +#define ELAPSEDCOUNTERWIDGET_H + +#include +#include +#include + +#include "common/define.h" + +OLIVE_NAMESPACE_ENTER + +class ElapsedCounterWidget : public QWidget +{ + Q_OBJECT +public: + ElapsedCounterWidget(QWidget* parent = nullptr); + + void SetProgress(double d); + + void Start(); + void Start(qint64 start_time); + +private: + QLabel* elapsed_lbl_; + + QLabel* remaining_lbl_; + + double last_progress_; + + QTimer elapsed_timer_; + + qint64 start_time_; + +private slots: + void UpdateTimers(); + +}; + +OLIVE_NAMESPACE_EXIT + +#endif // ELAPSEDCOUNTERWIDGET_H diff --git a/app/widget/taskview/taskviewitem.cpp b/app/widget/taskview/taskviewitem.cpp index b3438791c..49c7c8c91 100644 --- a/app/widget/taskview/taskviewitem.cpp +++ b/app/widget/taskview/taskviewitem.cpp @@ -20,8 +20,10 @@ #include "taskviewitem.h" +#include #include +#include "common/timecodefunctions.h" #include "ui/icons/icons.h" OLIVE_NAMESPACE_ENTER @@ -55,9 +57,22 @@ TaskViewItem::TaskViewItem(Task* task, QWidget *parent) : cancel_btn_->setIcon(icon::Error); middle_layout->addWidget(cancel_btn_); - // Create status label - task_status_lbl_ = new QLabel(this); - layout->addWidget(task_status_lbl_); + // Create stack with error label and elapsed/remaining time + status_stack_ = new QStackedWidget(); + status_stack_->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum); + layout->addWidget(status_stack_); + + // Create elapsed timer + elapsed_timer_lbl_ = new ElapsedCounterWidget(); + status_stack_->addWidget(elapsed_timer_lbl_); + + // Create error label + task_error_lbl_ = new QLabel(this); + status_stack_->addWidget(task_error_lbl_); + + // Set up elapsed timer + status_stack_->setCurrentWidget(elapsed_timer_lbl_); + elapsed_timer_lbl_->Start(task_->GetStartTime()); // Connect to the task connect(task_, &Task::ProgressChanged, this, &TaskViewItem::UpdateProgress); @@ -66,13 +81,15 @@ TaskViewItem::TaskViewItem(Task* task, QWidget *parent) : void TaskViewItem::Failed() { - task_status_lbl_->setStyleSheet("color: red"); - task_status_lbl_->setText(tr("Error: %1").arg(task_->GetError())); + status_stack_->setCurrentWidget(task_error_lbl_); + task_error_lbl_->setStyleSheet("color: red"); + task_error_lbl_->setText(tr("Error: %1").arg(task_->GetError())); } void TaskViewItem::UpdateProgress(double d) { progress_bar_->setValue(qRound(100.0 * d)); + elapsed_timer_lbl_->SetProgress(d); } OLIVE_NAMESPACE_EXIT diff --git a/app/widget/taskview/taskviewitem.h b/app/widget/taskview/taskviewitem.h index 5063834e2..40f9c003b 100644 --- a/app/widget/taskview/taskviewitem.h +++ b/app/widget/taskview/taskviewitem.h @@ -24,8 +24,10 @@ #include #include #include +#include #include +#include "elapsedcounterwidget.h" #include "task/task.h" OLIVE_NAMESPACE_ENTER @@ -54,7 +56,10 @@ private: QLabel* task_name_lbl_; QProgressBar* progress_bar_; QPushButton* cancel_btn_; - QLabel* task_status_lbl_; + + QStackedWidget* status_stack_; + ElapsedCounterWidget* elapsed_timer_lbl_; + QLabel* task_error_lbl_; Task* task_;