/*** Olive - Non-Linear Video Editor Copyright (C) 2022 Olive Team Modifications Copyright (C) 2025 mikesolar 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 "task.h" #include #include namespace olive { #define super ProgressDialog TaskDialog::TaskDialog(Task *task, const QString &title, QWidget *parent) : super(task->GetTitle(), title, parent) , task_(task) , destroy_on_close_(true) , already_shown_(false) , task_finished_(false) { // Clear task when this dialog is destroyed task_->setParent(this); // Connect the save manager progress signal to the progress bar update on the dialog connect(task_, &Task::ProgressChanged, this, &TaskDialog::SetProgress, Qt::QueuedConnection); // Connect cancel signal (must be a direct connection or it'll be queued after the task has // already finished) connect(this, &TaskDialog::Cancelled, task_, &Task::Cancel, Qt::DirectConnection); } void TaskDialog::showEvent(QShowEvent *e) { super::showEvent(e); if (!already_shown_) { // Create watcher for when the task finishes QFutureWatcher *task_watcher = new QFutureWatcher(); // Listen for when the task finishes connect(task_watcher, &QFutureWatcher::finished, this, &TaskDialog::TaskFinished, Qt::QueuedConnection); // Run task in another thread with QtConcurrent task_watcher->setFuture( #if QT_VERSION_MAJOR >= 6 QtConcurrent::run(&Task::Start, task_) #else QtConcurrent::run(task_, &Task::Start) #endif ); already_shown_ = true; } } void TaskDialog::closeEvent(QCloseEvent *e) { // Cancel task if it is running task_->Cancel(); // Standard close function super::closeEvent(e); // Reset shown already_shown_ = false; // Clean up this task and dialog, but only if the task has actually finished. // If the user closes the window while the task is still running, deleting now // would destroy the Task object out from under the worker thread and crash // when the task later touches its own members (e.g. ExportTask::encoder_). if (destroy_on_close_ && task_finished_) { deleteLater(); } } void TaskDialog::TaskFinished() { QFutureWatcher *task_watcher = static_cast *>(sender()); task_finished_ = true; if (task_watcher->result()) { emit TaskSucceeded(task_); } else { ShowErrorMessage(tr("Task Failed"), task_->GetError()); emit TaskFailed(task_); } task_watcher->deleteLater(); close(); } }