diff options
Diffstat (limited to 'launcher/tasks/ConcurrentTask.cpp')
-rw-r--r-- | launcher/tasks/ConcurrentTask.cpp | 199 |
1 files changed, 170 insertions, 29 deletions
diff --git a/launcher/tasks/ConcurrentTask.cpp b/launcher/tasks/ConcurrentTask.cpp index 3cc37b2a..fae2f3dc 100644 --- a/launcher/tasks/ConcurrentTask.cpp +++ b/launcher/tasks/ConcurrentTask.cpp @@ -1,11 +1,49 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (c) 2022 flowln <flowlnlnln@gmail.com> + * Copyright (c) 2023 Rachel Powers <508861+Ryex@users.noreply.github.com> + * + * 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, version 3. + * + * 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 <https://www.gnu.org/licenses/>. + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Copyright 2013-2021 MultiMC Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ #include "ConcurrentTask.h" -#include <QDebug> #include <QCoreApplication> +#include <QDebug> +#include "tasks/Task.h" ConcurrentTask::ConcurrentTask(QObject* parent, QString task_name, int max_concurrent) : Task(parent), m_name(task_name), m_total_max_size(max_concurrent) -{ setObjectName(task_name); } +{ + setObjectName(task_name); +} ConcurrentTask::~ConcurrentTask() { @@ -15,14 +53,9 @@ ConcurrentTask::~ConcurrentTask() } } -auto ConcurrentTask::getStepProgress() const -> qint64 +auto ConcurrentTask::getStepProgress() const -> TaskStepProgressList { - return m_stepProgress; -} - -auto ConcurrentTask::getStepTotalProgress() const -> qint64 -{ - return m_stepTotalProgress; + return m_task_progress.values(); } void ConcurrentTask::addTask(Task::Ptr task) @@ -32,11 +65,9 @@ void ConcurrentTask::addTask(Task::Ptr task) void ConcurrentTask::executeTask() { - // Start the least amount of tasks needed, but at least one - int num_starts = qMax(1, qMin(m_total_max_size, m_queue.size())); - for (int i = 0; i < num_starts; i++) { - QMetaObject::invokeMethod(this, &ConcurrentTask::startNext, Qt::QueuedConnection); - } + // Start one task, startNext handles starting the up to the m_total_max_size + // while tracking the number currently being done + QMetaObject::invokeMethod(this, &ConcurrentTask::startNext, Qt::QueuedConnection); } bool ConcurrentTask::abort() @@ -97,18 +128,22 @@ void ConcurrentTask::startNext() Task::Ptr next = m_queue.dequeue(); - connect(next.get(), &Task::succeeded, this, [this, next] { subTaskSucceeded(next); }); + connect(next.get(), &Task::succeeded, this, [this, next]() { subTaskSucceeded(next); }); connect(next.get(), &Task::failed, this, [this, next](QString msg) { subTaskFailed(next, msg); }); - connect(next.get(), &Task::status, this, &ConcurrentTask::subTaskStatus); - connect(next.get(), &Task::stepStatus, this, &ConcurrentTask::subTaskStatus); + connect(next.get(), &Task::status, this, [this, next](QString msg) { subTaskStatus(next, msg); }); + connect(next.get(), &Task::details, this, [this, next](QString msg) { subTaskDetails(next, msg); }); + connect(next.get(), &Task::stepProgress, this, [this, next](TaskStepProgress const& tp) { subTaskStepProgress(next, tp); }); - connect(next.get(), &Task::progress, this, &ConcurrentTask::subTaskProgress); + connect(next.get(), &Task::progress, this, [this, next](qint64 current, qint64 total) { subTaskProgress(next, current, total); }); m_doing.insert(next.get(), next); + auto task_progress = std::make_shared<TaskStepProgress>(TaskStepProgress({ next->getUid() })); + m_task_progress.insert(next->getUid(), task_progress); - setStepStatus(next->isMultiStep() ? next->getStepStatus() : next->getStatus()); updateState(); + updateStepProgress(*task_progress.get(), Operation::ADDED); + QCoreApplication::processEvents(); @@ -123,12 +158,17 @@ void ConcurrentTask::startNext() void ConcurrentTask::subTaskSucceeded(Task::Ptr task) { m_done.insert(task.get(), task); + m_succeeded.insert(task.get(), task); + m_doing.remove(task.get()); + auto task_progress = m_task_progress.value(task->getUid()); + task_progress->state = TaskStepState::Succeeded; disconnect(task.get(), 0, this, 0); + emit stepProgress(*task_progress.get()); updateState(); - + updateStepProgress(*task_progress.get(), Operation::REMOVED); startNext(); } @@ -139,27 +179,128 @@ void ConcurrentTask::subTaskFailed(Task::Ptr task, const QString& msg) m_doing.remove(task.get()); + auto task_progress = m_task_progress.value(task->getUid()); + task_progress->state = TaskStepState::Failed; + disconnect(task.get(), 0, this, 0); + emit stepProgress(*task_progress.get()); updateState(); - + updateStepProgress(*task_progress.get(), Operation::REMOVED); startNext(); } -void ConcurrentTask::subTaskStatus(const QString& msg) +void ConcurrentTask::subTaskStatus(Task::Ptr task, const QString& msg) { - setStepStatus(msg); + auto task_progress = m_task_progress.value(task->getUid()); + task_progress->status = msg; + task_progress->state = TaskStepState::Running; + + emit stepProgress(*task_progress.get()); + + if (totalSize() == 1) { + setStatus(msg); + } } -void ConcurrentTask::subTaskProgress(qint64 current, qint64 total) +void ConcurrentTask::subTaskDetails(Task::Ptr task, const QString& msg) { - m_stepProgress = current; - m_stepTotalProgress = total; + auto task_progress = m_task_progress.value(task->getUid()); + task_progress->details = msg; + task_progress->state = TaskStepState::Running; + + emit stepProgress(*task_progress.get()); + + if (totalSize() == 1) { + setDetails(msg); + } +} + +void ConcurrentTask::subTaskProgress(Task::Ptr task, qint64 current, qint64 total) +{ + auto task_progress = m_task_progress.value(task->getUid()); + + task_progress->old_current = task_progress->current; + task_progress->old_total = task_progress->old_total; + + task_progress->current = current; + task_progress->total = total; + task_progress->state = TaskStepState::Running; + + emit stepProgress(*task_progress.get()); + updateStepProgress(*task_progress.get(), Operation::CHANGED); + updateState(); + + if (totalSize() == 1) { + setProgress(task_progress->current, task_progress->total); + } +} + +void ConcurrentTask::subTaskStepProgress(Task::Ptr task, TaskStepProgress const& task_progress) +{ + Operation op = Operation::ADDED; + + if (!m_task_progress.contains(task_progress.uid)) { + m_task_progress.insert(task_progress.uid, std::make_shared<TaskStepProgress>(task_progress)); + op = Operation::ADDED; + emit stepProgress(task_progress); + updateStepProgress(task_progress, op); + } else { + auto tp = m_task_progress.value(task_progress.uid); + + tp->old_current = tp->current; + tp->old_total = tp->total; + + tp->current = task_progress.current; + tp->total = task_progress.total; + tp->status = task_progress.status; + tp->details = task_progress.details; + + op = Operation::CHANGED; + emit stepProgress(*tp.get()); + updateStepProgress(*tp.get(), op); + } + +} + +void ConcurrentTask::updateStepProgress(TaskStepProgress const& changed_progress, Operation op) +{ + + switch (op) { + case Operation::ADDED: + m_stepProgress += changed_progress.current; + m_stepTotalProgress += changed_progress.total; + break; + case Operation::REMOVED: + m_stepProgress -= changed_progress.current; + m_stepTotalProgress -= changed_progress.total; + break; + case Operation::CHANGED: + m_stepProgress -= changed_progress.old_current; + m_stepTotalProgress -= changed_progress.old_total; + m_stepProgress += changed_progress.current; + m_stepTotalProgress += changed_progress.total; + break; + } + } void ConcurrentTask::updateState() { - setProgress(m_done.count(), totalSize()); - setStatus(tr("Executing %1 task(s) (%2 out of %3 are done)") - .arg(QString::number(m_doing.count()), QString::number(m_done.count()), QString::number(totalSize()))); + if (totalSize() > 1) { + setProgress(m_done.count(), totalSize()); + setStatus(tr("Executing %1 task(s) (%2 out of %3 are done)") + .arg(QString::number(m_doing.count()), QString::number(m_done.count()), QString::number(totalSize()))); + } else { + setProgress(m_stepProgress, m_stepTotalProgress); + QString status = tr("Please wait..."); + if (m_queue.size() > 0) { + status = tr("Waiting for a task to start..."); + } else if (m_doing.size() > 0) { + status = tr("Executing 1 task:"); + } else if (m_done.size() > 0) { + status = tr("Task finished."); + } + setStatus(status); + } } |