From f997529cd4fb077b06d05da9c6ff0c23b85b4ebb Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Thu, 30 Mar 2023 11:22:55 -0700 Subject: feat: better task tracking Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) (limited to 'launcher/CMakeLists.txt') diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index ee36175f..24330adf 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -909,6 +909,8 @@ SET(LAUNCHER_SOURCES ui/widgets/VariableSizedImageObject.cpp ui/widgets/ProjectItem.h ui/widgets/ProjectItem.cpp + ui/widgets/SubTaskProgressBar.h + ui/widgets/SubTaskProgressBar.cpp ui/widgets/VersionListView.cpp ui/widgets/VersionListView.h ui/widgets/VersionSelectWidget.cpp @@ -969,6 +971,7 @@ qt_wrap_ui(LAUNCHER_UI ui/widgets/CustomCommands.ui ui/widgets/InfoFrame.ui ui/widgets/ModFilterWidget.ui + ui/widgets/SubTaskProgressBar.ui ui/widgets/ThemeCustomizationWidget.ui ui/dialogs/CopyInstanceDialog.ui ui/dialogs/ProfileSetupDialog.ui -- cgit From b6452215c16f6b1ee45fea746f9498767e48d049 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Fri, 31 Mar 2023 19:25:01 -0700 Subject: 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> --- launcher/Application.cpp | 19 +++++++++ launcher/CMakeLists.txt | 33 +++++++++++++++ launcher/InstanceImportTask.cpp | 2 + launcher/InstanceList.cpp | 1 + launcher/java/JavaInstallList.cpp | 1 + launcher/launch/steps/Update.cpp | 1 + launcher/minecraft/MinecraftUpdate.cpp | 2 + .../modplatform/atlauncher/ATLPackInstallTask.cpp | 3 +- .../flame/FlameInstanceCreationTask.cpp | 7 +++- .../modrinth/ModrinthInstanceCreationTask.cpp | 7 +++- launcher/net/Download.cpp | 47 +++++++++++----------- launcher/net/Download.h | 3 -- launcher/net/FileSink.cpp | 10 +++-- launcher/net/HttpMetaCache.cpp | 16 ++++---- launcher/net/MetaCacheSink.cpp | 10 +++-- launcher/net/PasteUpload.cpp | 22 +++++----- launcher/net/Upload.cpp | 38 ++++++++--------- launcher/net/logging.cpp | 24 +++++++++++ launcher/net/logging.h | 26 ++++++++++++ launcher/tasks/ConcurrentTask.cpp | 11 ++++- launcher/tasks/ConcurrentTask.h | 1 + launcher/tasks/Task.cpp | 42 ++++++++++++------- launcher/tasks/Task.h | 8 +++- launcher/ui/dialogs/ProgressDialog.cpp | 2 +- launcher/ui/widgets/ProgressWidget.cpp | 1 + launcher/ui/widgets/SubTaskProgressBar.ui | 7 +++- 26 files changed, 249 insertions(+), 95 deletions(-) create mode 100644 launcher/net/logging.cpp create mode 100644 launcher/net/logging.h (limited to 'launcher/CMakeLists.txt') diff --git a/launcher/Application.cpp b/launcher/Application.cpp index a7c97aa7..c8855cbc 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -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."; } diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index 24330adf..e49a4562 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -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}" diff --git a/launcher/InstanceImportTask.cpp b/launcher/InstanceImportTask.cpp index c196396d..8a48873e 100644 --- a/launcher/InstanceImportTask.cpp +++ b/launcher/InstanceImportTask.cpp @@ -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); diff --git a/launcher/InstanceList.cpp b/launcher/InstanceList.cpp index dbc891ff..5f98a184 100644 --- a/launcher/InstanceList.cpp +++ b/launcher/InstanceList.cpp @@ -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); diff --git a/launcher/java/JavaInstallList.cpp b/launcher/java/JavaInstallList.cpp index b29af857..5f133622 100644 --- a/launcher/java/JavaInstallList.cpp +++ b/launcher/java/JavaInstallList.cpp @@ -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; diff --git a/launcher/launch/steps/Update.cpp b/launcher/launch/steps/Update.cpp index 1640d115..c8e576a5 100644 --- a/launcher/launch/steps/Update.cpp +++ b/launcher/launch/steps/Update.cpp @@ -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; } diff --git a/launcher/minecraft/MinecraftUpdate.cpp b/launcher/minecraft/MinecraftUpdate.cpp index 3ce808f8..35430bb0 100644 --- a/launcher/minecraft/MinecraftUpdate.cpp +++ b/launcher/minecraft/MinecraftUpdate.cpp @@ -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()) { diff --git a/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp b/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp index 28026732..d130914f 100644 --- a/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp +++ b/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp @@ -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); }); diff --git a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp index 3cb6b61a..86fd2ab4 100644 --- a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp +++ b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp @@ -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); diff --git a/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp b/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp index 2fb656ea..bb8227aa 100644 --- a/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp +++ b/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp @@ -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...")); diff --git a/launcher/net/Download.cpp b/launcher/net/Download.cpp index 3eef9117..86e4bd97 100644 --- a/launcher/net/Download.cpp +++ b/launcher/net/Download.cpp @@ -4,6 +4,7 @@ * Copyright (c) 2022 flowln * Copyright (C) 2022 Sefa Eyeoglu * Copyright (C) 2023 TheKodeToad + * 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(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& 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; } } diff --git a/launcher/net/Download.h b/launcher/net/Download.h index cbee0d03..ae2b034c 100644 --- a/launcher/net/Download.h +++ b/launcher/net/Download.h @@ -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 m_last_progress_time; qint64 m_last_progress_bytes; - - QString m_details; }; } // namespace Net diff --git a/launcher/net/FileSink.cpp b/launcher/net/FileSink.cpp index ba0caf6c..3c2948d4 100644 --- a/launcher/net/FileSink.cpp +++ b/launcher/net/FileSink.cpp @@ -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; } diff --git a/launcher/net/HttpMetaCache.cpp b/launcher/net/HttpMetaCache.cpp index 0d7ca769..855211f7 100644 --- a/launcher/net/HttpMetaCache.cpp +++ b/launcher/net/HttpMetaCache.cpp @@ -44,6 +44,8 @@ #include +#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(); } } diff --git a/launcher/net/MetaCacheSink.cpp b/launcher/net/MetaCacheSink.cpp index c730fdbf..46bfe37d 100644 --- a/launcher/net/MetaCacheSink.cpp +++ b/launcher/net/MetaCacheSink.cpp @@ -39,6 +39,8 @@ #include #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); diff --git a/launcher/net/PasteUpload.cpp b/launcher/net/PasteUpload.cpp index d9e785c5..d5df3799 100644 --- a/launcher/net/PasteUpload.cpp +++ b/launcher/net/PasteUpload.cpp @@ -47,6 +47,8 @@ #include #include +#include "logging.h" + std::array 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; diff --git a/launcher/net/Upload.cpp b/launcher/net/Upload.cpp index ccf43c2d..518e302c 100644 --- a/launcher/net/Upload.cpp +++ b/launcher/net/Upload.cpp @@ -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 &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: diff --git a/launcher/net/logging.cpp b/launcher/net/logging.cpp new file mode 100644 index 00000000..e5b42bc4 --- /dev/null +++ b/launcher/net/logging.cpp @@ -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 . + * + */ + +#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") \ No newline at end of file diff --git a/launcher/net/logging.h b/launcher/net/logging.h new file mode 100644 index 00000000..e65e328c --- /dev/null +++ b/launcher/net/logging.h @@ -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 . + * + */ + +#pragma once + +#include + +Q_DECLARE_LOGGING_CATEGORY(taskNetLogC) +Q_DECLARE_LOGGING_CATEGORY(taskDownloadLogC) +Q_DECLARE_LOGGING_CATEGORY(taskUploadLogC) \ No newline at end of file diff --git a/launcher/tasks/ConcurrentTask.cpp b/launcher/tasks/ConcurrentTask.cpp index 41c405db..8d4f94ed 100644 --- a/launcher/tasks/ConcurrentTask.cpp +++ b/launcher/tasks/ConcurrentTask.cpp @@ -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(); diff --git a/launcher/tasks/ConcurrentTask.h b/launcher/tasks/ConcurrentTask.h index 9d4413c6..43e9f866 100644 --- a/launcher/tasks/ConcurrentTask.h +++ b/launcher/tasks/ConcurrentTask.h @@ -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); diff --git a/launcher/tasks/Task.cpp b/launcher/tasks/Task.cpp index 5aada876..ffde4a10 100644 --- a/launcher/tasks/Task.cpp +++ b/launcher/tasks/Task.cpp @@ -37,7 +37,7 @@ #include -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(); } diff --git a/launcher/tasks/Task.h b/launcher/tasks/Task.h index 863f8a4c..96b3b855 100644 --- a/launcher/tasks/Task.h +++ b/launcher/tasks/Task.h @@ -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; diff --git a/launcher/ui/dialogs/ProgressDialog.cpp b/launcher/ui/dialogs/ProgressDialog.cpp index 7ab766e4..1937c553 100644 --- a/launcher/ui/dialogs/ProgressDialog.cpp +++ b/launcher/ui/dialogs/ProgressDialog.cpp @@ -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); diff --git a/launcher/ui/widgets/ProgressWidget.cpp b/launcher/ui/widgets/ProgressWidget.cpp index f736af08..9181de7f 100644 --- a/launcher/ui/widgets/ProgressWidget.cpp +++ b/launcher/ui/widgets/ProgressWidget.cpp @@ -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); diff --git a/launcher/ui/widgets/SubTaskProgressBar.ui b/launcher/ui/widgets/SubTaskProgressBar.ui index ceae5e26..5431eab6 100644 --- a/launcher/ui/widgets/SubTaskProgressBar.ui +++ b/launcher/ui/widgets/SubTaskProgressBar.ui @@ -6,8 +6,8 @@ 0 0 - 597 - 61 + 312 + 86 @@ -25,6 +25,9 @@ + + 8 + -- cgit From fe36471b8dfad6156b735f9393072b9111a12547 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Sun, 2 Apr 2023 19:43:43 -0700 Subject: refactor: logging.h -> Logging.h Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/CMakeLists.txt | 22 ++++++++++++++++++++-- launcher/net/Download.cpp | 2 +- launcher/net/FileSink.cpp | 2 +- launcher/net/HttpMetaCache.cpp | 14 +++++++------- launcher/net/Logging.cpp | 26 ++++++++++++++++++++++++++ launcher/net/Logging.h | 28 ++++++++++++++++++++++++++++ launcher/net/MetaCacheSink.cpp | 10 +++++----- launcher/net/PasteUpload.cpp | 2 +- launcher/net/Upload.cpp | 2 +- launcher/net/logging.cpp | 24 ------------------------ launcher/net/logging.h | 26 -------------------------- 11 files changed, 90 insertions(+), 68 deletions(-) create mode 100644 launcher/net/Logging.cpp create mode 100644 launcher/net/Logging.h delete mode 100644 launcher/net/logging.cpp delete mode 100644 launcher/net/logging.h (limited to 'launcher/CMakeLists.txt') diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index e49a4562..5253a517 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -123,8 +123,8 @@ set(NET_SOURCES net/HttpMetaCache.h net/MetaCacheSink.cpp net/MetaCacheSink.h - net/logging.h - net/logging.cpp + net/Logging.h + net/Logging.cpp net/NetAction.h net/NetJob.cpp net/NetJob.h @@ -596,6 +596,24 @@ ecm_qt_export_logging_category( EXPORT "${Launcher_Name}" ) +ecm_qt_export_logging_category( + IDENTIFIER taskMetaCacheLogC + CATEGORY_NAME "launcher.task.net.metacache" + DEFAULT_SEVERITY Debug + DESCRIPTION "task network meta-cache actions" + EXPORT "${Launcher_Name}" +) + +ecm_qt_export_logging_category( + IDENTIFIER taskHttpMetaCacheLogC + CATEGORY_NAME "launcher.task.net.metacache.http" + DEFAULT_SEVERITY Debug + DESCRIPTION "task network http meta-cache 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}" diff --git a/launcher/net/Download.cpp b/launcher/net/Download.cpp index e7536dc9..bfd0be28 100644 --- a/launcher/net/Download.cpp +++ b/launcher/net/Download.cpp @@ -51,7 +51,7 @@ #include "BuildConfig.h" #include "Application.h" -#include "logging.h" +#include "net/Logging.h" #include "net/NetAction.h" namespace Net { diff --git a/launcher/net/FileSink.cpp b/launcher/net/FileSink.cpp index d5f09012..1ecb21fd 100644 --- a/launcher/net/FileSink.cpp +++ b/launcher/net/FileSink.cpp @@ -37,7 +37,7 @@ #include "FileSystem.h" -#include "logging.h" +#include "net/Logging.h" namespace Net { diff --git a/launcher/net/HttpMetaCache.cpp b/launcher/net/HttpMetaCache.cpp index c90f8d4d..e521c9e9 100644 --- a/launcher/net/HttpMetaCache.cpp +++ b/launcher/net/HttpMetaCache.cpp @@ -44,7 +44,7 @@ #include -#include "logging.h" +#include "net/Logging.h" auto MetaEntry::getFullPath() -> QString { @@ -139,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)) { - qCCritical(taskNetLogC) << "[HttpMetaCache]" << "Cannot add entry with unknown base: " << stale_entry->m_baseId.toLocal8Bit(); + qCCritical(taskHttpMetaCacheLogC) << "Cannot add entry with unknown base: " << stale_entry->m_baseId.toLocal8Bit(); return false; } if (stale_entry->m_stale) { - qCCritical(taskNetLogC) << "[HttpMetaCache]" << "Cannot add stale entry: " << stale_entry->getFullPath().toLocal8Bit(); + qCCritical(taskHttpMetaCacheLogC) << "Cannot add stale entry: " << stale_entry->getFullPath().toLocal8Bit(); return false; } @@ -168,10 +168,10 @@ void HttpMetaCache::evictAll() { for (QString& base : m_entries.keys()) { EntryMap& map = m_entries[base]; - qCDebug(taskNetLogC) << "[HttpMetaCache]" << "Evicting base" << base; + qCDebug(taskHttpMetaCacheLogC) << "Evicting base" << base; for (MetaEntryPtr entry : map.entry_list) { if (!evictEntry(entry)) - qCWarning(taskNetLogC) << "[HttpMetaCache]" << "Unexpected missing cache entry" << entry->m_basePath; + qCWarning(taskHttpMetaCacheLogC) << "Unexpected missing cache entry" << entry->m_basePath; } } } @@ -269,7 +269,7 @@ void HttpMetaCache::SaveNow() if (m_index_file.isNull()) return; - qCDebug(taskNetLogC) << "[HttpMetaCache]" << "Saving metacache with" << m_entries.size() << "entries"; + qCDebug(taskHttpMetaCacheLogC) << "Saving metacache with" << m_entries.size() << "entries"; QJsonObject toplevel; Json::writeString(toplevel, "version", "1"); @@ -304,6 +304,6 @@ void HttpMetaCache::SaveNow() try { Json::write(toplevel, m_index_file); } catch (const Exception& e) { - qCWarning(taskNetLogC) << "[HttpMetaCache]" << e.what(); + qCWarning(taskHttpMetaCacheLogC) << "Error writing cache:" << e.what(); } } diff --git a/launcher/net/Logging.cpp b/launcher/net/Logging.cpp new file mode 100644 index 00000000..a9b9db7c --- /dev/null +++ b/launcher/net/Logging.cpp @@ -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 . + * + */ + +#include "net/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") +Q_LOGGING_CATEGORY(taskMetaCacheLogC, "launcher.task.net.metacache") +Q_LOGGING_CATEGORY(taskHttpMetaCacheLogC, "launcher.task.net.metacache.http") diff --git a/launcher/net/Logging.h b/launcher/net/Logging.h new file mode 100644 index 00000000..b692e707 --- /dev/null +++ b/launcher/net/Logging.h @@ -0,0 +1,28 @@ +// 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 . + * + */ + +#pragma once + +#include + +Q_DECLARE_LOGGING_CATEGORY(taskNetLogC) +Q_DECLARE_LOGGING_CATEGORY(taskDownloadLogC) +Q_DECLARE_LOGGING_CATEGORY(taskUploadLogC) +Q_DECLARE_LOGGING_CATEGORY(taskMetaCacheLogC) +Q_DECLARE_LOGGING_CATEGORY(taskHttpMetaCacheLogC) diff --git a/launcher/net/MetaCacheSink.cpp b/launcher/net/MetaCacheSink.cpp index fc997553..e203bc06 100644 --- a/launcher/net/MetaCacheSink.cpp +++ b/launcher/net/MetaCacheSink.cpp @@ -39,7 +39,7 @@ #include #include "Application.h" -#include "logging.h" +#include "net/Logging.h" namespace Net { @@ -99,11 +99,11 @@ Task::State MetaCacheSink::finalizeCache(QNetworkReply & reply) { // Cache lifetime if (m_is_eternal) { - qCDebug(taskNetLogC) << "[MetaCache] Adding eternal cache entry:" << m_entry->getFullPath(); + qCDebug(taskMetaCacheLogC) << "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"); - // qCDebug(taskNetLogC) << "[MetaCache] Parsing 'Cache-Control' header with" << cache_control_header; + qCDebug(taskMetaCacheLogC) << "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(); @@ -111,7 +111,7 @@ Task::State MetaCacheSink::finalizeCache(QNetworkReply & reply) } else if (reply.hasRawHeader("Expires")) { auto expires_header = reply.rawHeader("Expires"); - // qCDebug(taskNetLogC) << "[MetaCache] Parsing 'Expires' header with" << expires_header; + qCDebug(taskMetaCacheLogC) << "Parsing 'Expires' header with" << expires_header; qint64 max_age = QDateTime::fromString(expires_header).toSecsSinceEpoch() - QDateTime::currentSecsSinceEpoch(); m_entry->setMaximumAge(max_age); @@ -121,7 +121,7 @@ Task::State MetaCacheSink::finalizeCache(QNetworkReply & reply) if (reply.hasRawHeader("Age")) { auto age_header = reply.rawHeader("Age"); - // qCDebug(taskNetLogC) << "[MetaCache] Parsing 'Age' header with" << age_header; + qCDebug(taskMetaCacheLogC) << "Parsing 'Age' header with" << age_header; qint64 current_age = age_header.toLongLong(); m_entry->setCurrentAge(current_age); diff --git a/launcher/net/PasteUpload.cpp b/launcher/net/PasteUpload.cpp index 9c2b20c6..595279a3 100644 --- a/launcher/net/PasteUpload.cpp +++ b/launcher/net/PasteUpload.cpp @@ -47,7 +47,7 @@ #include #include -#include "logging.h" +#include "net/Logging.h" std::array PasteUpload::PasteTypes = { {{"0x0.st", "https://0x0.st", ""}, diff --git a/launcher/net/Upload.cpp b/launcher/net/Upload.cpp index 85f364d3..8045f850 100644 --- a/launcher/net/Upload.cpp +++ b/launcher/net/Upload.cpp @@ -43,7 +43,7 @@ #include "BuildConfig.h" #include "Application.h" -#include "logging.h" +#include "net/Logging.h" namespace Net { diff --git a/launcher/net/logging.cpp b/launcher/net/logging.cpp deleted file mode 100644 index e5b42bc4..00000000 --- a/launcher/net/logging.cpp +++ /dev/null @@ -1,24 +0,0 @@ -// 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 . - * - */ - -#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") \ No newline at end of file diff --git a/launcher/net/logging.h b/launcher/net/logging.h deleted file mode 100644 index e65e328c..00000000 --- a/launcher/net/logging.h +++ /dev/null @@ -1,26 +0,0 @@ -// 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 . - * - */ - -#pragma once - -#include - -Q_DECLARE_LOGGING_CATEGORY(taskNetLogC) -Q_DECLARE_LOGGING_CATEGORY(taskDownloadLogC) -Q_DECLARE_LOGGING_CATEGORY(taskUploadLogC) \ No newline at end of file -- cgit From 96decbac27b364e0ffdcb20c40b08a79b827be00 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Mon, 3 Apr 2023 15:14:24 -0700 Subject: feat: default qtlogging.ini file Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- CMakeLists.txt | 4 ++++ launcher/Application.cpp | 52 ++++++++++++++++++++++++++++++----------- launcher/Application.h | 5 ++++ launcher/CMakeLists.txt | 6 +++++ launcher/qtlogging.ini | 11 +++++++++ program_info/win_install.nsi.in | 1 + 6 files changed, 65 insertions(+), 14 deletions(-) create mode 100644 launcher/qtlogging.ini (limited to 'launcher/CMakeLists.txt') diff --git a/CMakeLists.txt b/CMakeLists.txt index 05c69c89..2ff26aee 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -345,6 +345,8 @@ elseif(UNIX) install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${Launcher_SVG} DESTINATION "${KDE_INSTALL_ICONDIR}/hicolor/scalable/apps") install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${Launcher_mrpack_MIMEInfo} DESTINATION ${KDE_INSTALL_MIMEDIR}) + install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/launcher/qtlogging.ini" DESTINATION "${KDE_INSTALL_DATADIR}/${Launcher_Name}") + if(Launcher_ManPage) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${Launcher_ManPage} DESTINATION "${KDE_INSTALL_MANDIR}/man6") endif() @@ -372,6 +374,8 @@ else() message(FATAL_ERROR "Platform not supported") endif() + + ################################ Included Libs ################################ include(ExternalProject) diff --git a/launcher/Application.cpp b/launcher/Application.cpp index c8855cbc..f7595512 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -287,6 +287,7 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) if (QFile::exists(FS::PathCombine(m_rootPath, "portable.txt"))) { dataPath = m_rootPath; adjustedBy = "Portable data path"; + m_portable = true; } #endif } @@ -411,23 +412,46 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) " " "|" " " "%{if-category}[%{category}]: %{endif}" "%{message}"); + + bool foundLoggingRules = false; - if(QFile::exists("logging.ini")) { + auto logRulesFile = QStringLiteral("qtlogging.ini"); + auto logRulesPath = FS::PathCombine(dataPath, logRulesFile); + + qDebug() << "Testing" << logRulesPath << "..."; + foundLoggingRules = QFile::exists(logRulesPath); + + // search the dataPath() + + if(!foundLoggingRules && ! isPortable()) { + logRulesPath = QStandardPaths::locate(QStandardPaths::AppDataLocation, logRulesFile); + if(!logRulesPath.isEmpty()) { + qDebug() << "Found" << logRulesPath << "..."; + foundLoggingRules = true; + } + } + + if(!QFile::exists(logRulesPath)) { + logRulesPath = FS::PathCombine(m_rootPath, logRulesFile); + qDebug() << "Testing" << logRulesPath << "..."; + foundLoggingRules = QFile::exists(logRulesPath); + } + + if(foundLoggingRules) { // 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() << "Loading logging rules from:" << logRulesPath; + QSettings loggingRules(logRulesPath, QSettings::IniFormat); + loggingRules.beginGroup("Rules"); + QStringList rule_names = loggingRules.childKeys(); + QStringList rules; + qDebug() << "Setting log rules:"; + for (auto rule_name : rule_names) { + auto rule = QString("%1=%2").arg(rule_name).arg(loggingRules.value(rule_name).toString()); + rules.append(rule); + qDebug() << " " << rule; } + auto rules_str = rules.join("\n"); + QLoggingCategory::setFilterRules(rules_str); } qDebug() << "<> Log initialized."; diff --git a/launcher/Application.h b/launcher/Application.h index 0d24a4e9..3d833edc 100644 --- a/launcher/Application.h +++ b/launcher/Application.h @@ -187,6 +187,10 @@ public: return m_rootPath; } + const bool isPortable() { + return m_portable; + } + const Capabilities capabilities() { return m_capabilities; } @@ -275,6 +279,7 @@ private: QString m_rootPath; Status m_status = Application::StartingUp; Capabilities m_capabilities; + bool m_portable = false; #ifdef Q_OS_MACOS Qt::ApplicationState m_prevAppState = Qt::ApplicationInactive; diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index 5253a517..a3ef20e8 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -1161,6 +1161,12 @@ if(INSTALL_BUNDLE STREQUAL "full") CODE "file(WRITE \"\${CMAKE_INSTALL_PREFIX}/${RESOURCES_DEST_DIR}/qt.conf\" \" \")" COMPONENT Runtime ) + # add qtlogging.ini as a config file + install( + FILES "qtlogging.ini" + DESTINATION ${CMAKE_INSTALL_PREFIX}/${RESOURCES_DEST_DIR} + COMPONENT Runtime + ) # Bundle plugins # Image formats install( diff --git a/launcher/qtlogging.ini b/launcher/qtlogging.ini new file mode 100644 index 00000000..eba5390d --- /dev/null +++ b/launcher/qtlogging.ini @@ -0,0 +1,11 @@ +[Rules] +*.debug=true +# remove the debug lines, other log levels still get through +launcher.task.net.download.debug=false +# enable or disable whole catageries +launcher.task.net=true +launcher.task=false +launcher.task.net.upload=true +launcher.task.net.metacache=false +launcher.task.net.metacache.http=true + diff --git a/program_info/win_install.nsi.in b/program_info/win_install.nsi.in index 49e22500..a809c55d 100644 --- a/program_info/win_install.nsi.in +++ b/program_info/win_install.nsi.in @@ -282,6 +282,7 @@ Section "@Launcher_DisplayName@" File "@Launcher_APP_BINARY_NAME@.exe" File "qt.conf" + File "qtlogging.ini" File *.dll File /r "iconengines" File /r "imageformats" -- cgit