feat: add details signal to Task
				
					
				
			feat: add details to mod pack downloading feat: add logging rule sloading form `ligging.ini at data path root feat: add `launcher.task` `launcher.task.net` and `launcher.task.net.[down|up]load` logging categories fix: add new subtask progress to the end of the lay out not the beginning (cuts down on flickering) Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
This commit is contained in:
		| @@ -46,6 +46,7 @@ | ||||
| #include "net/PasteUpload.h" | ||||
| #include "pathmatcher/MultiMatcher.h" | ||||
| #include "pathmatcher/SimplePrefixMatcher.h" | ||||
| #include "settings/INIFile.h" | ||||
| #include "ui/MainWindow.h" | ||||
| #include "ui/InstanceWindow.h" | ||||
|  | ||||
| @@ -410,6 +411,24 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) | ||||
|                 " " "|" " " | ||||
|                 "%{if-category}[%{category}]: %{endif}" | ||||
|                 "%{message}"); | ||||
|          | ||||
|         if(QFile::exists("logging.ini")) { | ||||
|             // load and set logging rules | ||||
|             qDebug() << "Loading logging rules from:" << QString("%1/logging.ini").arg(dataPath); | ||||
|             INIFile loggingRules; | ||||
|             bool rulesLoaded = loggingRules.loadFile(QString("logging.ini")); | ||||
|             if (rulesLoaded) { | ||||
|                 QStringList rules; | ||||
|                 qDebug() << "Setting log rules:"; | ||||
|                 for (auto it = loggingRules.begin(); it != loggingRules.end(); ++it) { | ||||
|                     auto rule = it.key() + "=" + it.value().toString(); | ||||
|                     rules.append(rule); | ||||
|                     qDebug() << "    " << rule; | ||||
|                 } | ||||
|                 auto rules_str = rules.join("\n"); | ||||
|                 QLoggingCategory::setFilterRules(rules_str); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         qDebug() << "<> Log initialized."; | ||||
|     } | ||||
|   | ||||
| @@ -123,6 +123,8 @@ set(NET_SOURCES | ||||
|     net/HttpMetaCache.h | ||||
|     net/MetaCacheSink.cpp | ||||
|     net/MetaCacheSink.h | ||||
|     net/logging.h | ||||
|     net/logging.cpp | ||||
|     net/NetAction.h | ||||
|     net/NetJob.cpp | ||||
|     net/NetJob.h | ||||
| @@ -563,6 +565,37 @@ ecm_qt_declare_logging_category(CORE_SOURCES | ||||
|     EXPORT "${Launcher_Name}" | ||||
| ) | ||||
|  | ||||
| ecm_qt_export_logging_category( | ||||
|     IDENTIFIER taskLogC | ||||
|     CATEGORY_NAME "launcher.task" | ||||
|     DEFAULT_SEVERITY Debug | ||||
|     DESCRIPTION "Task actions" | ||||
|     EXPORT "${Launcher_Name}" | ||||
| ) | ||||
|  | ||||
| ecm_qt_export_logging_category( | ||||
|     IDENTIFIER taskNetLogC | ||||
|     CATEGORY_NAME "launcher.task.net" | ||||
|     DEFAULT_SEVERITY Debug | ||||
|     DESCRIPTION "task network action" | ||||
|     EXPORT "${Launcher_Name}" | ||||
| ) | ||||
|  | ||||
| ecm_qt_export_logging_category( | ||||
|     IDENTIFIER taskDownloadLogC | ||||
|     CATEGORY_NAME "launcher.task.net.download" | ||||
|     DEFAULT_SEVERITY Debug | ||||
|     DESCRIPTION "task network download actions" | ||||
|     EXPORT "${Launcher_Name}" | ||||
| ) | ||||
| ecm_qt_export_logging_category( | ||||
|     IDENTIFIER taskUploadLogC | ||||
|     CATEGORY_NAME "launcher.task.net.upload" | ||||
|     DEFAULT_SEVERITY Debug | ||||
|     DESCRIPTION "task network upload actions" | ||||
|     EXPORT "${Launcher_Name}" | ||||
| ) | ||||
|  | ||||
| if(KDE_INSTALL_LOGGINGCATEGORIESDIR)  # only install if there is a standard path for this | ||||
|     ecm_qt_install_logging_categories( | ||||
|         EXPORT "${Launcher_Name}" | ||||
|   | ||||
| @@ -294,6 +294,7 @@ void InstanceImportTask::processFlame() | ||||
|     connect(inst_creation_task, &Task::progress, this, &InstanceImportTask::setProgress); | ||||
|     connect(inst_creation_task, &Task::stepProgress, this, &InstanceImportTask::propogateStepProgress); | ||||
|     connect(inst_creation_task, &Task::status, this, &InstanceImportTask::setStatus); | ||||
|     connect(inst_creation_task, &Task::details, this, &InstanceImportTask::setDetails); | ||||
|     connect(inst_creation_task, &Task::finished, inst_creation_task, &InstanceCreationTask::deleteLater); | ||||
|  | ||||
|     connect(this, &Task::aborted, inst_creation_task, &InstanceCreationTask::abort); | ||||
| @@ -386,6 +387,7 @@ void InstanceImportTask::processModrinth() | ||||
|     connect(inst_creation_task, &Task::progress, this, &InstanceImportTask::setProgress); | ||||
|     connect(inst_creation_task, &Task::stepProgress, this, &InstanceImportTask::propogateStepProgress); | ||||
|     connect(inst_creation_task, &Task::status, this, &InstanceImportTask::setStatus); | ||||
|     connect(inst_creation_task, &Task::details, this, &InstanceImportTask::setDetails); | ||||
|     connect(inst_creation_task, &Task::finished, inst_creation_task, &InstanceCreationTask::deleteLater); | ||||
|  | ||||
|     connect(this, &Task::aborted, inst_creation_task, &InstanceCreationTask::abort); | ||||
|   | ||||
| @@ -787,6 +787,7 @@ class InstanceStaging : public Task { | ||||
|         connect(child, &Task::aborted, this, &InstanceStaging::childAborted); | ||||
|         connect(child, &Task::abortStatusChanged, this, &InstanceStaging::setAbortable); | ||||
|         connect(child, &Task::status, this, &InstanceStaging::setStatus); | ||||
|         connect(child, &Task::details, this, &InstanceStaging::setDetails); | ||||
|         connect(child, &Task::progress, this, &InstanceStaging::setProgress); | ||||
|         connect(child, &Task::stepProgress, this, &InstanceStaging::propogateStepProgress); | ||||
|         connect(&m_backoffTimer, &QTimer::timeout, this, &InstanceStaging::childSucceded); | ||||
|   | ||||
| @@ -170,6 +170,7 @@ void JavaListLoadTask::executeTask() | ||||
|     m_job.reset(new JavaCheckerJob("Java detection")); | ||||
|     connect(m_job.get(), &Task::finished, this, &JavaListLoadTask::javaCheckerFinished); | ||||
|     connect(m_job.get(), &Task::progress, this, &Task::setProgress); | ||||
|     // stepProgress? | ||||
|  | ||||
|     qDebug() << "Probing the following Java paths: "; | ||||
|     int id = 0; | ||||
|   | ||||
| @@ -30,6 +30,7 @@ void Update::executeTask() | ||||
|         connect(m_updateTask.get(), &Task::progress, this, &Update::setProgress); | ||||
|         connect(m_updateTask.get(), &Task::stepProgress, this, &Update::propogateStepProgress); | ||||
|         connect(m_updateTask.get(), &Task::status, this, &Update::setStatus); | ||||
|         connect(m_updateTask.get(), &Task::details, this, &Update::setDetails); | ||||
|         emit progressReportingRequest(); | ||||
|         return; | ||||
|     } | ||||
|   | ||||
| @@ -102,6 +102,7 @@ void MinecraftUpdate::next() | ||||
|         disconnect(task.get(), &Task::progress, this, &MinecraftUpdate::progress); | ||||
|         disconnect(task.get(), &Task::stepProgress, this, &MinecraftUpdate::propogateStepProgress); | ||||
|         disconnect(task.get(), &Task::status, this, &MinecraftUpdate::setStatus); | ||||
|         disconnect(task.get(), &Task::details, this, &MinecraftUpdate::setDetails); | ||||
|     } | ||||
|     if(m_currentTask == m_tasks.size()) | ||||
|     { | ||||
| @@ -121,6 +122,7 @@ void MinecraftUpdate::next() | ||||
|     connect(task.get(), &Task::progress, this, &MinecraftUpdate::progress); | ||||
|     connect(task.get(), &Task::stepProgress, this, &MinecraftUpdate::propogateStepProgress); | ||||
|     connect(task.get(), &Task::status, this, &MinecraftUpdate::setStatus); | ||||
|     connect(task.get(), &Task::details, this, &MinecraftUpdate::setDetails); | ||||
|     // if the task is already running, do not start it again | ||||
|     if(!task->isRunning()) | ||||
|     { | ||||
|   | ||||
| @@ -846,7 +846,8 @@ void PackInstallTask::downloadMods() | ||||
|         emitFailed(reason); | ||||
|     }); | ||||
|     connect(jobPtr.get(), &NetJob::progress, [&](qint64 current, qint64 total) | ||||
|     { | ||||
|     {    | ||||
|         setDetails(tr("%1 out of %2 complete").arg(current).arg(total)); | ||||
|         abortable = true; | ||||
|         setProgress(current, total); | ||||
|     }); | ||||
|   | ||||
| @@ -453,7 +453,7 @@ void FlameCreationTask::idResolverSucceeded(QEventLoop& loop) | ||||
|  | ||||
| void FlameCreationTask::setupDownloadJob(QEventLoop& loop) | ||||
| { | ||||
|     m_files_job.reset(new NetJob(tr("Mod download"), APPLICATION->network())); | ||||
|     m_files_job.reset(new NetJob(tr("Mod Download Flame"), APPLICATION->network())); | ||||
|     for (const auto& result : m_mod_id_resolver->getResults().files) { | ||||
|         QString filename = result.fileName; | ||||
|         if (!result.required) { | ||||
| @@ -497,7 +497,10 @@ void FlameCreationTask::setupDownloadJob(QEventLoop& loop) | ||||
|         m_files_job.reset(); | ||||
|         setError(reason); | ||||
|     }); | ||||
|     connect(m_files_job.get(), &NetJob::progress, this, &FlameCreationTask::setProgress); | ||||
|     connect(m_files_job.get(), &NetJob::progress, this, [this](qint64 current, qint64 total){ | ||||
|         setDetails(tr("%1 out of %2 complete").arg(current).arg(total)); | ||||
|         setProgress(current, total); | ||||
|     }); | ||||
|     connect(m_files_job.get(), &NetJob::stepProgress, this, &FlameCreationTask::propogateStepProgress); | ||||
|     connect(m_files_job.get(), &NetJob::finished, &loop, &QEventLoop::quit); | ||||
|  | ||||
|   | ||||
| @@ -224,7 +224,7 @@ bool ModrinthCreationTask::createInstance() | ||||
|     instance.setName(name()); | ||||
|     instance.saveNow(); | ||||
|  | ||||
|     m_files_job.reset(new NetJob(tr("Mod download"), APPLICATION->network())); | ||||
|     m_files_job.reset(new NetJob(tr("Mod Download Modrinth"), APPLICATION->network())); | ||||
|  | ||||
|     auto root_modpack_path = FS::PathCombine(m_stagingPath, ".minecraft"); | ||||
|     auto root_modpack_url = QUrl::fromLocalFile(root_modpack_path); | ||||
| @@ -263,7 +263,10 @@ bool ModrinthCreationTask::createInstance() | ||||
|         setError(reason); | ||||
|     }); | ||||
|     connect(m_files_job.get(), &NetJob::finished, &loop, &QEventLoop::quit); | ||||
|     connect(m_files_job.get(), &NetJob::progress, [&](qint64 current, qint64 total) { setProgress(current, total); }); | ||||
|     connect(m_files_job.get(), &NetJob::progress, [&](qint64 current, qint64 total) {  | ||||
|         setDetails(tr("%1 out of %2 complete").arg(current).arg(total)); | ||||
|         setProgress(current, total);  | ||||
|     }); | ||||
|     connect(m_files_job.get(), &NetJob::stepProgress, this, &ModrinthCreationTask::propogateStepProgress); | ||||
|  | ||||
|     setStatus(tr("Downloading mods...")); | ||||
|   | ||||
| @@ -4,6 +4,7 @@ | ||||
|  *  Copyright (c) 2022 flowln <flowlnlnln@gmail.com> | ||||
|  *  Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net> | ||||
|  *  Copyright (C) 2023 TheKodeToad <TheKodeToad@proton.me> | ||||
|  *  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 | ||||
| @@ -50,7 +51,7 @@ | ||||
| #include "BuildConfig.h" | ||||
| #include "Application.h" | ||||
|  | ||||
| Q_LOGGING_CATEGORY(DownloadLogC, "Task.Net.Download") | ||||
| #include "logging.h" | ||||
|  | ||||
| namespace Net { | ||||
|  | ||||
| @@ -133,7 +134,7 @@ void Download::executeTask() | ||||
|     setStatus(tr("Downloading %1").arg(truncateUrlHumanFriendly(m_url, 100))); | ||||
|  | ||||
|     if (getState() == Task::State::AbortedByUser) { | ||||
|         qCWarning(DownloadLogC) << getUid().toString() << "Attempt to start an aborted Download:" << m_url.toString(); | ||||
|         qCWarning(taskDownloadLogC) << getUid().toString() << "Attempt to start an aborted Download:" << m_url.toString(); | ||||
|         emitAborted(); | ||||
|         return; | ||||
|     } | ||||
| @@ -143,10 +144,10 @@ void Download::executeTask() | ||||
|     switch (m_state) { | ||||
|         case State::Succeeded: | ||||
|             emit succeeded(); | ||||
|             qCDebug(DownloadLogC) << getUid().toString() << "Download cache hit " << m_url.toString(); | ||||
|             qCDebug(taskDownloadLogC) << getUid().toString() << "Download cache hit " << m_url.toString(); | ||||
|             return; | ||||
|         case State::Running: | ||||
|             qCDebug(DownloadLogC) << getUid().toString() << "Downloading " << m_url.toString(); | ||||
|             qCDebug(taskDownloadLogC) << getUid().toString() << "Downloading " << m_url.toString(); | ||||
|             break; | ||||
|         case State::Inactive: | ||||
|         case State::Failed: | ||||
| @@ -192,9 +193,9 @@ void Download::downloadProgress(qint64 bytesReceived, qint64 bytesTotal) | ||||
|     auto elapsed_ms = std::chrono::duration_cast<std::chrono::milliseconds>(elapsed).count(); | ||||
|     auto bytes_recived_since = bytesReceived - m_last_progress_bytes; | ||||
|     if (elapsed_ms > 0) { | ||||
|         m_details = humanReadableFileSize(bytes_recived_since / elapsed_ms * 1000) + "/s"; | ||||
|         setDetails(humanReadableFileSize(bytes_recived_since / elapsed_ms * 1000) + "/s"); | ||||
|     } else { | ||||
|         m_details = "0 b/s"; | ||||
|         setDetails("0 b/s"); | ||||
|     }   | ||||
|  | ||||
|     setProgress(bytesReceived, bytesTotal); | ||||
| @@ -203,7 +204,7 @@ void Download::downloadProgress(qint64 bytesReceived, qint64 bytesTotal) | ||||
| void Download::downloadError(QNetworkReply::NetworkError error) | ||||
| { | ||||
|     if (error == QNetworkReply::OperationCanceledError) { | ||||
|         qCCritical(DownloadLogC) << getUid().toString() << "Aborted " << m_url.toString(); | ||||
|         qCCritical(taskDownloadLogC) << getUid().toString() << "Aborted " << m_url.toString(); | ||||
|         m_state = State::AbortedByUser; | ||||
|     } else { | ||||
|         if (m_options & Option::AcceptLocalFiles) { | ||||
| @@ -213,7 +214,7 @@ void Download::downloadError(QNetworkReply::NetworkError error) | ||||
|             } | ||||
|         } | ||||
|         // error happened during download. | ||||
|         qCCritical(DownloadLogC) << getUid().toString() << "Failed " << m_url.toString() << " with reason " << error; | ||||
|         qCCritical(taskDownloadLogC) << getUid().toString() << "Failed " << m_url.toString() << " with reason " << error; | ||||
|         m_state = State::Failed; | ||||
|     } | ||||
| } | ||||
| @@ -222,9 +223,9 @@ void Download::sslErrors(const QList<QSslError>& errors) | ||||
| { | ||||
|     int i = 1; | ||||
|     for (auto error : errors) { | ||||
|         qCCritical(DownloadLogC) << getUid().toString() << "Download" << m_url.toString() << "SSL Error #" << i << " : " << error.errorString(); | ||||
|         qCCritical(taskDownloadLogC) << getUid().toString() << "Download" << m_url.toString() << "SSL Error #" << i << " : " << error.errorString(); | ||||
|         auto cert = error.certificate(); | ||||
|         qCCritical(DownloadLogC) << getUid().toString() << "Certificate in question:\n" << cert.toText(); | ||||
|         qCCritical(taskDownloadLogC) << getUid().toString() << "Certificate in question:\n" << cert.toText(); | ||||
|         i++; | ||||
|     } | ||||
| } | ||||
| @@ -267,17 +268,17 @@ auto Download::handleRedirect() -> bool | ||||
|          */ | ||||
|         redirect = QUrl(redirectStr, QUrl::TolerantMode); | ||||
|         if (!redirect.isValid()) { | ||||
|             qCWarning(DownloadLogC) << getUid().toString() << "Failed to parse redirect URL:" << redirectStr; | ||||
|             qCWarning(taskDownloadLogC) << getUid().toString() << "Failed to parse redirect URL:" << redirectStr; | ||||
|             downloadError(QNetworkReply::ProtocolFailure); | ||||
|             return false; | ||||
|         } | ||||
|         qCDebug(DownloadLogC) << getUid().toString() << "Fixed location header:" << redirect; | ||||
|         qCDebug(taskDownloadLogC) << getUid().toString() << "Fixed location header:" << redirect; | ||||
|     } else { | ||||
|         qCDebug(DownloadLogC) << getUid().toString() << "Location header:" << redirect; | ||||
|         qCDebug(taskDownloadLogC) << getUid().toString() << "Location header:" << redirect; | ||||
|     } | ||||
|  | ||||
|     m_url = QUrl(redirect.toString()); | ||||
|     qCDebug(DownloadLogC) << getUid().toString() << "Following redirect to " << m_url.toString(); | ||||
|     qCDebug(taskDownloadLogC) << getUid().toString() << "Following redirect to " << m_url.toString(); | ||||
|     startAction(m_network); | ||||
|  | ||||
|     return true; | ||||
| @@ -287,26 +288,26 @@ void Download::downloadFinished() | ||||
| { | ||||
|     // handle HTTP redirection first | ||||
|     if (handleRedirect()) { | ||||
|         qCDebug(DownloadLogC) << getUid().toString() << "Download redirected:" << m_url.toString(); | ||||
|         qCDebug(taskDownloadLogC) << getUid().toString() << "Download redirected:" << m_url.toString(); | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     // if the download failed before this point ... | ||||
|     if (m_state == State::Succeeded)  // pretend to succeed so we continue processing :) | ||||
|     { | ||||
|         qCDebug(DownloadLogC) << getUid().toString() << "Download failed but we are allowed to proceed:" << m_url.toString(); | ||||
|         qCDebug(taskDownloadLogC) << getUid().toString() << "Download failed but we are allowed to proceed:" << m_url.toString(); | ||||
|         m_sink->abort(); | ||||
|         m_reply.reset(); | ||||
|         emit succeeded(); | ||||
|         return; | ||||
|     } else if (m_state == State::Failed) { | ||||
|         qCDebug(DownloadLogC) << getUid().toString() << "Download failed in previous step:" << m_url.toString(); | ||||
|         qCDebug(taskDownloadLogC) << getUid().toString() << "Download failed in previous step:" << m_url.toString(); | ||||
|         m_sink->abort(); | ||||
|         m_reply.reset(); | ||||
|         emit failed(""); | ||||
|         return; | ||||
|     } else if (m_state == State::AbortedByUser) { | ||||
|         qCDebug(DownloadLogC) << getUid().toString() << "Download aborted in previous step:" << m_url.toString(); | ||||
|         qCDebug(taskDownloadLogC) << getUid().toString() << "Download aborted in previous step:" << m_url.toString(); | ||||
|         m_sink->abort(); | ||||
|         m_reply.reset(); | ||||
|         emit aborted(); | ||||
| @@ -316,14 +317,14 @@ void Download::downloadFinished() | ||||
|     // make sure we got all the remaining data, if any | ||||
|     auto data = m_reply->readAll(); | ||||
|     if (data.size()) { | ||||
|         qCDebug(DownloadLogC) << getUid().toString() << "Writing extra" << data.size() << "bytes"; | ||||
|         qCDebug(taskDownloadLogC) << getUid().toString() << "Writing extra" << data.size() << "bytes"; | ||||
|         m_state = m_sink->write(data); | ||||
|     } | ||||
|  | ||||
|     // otherwise, finalize the whole graph | ||||
|     m_state = m_sink->finalize(*m_reply.get()); | ||||
|     if (m_state != State::Succeeded) { | ||||
|         qCDebug(DownloadLogC) << getUid().toString() << "Download failed to finalize:" << m_url.toString(); | ||||
|         qCDebug(taskDownloadLogC) << getUid().toString() << "Download failed to finalize:" << m_url.toString(); | ||||
|         m_sink->abort(); | ||||
|         m_reply.reset(); | ||||
|         emit failed(""); | ||||
| @@ -331,7 +332,7 @@ void Download::downloadFinished() | ||||
|     } | ||||
|  | ||||
|     m_reply.reset(); | ||||
|     qCDebug(DownloadLogC) << getUid().toString() << "Download succeeded:" << m_url.toString(); | ||||
|     qCDebug(taskDownloadLogC) << getUid().toString() << "Download succeeded:" << m_url.toString(); | ||||
|     emit succeeded(); | ||||
| } | ||||
|  | ||||
| @@ -341,11 +342,11 @@ void Download::downloadReadyRead() | ||||
|         auto data = m_reply->readAll(); | ||||
|         m_state = m_sink->write(data); | ||||
|         if (m_state == State::Failed) { | ||||
|             qCCritical(DownloadLogC) << getUid().toString() << "Failed to process response chunk"; | ||||
|             qCCritical(taskDownloadLogC) << getUid().toString() << "Failed to process response chunk"; | ||||
|         } | ||||
|         // qDebug() << "Download" << m_url.toString() << "gained" << data.size() << "bytes"; | ||||
|     } else { | ||||
|         qCCritical(DownloadLogC) << getUid().toString() << "Cannot write download data! illegal status " << m_status; | ||||
|         qCCritical(taskDownloadLogC) << getUid().toString() << "Cannot write download data! illegal status " << m_status; | ||||
|     } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -66,7 +66,6 @@ class Download : public NetAction { | ||||
|     void addValidator(Validator* v); | ||||
|     auto abort() -> bool override; | ||||
|     auto canAbort() const -> bool override { return true; }; | ||||
|     auto getDetails() const -> QString override {return m_details; }; | ||||
|  | ||||
|    private: | ||||
|     auto handleRedirect() -> bool; | ||||
| @@ -88,8 +87,6 @@ class Download : public NetAction { | ||||
|     std::chrono::steady_clock m_clock; | ||||
|     std::chrono::time_point<std::chrono::steady_clock> m_last_progress_time; | ||||
|     qint64 m_last_progress_bytes; | ||||
|  | ||||
|     QString m_details; | ||||
| }; | ||||
| }  // namespace Net | ||||
|  | ||||
|   | ||||
| @@ -37,6 +37,8 @@ | ||||
|  | ||||
| #include "FileSystem.h" | ||||
|  | ||||
| #include "logging.h" | ||||
|  | ||||
| namespace Net { | ||||
|  | ||||
| Task::State FileSink::init(QNetworkRequest& request) | ||||
| @@ -48,14 +50,14 @@ Task::State FileSink::init(QNetworkRequest& request) | ||||
|  | ||||
|     // create a new save file and open it for writing | ||||
|     if (!FS::ensureFilePathExists(m_filename)) { | ||||
|         qCritical() << "Could not create folder for " + m_filename; | ||||
|         qCCritical(taskNetLogC) << "Could not create folder for " + m_filename; | ||||
|         return Task::State::Failed; | ||||
|     } | ||||
|  | ||||
|     wroteAnyData = false; | ||||
|     m_output_file.reset(new QSaveFile(m_filename)); | ||||
|     if (!m_output_file->open(QIODevice::WriteOnly)) { | ||||
|         qCritical() << "Could not open " + m_filename + " for writing"; | ||||
|         qCCritical(taskNetLogC) << "Could not open " + m_filename + " for writing"; | ||||
|         return Task::State::Failed; | ||||
|     } | ||||
|  | ||||
| @@ -67,7 +69,7 @@ Task::State FileSink::init(QNetworkRequest& request) | ||||
| Task::State FileSink::write(QByteArray& data) | ||||
| { | ||||
|     if (!writeAllValidators(data) || m_output_file->write(data) != data.size()) { | ||||
|         qCritical() << "Failed writing into " + m_filename; | ||||
|         qCCritical(taskNetLogC) << "Failed writing into " + m_filename; | ||||
|         m_output_file->cancelWriting(); | ||||
|         m_output_file.reset(); | ||||
|         wroteAnyData = false; | ||||
| @@ -106,7 +108,7 @@ Task::State FileSink::finalize(QNetworkReply& reply) | ||||
|  | ||||
|         // nothing went wrong... | ||||
|         if (!m_output_file->commit()) { | ||||
|             qCritical() << "Failed to commit changes to " << m_filename; | ||||
|             qCCritical(taskNetLogC) << "Failed to commit changes to " << m_filename; | ||||
|             m_output_file->cancelWriting(); | ||||
|             return Task::State::Failed; | ||||
|         } | ||||
|   | ||||
| @@ -44,6 +44,8 @@ | ||||
|  | ||||
| #include <QDebug> | ||||
|  | ||||
| #include "logging.h" | ||||
|  | ||||
| auto MetaEntry::getFullPath() -> QString | ||||
| { | ||||
|     // FIXME: make local? | ||||
| @@ -124,7 +126,7 @@ auto HttpMetaCache::resolveEntry(QString base, QString resource_path, QString ex | ||||
|     // Get rid of old entries, to prevent cache problems | ||||
|     auto current_time = QDateTime::currentSecsSinceEpoch(); | ||||
|     if (entry->isExpired(current_time - ( file_last_changed / 1000 ))) { | ||||
|         qWarning() << "Removing cache entry because of old age!"; | ||||
|         qCWarning(taskNetLogC) << "[HttpMetaCache]" << "Removing cache entry because of old age!"; | ||||
|         selected_base.entry_list.remove(resource_path); | ||||
|         return staleEntry(base, resource_path); | ||||
|     } | ||||
| @@ -137,12 +139,12 @@ auto HttpMetaCache::resolveEntry(QString base, QString resource_path, QString ex | ||||
| auto HttpMetaCache::updateEntry(MetaEntryPtr stale_entry) -> bool | ||||
| { | ||||
|     if (!m_entries.contains(stale_entry->m_baseId)) { | ||||
|         qCritical() << "Cannot add entry with unknown base: " << stale_entry->m_baseId.toLocal8Bit(); | ||||
|         qCCritical(taskNetLogC) << "[HttpMetaCache]" << "Cannot add entry with unknown base: " << stale_entry->m_baseId.toLocal8Bit(); | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     if (stale_entry->m_stale) { | ||||
|         qCritical() << "Cannot add stale entry: " << stale_entry->getFullPath().toLocal8Bit(); | ||||
|         qCCritical(taskNetLogC) << "[HttpMetaCache]" << "Cannot add stale entry: " << stale_entry->getFullPath().toLocal8Bit(); | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
| @@ -166,10 +168,10 @@ void HttpMetaCache::evictAll() | ||||
| { | ||||
|     for (QString& base : m_entries.keys()) { | ||||
|         EntryMap& map = m_entries[base]; | ||||
|         qDebug() << "Evicting base" << base; | ||||
|         qCDebug(taskNetLogC) << "[HttpMetaCache]" << "Evicting base" << base; | ||||
|         for (MetaEntryPtr entry : map.entry_list) { | ||||
|             if (!evictEntry(entry)) | ||||
|                 qWarning() << "Unexpected missing cache entry" << entry->m_basePath; | ||||
|                 qCWarning(taskNetLogC) << "[HttpMetaCache]" << "Unexpected missing cache entry" << entry->m_basePath; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -267,7 +269,7 @@ void HttpMetaCache::SaveNow() | ||||
|     if (m_index_file.isNull()) | ||||
|         return; | ||||
|  | ||||
|     qDebug() << "[HttpMetaCache]" << "Saving metacache with" << m_entries.size() << "entries"; | ||||
|     qCDebug(taskNetLogC) << "[HttpMetaCache]" << "Saving metacache with" << m_entries.size() << "entries"; | ||||
|  | ||||
|     QJsonObject toplevel; | ||||
|     Json::writeString(toplevel, "version", "1"); | ||||
| @@ -302,6 +304,6 @@ void HttpMetaCache::SaveNow() | ||||
|     try { | ||||
|         Json::write(toplevel, m_index_file); | ||||
|     } catch (const Exception& e) { | ||||
|         qWarning() << e.what(); | ||||
|         qCWarning(taskNetLogC) << "[HttpMetaCache]" << e.what(); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -39,6 +39,8 @@ | ||||
| #include <QRegularExpression> | ||||
| #include "Application.h" | ||||
|  | ||||
| #include "logging.h" | ||||
|  | ||||
| namespace Net { | ||||
|  | ||||
| /** Maximum time to hold a cache entry | ||||
| @@ -97,11 +99,11 @@ Task::State MetaCacheSink::finalizeCache(QNetworkReply & reply) | ||||
|  | ||||
|     { // Cache lifetime | ||||
|         if (m_is_eternal) { | ||||
|             qDebug() << "[MetaCache] Adding eternal cache entry:" << m_entry->getFullPath(); | ||||
|             qCDebug(taskNetLogC) << "[MetaCache] Adding eternal cache entry:" << m_entry->getFullPath(); | ||||
|             m_entry->makeEternal(true); | ||||
|         } else if (reply.hasRawHeader("Cache-Control")) { | ||||
|             auto cache_control_header = reply.rawHeader("Cache-Control"); | ||||
|             // qDebug() << "[MetaCache] Parsing 'Cache-Control' header with" << cache_control_header; | ||||
|             // qCDebug(taskNetLogC) << "[MetaCache] Parsing 'Cache-Control' header with" << cache_control_header; | ||||
|  | ||||
|             QRegularExpression max_age_expr("max-age=([0-9]+)"); | ||||
|             qint64 max_age = max_age_expr.match(cache_control_header).captured(1).toLongLong(); | ||||
| @@ -109,7 +111,7 @@ Task::State MetaCacheSink::finalizeCache(QNetworkReply & reply) | ||||
|  | ||||
|         } else if (reply.hasRawHeader("Expires")) { | ||||
|             auto expires_header = reply.rawHeader("Expires"); | ||||
|             // qDebug() << "[MetaCache] Parsing 'Expires' header with" << expires_header; | ||||
|             // qCDebug(taskNetLogC) << "[MetaCache] Parsing 'Expires' header with" << expires_header; | ||||
|  | ||||
|             qint64 max_age = QDateTime::fromString(expires_header).toSecsSinceEpoch() - QDateTime::currentSecsSinceEpoch(); | ||||
|             m_entry->setMaximumAge(max_age); | ||||
| @@ -119,7 +121,7 @@ Task::State MetaCacheSink::finalizeCache(QNetworkReply & reply) | ||||
|  | ||||
|         if (reply.hasRawHeader("Age")) { | ||||
|             auto age_header = reply.rawHeader("Age"); | ||||
|             // qDebug() << "[MetaCache] Parsing 'Age' header with" << age_header; | ||||
|             // qCDebug(taskNetLogC) << "[MetaCache] Parsing 'Age' header with" << age_header; | ||||
|  | ||||
|             qint64 current_age = age_header.toLongLong(); | ||||
|             m_entry->setCurrentAge(current_age); | ||||
|   | ||||
| @@ -47,6 +47,8 @@ | ||||
| #include <QFile> | ||||
| #include <QUrlQuery> | ||||
|  | ||||
| #include "logging.h" | ||||
|  | ||||
| std::array<PasteUpload::PasteTypeInfo, 4> PasteUpload::PasteTypes = { | ||||
|     {{"0x0.st", "https://0x0.st", ""}, | ||||
|      {"hastebin", "https://hst.sh", "/documents"}, | ||||
| @@ -147,7 +149,7 @@ void PasteUpload::executeTask() | ||||
| void PasteUpload::downloadError(QNetworkReply::NetworkError error) | ||||
| { | ||||
|     // error happened during download. | ||||
|     qCritical() << "Network error: " << error; | ||||
|     qCCritical(taskUploadLogC) << "Network error: " << error; | ||||
|     emitFailed(m_reply->errorString()); | ||||
| } | ||||
|  | ||||
| @@ -166,7 +168,7 @@ void PasteUpload::downloadFinished() | ||||
|     { | ||||
|         QString reasonPhrase = m_reply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString(); | ||||
|         emitFailed(tr("Error: %1 returned unexpected status code %2 %3").arg(m_uploadUrl).arg(statusCode).arg(reasonPhrase)); | ||||
|         qCritical() << m_uploadUrl << " returned unexpected status code " << statusCode << " with body: " << data; | ||||
|         qCCritical(taskUploadLogC) << m_uploadUrl << " returned unexpected status code " << statusCode << " with body: " << data; | ||||
|         m_reply.reset(); | ||||
|         return; | ||||
|     } | ||||
| @@ -187,7 +189,7 @@ void PasteUpload::downloadFinished() | ||||
|         else | ||||
|         { | ||||
|             emitFailed(tr("Error: %1 returned a malformed response body").arg(m_uploadUrl)); | ||||
|             qCritical() << m_uploadUrl << " returned malformed response body: " << data; | ||||
|             qCCritical(taskUploadLogC) << m_uploadUrl << " returned malformed response body: " << data; | ||||
|             return; | ||||
|         } | ||||
|         break; | ||||
| @@ -206,15 +208,15 @@ void PasteUpload::downloadFinished() | ||||
|             { | ||||
|                 QString error = jsonObj["error"].toString(); | ||||
|                 emitFailed(tr("Error: %1 returned an error: %2").arg(m_uploadUrl, error)); | ||||
|                 qCritical() << m_uploadUrl << " returned error: " << error; | ||||
|                 qCritical() << "Response body: " << data; | ||||
|                 qCCritical(taskUploadLogC) << m_uploadUrl << " returned error: " << error; | ||||
|                 qCCritical(taskUploadLogC) << "Response body: " << data; | ||||
|                 return; | ||||
|             } | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             emitFailed(tr("Error: %1 returned a malformed response body").arg(m_uploadUrl)); | ||||
|             qCritical() << m_uploadUrl << " returned malformed response body: " << data; | ||||
|             qCCritical(taskUploadLogC) << m_uploadUrl << " returned malformed response body: " << data; | ||||
|             return; | ||||
|         } | ||||
|         break; | ||||
| @@ -234,16 +236,16 @@ void PasteUpload::downloadFinished() | ||||
|                 QString error = jsonObj["error"].toString(); | ||||
|                 QString message = (jsonObj.contains("message") && jsonObj["message"].isString()) ? jsonObj["message"].toString() : "none"; | ||||
|                 emitFailed(tr("Error: %1 returned an error code: %2\nError message: %3").arg(m_uploadUrl, error, message)); | ||||
|                 qCritical() << m_uploadUrl << " returned error: " << error; | ||||
|                 qCritical() << "Error message: " << message; | ||||
|                 qCritical() << "Response body: " << data; | ||||
|                 qCCritical(taskUploadLogC) << m_uploadUrl << " returned error: " << error; | ||||
|                 qCCritical(taskUploadLogC) << "Error message: " << message; | ||||
|                 qCCritical(taskUploadLogC) << "Response body: " << data; | ||||
|                 return; | ||||
|             } | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             emitFailed(tr("Error: %1 returned a malformed response body").arg(m_uploadUrl)); | ||||
|             qCritical() << m_uploadUrl << " returned malformed response body: " << data; | ||||
|             qCCritical(taskUploadLogC) << m_uploadUrl << " returned malformed response body: " << data; | ||||
|             return; | ||||
|         } | ||||
|         break; | ||||
|   | ||||
| @@ -42,6 +42,8 @@ | ||||
| #include "BuildConfig.h" | ||||
| #include "Application.h" | ||||
|  | ||||
| #include "logging.h" | ||||
|  | ||||
| namespace Net { | ||||
|  | ||||
|     bool Upload::abort() | ||||
| @@ -60,11 +62,11 @@ namespace Net { | ||||
|  | ||||
|     void Upload::downloadError(QNetworkReply::NetworkError error) { | ||||
|         if (error == QNetworkReply::OperationCanceledError) { | ||||
|             qCritical() << "Aborted " << m_url.toString(); | ||||
|             qCCritical(taskUploadLogC) << "Aborted " << m_url.toString(); | ||||
|             m_state = State::AbortedByUser; | ||||
|         } else { | ||||
|             // error happened during download. | ||||
|             qCritical() << "Failed " << m_url.toString() << " with reason " << error; | ||||
|             qCCritical(taskUploadLogC) << "Failed " << m_url.toString() << " with reason " << error; | ||||
|             m_state = State::Failed; | ||||
|         } | ||||
|     } | ||||
| @@ -72,9 +74,9 @@ namespace Net { | ||||
|     void Upload::sslErrors(const QList<QSslError> &errors) { | ||||
|         int i = 1; | ||||
|         for (const auto& error : errors) { | ||||
|             qCritical() << "Upload" << m_url.toString() << "SSL Error #" << i << " : " << error.errorString(); | ||||
|             qCCritical(taskUploadLogC) << "Upload" << m_url.toString() << "SSL Error #" << i << " : " << error.errorString(); | ||||
|             auto cert = error.certificate(); | ||||
|             qCritical() << "Certificate in question:\n" << cert.toText(); | ||||
|             qCCritical(taskUploadLogC) << "Certificate in question:\n" << cert.toText(); | ||||
|             i++; | ||||
|         } | ||||
|     } | ||||
| @@ -117,17 +119,17 @@ namespace Net { | ||||
|              */ | ||||
|             redirect = QUrl(redirectStr, QUrl::TolerantMode); | ||||
|             if (!redirect.isValid()) { | ||||
|                 qWarning() << "Failed to parse redirect URL:" << redirectStr; | ||||
|                 qCWarning(taskUploadLogC) << "Failed to parse redirect URL:" << redirectStr; | ||||
|                 downloadError(QNetworkReply::ProtocolFailure); | ||||
|                 return false; | ||||
|             } | ||||
|             qDebug() << "Fixed location header:" << redirect; | ||||
|             qCDebug(taskUploadLogC) << "Fixed location header:" << redirect; | ||||
|         } else { | ||||
|             qDebug() << "Location header:" << redirect; | ||||
|             qCDebug(taskUploadLogC) << "Location header:" << redirect; | ||||
|         } | ||||
|  | ||||
|         m_url = QUrl(redirect.toString()); | ||||
|         qDebug() << "Following redirect to " << m_url.toString(); | ||||
|         qCDebug(taskUploadLogC) << "Following redirect to " << m_url.toString(); | ||||
|         startAction(m_network); | ||||
|         return true; | ||||
|     } | ||||
| @@ -136,25 +138,25 @@ namespace Net { | ||||
|         // handle HTTP redirection first | ||||
|         // very unlikely for post requests, still can happen | ||||
|         if (handleRedirect()) { | ||||
|             qDebug() << "Upload redirected:" << m_url.toString(); | ||||
|             qCDebug(taskUploadLogC) << "Upload redirected:" << m_url.toString(); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         // if the download failed before this point ... | ||||
|         if (m_state == State::Succeeded) { | ||||
|             qDebug() << "Upload failed but we are allowed to proceed:" << m_url.toString(); | ||||
|             qCDebug(taskUploadLogC) << "Upload failed but we are allowed to proceed:" << m_url.toString(); | ||||
|             m_sink->abort(); | ||||
|             m_reply.reset(); | ||||
|             emit succeeded(); | ||||
|             return; | ||||
|         } else if (m_state == State::Failed) { | ||||
|             qDebug() << "Upload failed in previous step:" << m_url.toString(); | ||||
|             qCDebug(taskUploadLogC) << "Upload failed in previous step:" << m_url.toString(); | ||||
|             m_sink->abort(); | ||||
|             m_reply.reset(); | ||||
|             emit failed(""); | ||||
|             return; | ||||
|         } else if (m_state == State::AbortedByUser) { | ||||
|             qDebug() << "Upload aborted in previous step:" << m_url.toString(); | ||||
|             qCDebug(taskUploadLogC) << "Upload aborted in previous step:" << m_url.toString(); | ||||
|             m_sink->abort(); | ||||
|             m_reply.reset(); | ||||
|             emit aborted(); | ||||
| @@ -164,21 +166,21 @@ namespace Net { | ||||
|         // make sure we got all the remaining data, if any | ||||
|         auto data = m_reply->readAll(); | ||||
|         if (data.size()) { | ||||
|             qDebug() << "Writing extra" << data.size() << "bytes"; | ||||
|             qCDebug(taskUploadLogC) << "Writing extra" << data.size() << "bytes"; | ||||
|             m_state = m_sink->write(data); | ||||
|         } | ||||
|  | ||||
|         // otherwise, finalize the whole graph | ||||
|         m_state = m_sink->finalize(*m_reply.get()); | ||||
|         if (m_state != State::Succeeded) { | ||||
|             qDebug() << "Upload failed to finalize:" << m_url.toString(); | ||||
|             qCDebug(taskUploadLogC) << "Upload failed to finalize:" << m_url.toString(); | ||||
|             m_sink->abort(); | ||||
|             m_reply.reset(); | ||||
|             emit failed(""); | ||||
|             return; | ||||
|         } | ||||
|         m_reply.reset(); | ||||
|         qDebug() << "Upload succeeded:" << m_url.toString(); | ||||
|         qCDebug(taskUploadLogC) << "Upload succeeded:" << m_url.toString(); | ||||
|         emit succeeded(); | ||||
|     } | ||||
|  | ||||
| @@ -193,7 +195,7 @@ namespace Net { | ||||
|         setStatus(tr("Uploading %1").arg(m_url.toString())); | ||||
|  | ||||
|         if (m_state == State::AbortedByUser) { | ||||
|             qWarning() << "Attempt to start an aborted Upload:" << m_url.toString(); | ||||
|             qCWarning(taskUploadLogC) << "Attempt to start an aborted Upload:" << m_url.toString(); | ||||
|             emit aborted(); | ||||
|             return; | ||||
|         } | ||||
| @@ -202,10 +204,10 @@ namespace Net { | ||||
|         switch (m_state) { | ||||
|             case State::Succeeded: | ||||
|                 emitSucceeded(); | ||||
|                 qDebug() << "Upload cache hit " << m_url.toString(); | ||||
|                 qCDebug(taskUploadLogC) << "Upload cache hit " << m_url.toString(); | ||||
|                 return; | ||||
|             case State::Running: | ||||
|                 qDebug() << "Uploading " << m_url.toString(); | ||||
|                 qCDebug(taskUploadLogC) << "Uploading " << m_url.toString(); | ||||
|                 break; | ||||
|             case State::Inactive: | ||||
|             case State::Failed: | ||||
|   | ||||
							
								
								
									
										24
									
								
								launcher/net/logging.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								launcher/net/logging.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,24 @@ | ||||
| // SPDX-License-Identifier: GPL-3.0-only | ||||
| /* | ||||
|  *  Prism Launcher - Minecraft Launcher | ||||
|  *  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/>. | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #include "logging.h" | ||||
|  | ||||
| Q_LOGGING_CATEGORY(taskNetLogC, "launcher.task.net") | ||||
| Q_LOGGING_CATEGORY(taskDownloadLogC, "launcher.task.net.download") | ||||
| Q_LOGGING_CATEGORY(taskUploadLogC, "launcher.task.net.upload") | ||||
							
								
								
									
										26
									
								
								launcher/net/logging.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								launcher/net/logging.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | ||||
| // SPDX-License-Identifier: GPL-3.0-only | ||||
| /* | ||||
|  *  Prism Launcher - Minecraft Launcher | ||||
|  *  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/>. | ||||
|  * | ||||
|  */ | ||||
|   | ||||
| #pragma  once | ||||
|  | ||||
| #include <QLoggingCategory> | ||||
|  | ||||
| Q_DECLARE_LOGGING_CATEGORY(taskNetLogC) | ||||
| Q_DECLARE_LOGGING_CATEGORY(taskDownloadLogC) | ||||
| Q_DECLARE_LOGGING_CATEGORY(taskUploadLogC) | ||||
| @@ -95,6 +95,7 @@ void ConcurrentTask::startNext() | ||||
|     connect(next.get(), &Task::failed, this, [this, next](QString msg) { subTaskFailed(next, msg); }); | ||||
|  | ||||
|     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](TaskStepProgressList tp){ subTaskStepProgress(next, tp); }); | ||||
|  | ||||
|     connect(next.get(), &Task::progress, this, [this, next](qint64 current, qint64 total){ subTaskProgress(next, current, total); }); | ||||
| @@ -151,7 +152,14 @@ void ConcurrentTask::subTaskStatus(Task::Ptr task, const QString& msg) | ||||
|     auto taskProgress = m_task_progress.value(task->getUid()); | ||||
|     taskProgress->status = msg;  | ||||
|     taskProgress->state = TaskStepState::Running; | ||||
|     updateState(); | ||||
|     updateStepProgress(); | ||||
| } | ||||
|  | ||||
| void ConcurrentTask::subTaskDetails(Task::Ptr task, const QString& msg) | ||||
| { | ||||
|     auto taskProgress = m_task_progress.value(task->getUid()); | ||||
|     taskProgress->details = msg;  | ||||
|     taskProgress->state = TaskStepState::Running; | ||||
|     updateStepProgress(); | ||||
| } | ||||
|  | ||||
| @@ -162,7 +170,6 @@ void ConcurrentTask::subTaskProgress(Task::Ptr task, qint64 current, qint64 tota | ||||
|     taskProgress->current = current; | ||||
|     taskProgress->total = total; | ||||
|     taskProgress->state = TaskStepState::Running; | ||||
|     taskProgress->details = task->getDetails();  | ||||
|  | ||||
|     updateStepProgress(); | ||||
|     updateState(); | ||||
|   | ||||
| @@ -40,6 +40,7 @@ slots: | ||||
|     void subTaskSucceeded(Task::Ptr); | ||||
|     void subTaskFailed(Task::Ptr, const QString &msg); | ||||
|     void subTaskStatus(Task::Ptr task, const QString &msg); | ||||
|     void subTaskDetails(Task::Ptr task, const QString &msg); | ||||
|     void subTaskProgress(Task::Ptr task, qint64 current, qint64 total); | ||||
|     void subTaskStepProgress(Task::Ptr task, TaskStepProgressList task_step_progress); | ||||
|  | ||||
|   | ||||
| @@ -37,7 +37,7 @@ | ||||
|  | ||||
| #include <QDebug> | ||||
|  | ||||
| Q_LOGGING_CATEGORY(TaskLogC, "Task") | ||||
| Q_LOGGING_CATEGORY(taskLogC, "launcher.task") | ||||
|  | ||||
| Task::Task(QObject *parent, bool show_debug) : QObject(parent), m_show_debug(show_debug) | ||||
| { | ||||
| @@ -54,11 +54,23 @@ void Task::setStatus(const QString &new_status) | ||||
|     } | ||||
| } | ||||
|  | ||||
| void Task::setDetails(const QString& new_details) | ||||
| { | ||||
|     if (m_details != new_details) | ||||
|     { | ||||
|         m_details = new_details; | ||||
|         emit details(m_details); | ||||
|     } | ||||
| } | ||||
|  | ||||
| void Task::setProgress(qint64 current, qint64 total) | ||||
| { | ||||
|     m_progress = current; | ||||
|     m_progressTotal = total; | ||||
|     emit progress(m_progress, m_progressTotal); | ||||
|     if ((m_progress != current) || (m_progressTotal != total)) { | ||||
|         m_progress = current; | ||||
|         m_progressTotal = total; | ||||
|          | ||||
|         emit progress(m_progress, m_progressTotal); | ||||
|     }  | ||||
| } | ||||
|  | ||||
| void Task::start() | ||||
| @@ -68,31 +80,31 @@ void Task::start() | ||||
|         case State::Inactive: | ||||
|         { | ||||
|             if (m_show_debug) | ||||
|                 qCDebug(TaskLogC) << "Task" << describe() << "starting for the first time"; | ||||
|                 qCDebug(taskLogC) << "Task" << describe() << "starting for the first time"; | ||||
|             break; | ||||
|         } | ||||
|         case State::AbortedByUser: | ||||
|         { | ||||
|             if (m_show_debug) | ||||
|                 qCDebug(TaskLogC) << "Task" << describe() << "restarting for after being aborted by user"; | ||||
|                 qCDebug(taskLogC) << "Task" << describe() << "restarting for after being aborted by user"; | ||||
|             break; | ||||
|         } | ||||
|         case State::Failed: | ||||
|         { | ||||
|             if (m_show_debug) | ||||
|                 qCDebug(TaskLogC) << "Task" << describe() << "restarting for after failing at first"; | ||||
|                 qCDebug(taskLogC) << "Task" << describe() << "restarting for after failing at first"; | ||||
|             break; | ||||
|         } | ||||
|         case State::Succeeded: | ||||
|         { | ||||
|             if (m_show_debug) | ||||
|                 qCDebug(TaskLogC) << "Task" << describe() << "restarting for after succeeding at first"; | ||||
|                 qCDebug(taskLogC) << "Task" << describe() << "restarting for after succeeding at first"; | ||||
|             break; | ||||
|         } | ||||
|         case State::Running: | ||||
|         { | ||||
|             if (m_show_debug) | ||||
|                 qCWarning(TaskLogC) << "The launcher tried to start task" << describe() << "while it was already running!"; | ||||
|                 qCWarning(taskLogC) << "The launcher tried to start task" << describe() << "while it was already running!"; | ||||
|             return; | ||||
|         } | ||||
|     } | ||||
| @@ -107,12 +119,12 @@ void Task::emitFailed(QString reason) | ||||
|     // Don't fail twice. | ||||
|     if (!isRunning()) | ||||
|     { | ||||
|         qCCritical(TaskLogC) << "Task" << describe() << "failed while not running!!!!: " << reason; | ||||
|         qCCritical(taskLogC) << "Task" << describe() << "failed while not running!!!!: " << reason; | ||||
|         return; | ||||
|     } | ||||
|     m_state = State::Failed; | ||||
|     m_failReason = reason; | ||||
|     qCCritical(TaskLogC) << "Task" << describe() << "failed: " << reason; | ||||
|     qCCritical(taskLogC) << "Task" << describe() << "failed: " << reason; | ||||
|     emit failed(reason); | ||||
|     emit finished(); | ||||
| } | ||||
| @@ -122,13 +134,13 @@ void Task::emitAborted() | ||||
|     // Don't abort twice. | ||||
|     if (!isRunning()) | ||||
|     { | ||||
|         qCCritical(TaskLogC) << "Task" << describe() << "aborted while not running!!!!"; | ||||
|         qCCritical(taskLogC) << "Task" << describe() << "aborted while not running!!!!"; | ||||
|         return; | ||||
|     } | ||||
|     m_state = State::AbortedByUser; | ||||
|     m_failReason = "Aborted."; | ||||
|     if (m_show_debug) | ||||
|         qCDebug(TaskLogC) << "Task" << describe() << "aborted."; | ||||
|         qCDebug(taskLogC) << "Task" << describe() << "aborted."; | ||||
|     emit aborted(); | ||||
|     emit finished(); | ||||
| } | ||||
| @@ -138,12 +150,12 @@ void Task::emitSucceeded() | ||||
|     // Don't succeed twice. | ||||
|     if (!isRunning()) | ||||
|     { | ||||
|         qCCritical(TaskLogC) << "Task" << describe() << "succeeded while not running!!!!"; | ||||
|         qCCritical(taskLogC) << "Task" << describe() << "succeeded while not running!!!!"; | ||||
|         return; | ||||
|     } | ||||
|     m_state = State::Succeeded; | ||||
|     if (m_show_debug) | ||||
|         qCDebug(TaskLogC) << "Task" << describe() << "succeeded"; | ||||
|         qCDebug(taskLogC) << "Task" << describe() << "succeeded"; | ||||
|     emit succeeded(); | ||||
|     emit finished(); | ||||
| } | ||||
|   | ||||
| @@ -42,6 +42,8 @@ | ||||
|  | ||||
| #include "QObjectPtr.h" | ||||
|  | ||||
| Q_DECLARE_LOGGING_CATEGORY(taskLogC) | ||||
|  | ||||
| enum class TaskStepState { | ||||
|     Waiting, | ||||
|     Running, | ||||
| @@ -100,12 +102,13 @@ class Task : public QObject, public QRunnable { | ||||
|     auto getState() const -> State { return m_state; } | ||||
|  | ||||
|     QString getStatus() { return m_status; } | ||||
|     QString getDetails() { return m_details; } | ||||
|  | ||||
|     qint64 getProgress() { return m_progress; } | ||||
|     qint64 getTotalProgress() { return m_progressTotal; } | ||||
|     virtual auto getStepProgress() const -> TaskStepProgressList { return {}; } | ||||
|  | ||||
|     virtual auto getDetails() const -> QString { return ""; }  | ||||
|       | ||||
|  | ||||
|     QUuid getUid() { return m_uid; } | ||||
|  | ||||
| @@ -123,6 +126,7 @@ class Task : public QObject, public QRunnable { | ||||
|     void aborted(); | ||||
|     void failed(QString reason); | ||||
|     void status(QString status); | ||||
|     void details(QString details); | ||||
|     void stepProgress(TaskStepProgressList task_progress); //  | ||||
|  | ||||
|     /** Emitted when the canAbort() status has changed. | ||||
| @@ -150,6 +154,7 @@ class Task : public QObject, public QRunnable { | ||||
|  | ||||
|    public slots: | ||||
|     void setStatus(const QString& status); | ||||
|     void setDetails(const QString& details); | ||||
|     void setProgress(qint64 current, qint64 total); | ||||
|  | ||||
|    protected: | ||||
| @@ -157,6 +162,7 @@ class Task : public QObject, public QRunnable { | ||||
|     QStringList m_Warnings; | ||||
|     QString m_failReason = ""; | ||||
|     QString m_status; | ||||
|     QString m_details; | ||||
|     int m_progress = 0; | ||||
|     int m_progressTotal = 100; | ||||
|  | ||||
|   | ||||
| @@ -133,9 +133,9 @@ int ProgressDialog::execWithTask(Task* task) | ||||
|     connect(task, &Task::failed, this, &ProgressDialog::onTaskFailed); | ||||
|     connect(task, &Task::succeeded, this, &ProgressDialog::onTaskSucceeded); | ||||
|     connect(task, &Task::status, this, &ProgressDialog::changeStatus); | ||||
|     connect(task, &Task::details, this, &ProgressDialog::changeStatus); | ||||
|     connect(task, &Task::stepProgress, this, &ProgressDialog::changeStepProgress); | ||||
|     connect(task, &Task::progress, this, &ProgressDialog::changeProgress); | ||||
|  | ||||
|     connect(task, &Task::aborted, this, &ProgressDialog::hide); | ||||
|     connect(task, &Task::abortStatusChanged, ui->skipButton, &QPushButton::setEnabled); | ||||
|  | ||||
|   | ||||
| @@ -51,6 +51,7 @@ void ProgressWidget::watch(const Task* task) | ||||
|  | ||||
|     connect(m_task, &Task::finished, this, &ProgressWidget::handleTaskFinish); | ||||
|     connect(m_task, &Task::status, this, &ProgressWidget::handleTaskStatus); | ||||
|     // TODO: should we connect &Task::details | ||||
|     connect(m_task, &Task::progress, this, &ProgressWidget::handleTaskProgress); | ||||
|     connect(m_task, &Task::destroyed, this, &ProgressWidget::taskDestroyed); | ||||
|  | ||||
|   | ||||
| @@ -6,8 +6,8 @@ | ||||
|    <rect> | ||||
|     <x>0</x> | ||||
|     <y>0</y> | ||||
|     <width>597</width> | ||||
|     <height>61</height> | ||||
|     <width>312</width> | ||||
|     <height>86</height> | ||||
|    </rect> | ||||
|   </property> | ||||
|   <property name="sizePolicy"> | ||||
| @@ -25,6 +25,9 @@ | ||||
|    </property> | ||||
|    <item> | ||||
|     <layout class="QHBoxLayout" name="horizontalLayout" stretch="1,0"> | ||||
|      <property name="spacing"> | ||||
|       <number>8</number> | ||||
|      </property> | ||||
|      <item> | ||||
|       <widget class="QLabel" name="statusLabel"> | ||||
|        <property name="sizePolicy"> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user