From 014fc142915ec4a0f96b3082f76d4d32ce7596aa Mon Sep 17 00:00:00 2001 From: maskers <97827489+mskrss@users.noreply.github.com> Date: Tue, 20 Aug 2024 21:53:05 +0300 Subject: [PATCH 01/80] truncate logs for mclo.gs upload to fit 25k line limit Signed-off-by: maskers <97827489+mskrss@users.noreply.github.com> --- launcher/net/PasteUpload.cpp | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/launcher/net/PasteUpload.cpp b/launcher/net/PasteUpload.cpp index c67d3b23c..5e8c5a8cd 100644 --- a/launcher/net/PasteUpload.cpp +++ b/launcher/net/PasteUpload.cpp @@ -49,6 +49,27 @@ #include "net/Logging.h" +constexpr int MaxMclogsLines = 25000; +constexpr int InitialMclogsLines = 10000; +constexpr int FinalMclogsLines = 14900; + +QString truncateLogForMclogs(const QString &logContent) { + QStringList lines = logContent.split("\n"); + if (lines.size() > MaxMclogsLines) { + QString truncatedLog = lines.mid(0, InitialMclogsLines).join("\n"); + truncatedLog += "\n\n\n\n\n\n\n\n\n\n" + "------------------------------------------------------------\n" + "--------------------- Log truncated by ---------------------\n" + "---------------------- Prism Launcher ----------------------\n" + "----- Middle portion omitted to fit mclo.gs size limits ----\n" + "------------------------------------------------------------\n" + "\n\n\n\n\n\n\n\n\n\n"; + truncatedLog += lines.mid(lines.size() - FinalMclogsLines, FinalMclogsLines).join("\n"); + return truncatedLog; + } + return logContent; +} + std::array PasteUpload::PasteTypes = { { { "0x0.st", "https://0x0.st", "" }, { "hastebin", "https://hst.sh", "/documents" }, { "paste.gg", "https://paste.gg", "/api/v1/pastes" }, @@ -98,6 +119,7 @@ void PasteUpload::executeTask() } case Mclogs: { QUrlQuery postData; + m_text = truncateLogForMclogs(m_text).toUtf8(); postData.addQueryItem("content", m_text); request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded"); rep = APPLICATION->network()->post(request, postData.toString().toUtf8()); From e6f30c0ebe0ddd43b493f27156d6c0765105ded5 Mon Sep 17 00:00:00 2001 From: maskers <97827489+mskrss@users.noreply.github.com> Date: Tue, 20 Aug 2024 22:14:40 +0300 Subject: [PATCH 02/80] fix formatting Signed-off-by: maskers <97827489+mskrss@users.noreply.github.com> --- launcher/net/PasteUpload.cpp | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/launcher/net/PasteUpload.cpp b/launcher/net/PasteUpload.cpp index 5e8c5a8cd..92a44d5ed 100644 --- a/launcher/net/PasteUpload.cpp +++ b/launcher/net/PasteUpload.cpp @@ -53,17 +53,19 @@ constexpr int MaxMclogsLines = 25000; constexpr int InitialMclogsLines = 10000; constexpr int FinalMclogsLines = 14900; -QString truncateLogForMclogs(const QString &logContent) { +QString truncateLogForMclogs(const QString &logContent) +{ QStringList lines = logContent.split("\n"); if (lines.size() > MaxMclogsLines) { QString truncatedLog = lines.mid(0, InitialMclogsLines).join("\n"); - truncatedLog += "\n\n\n\n\n\n\n\n\n\n" - "------------------------------------------------------------\n" - "--------------------- Log truncated by ---------------------\n" - "---------------------- Prism Launcher ----------------------\n" - "----- Middle portion omitted to fit mclo.gs size limits ----\n" - "------------------------------------------------------------\n" - "\n\n\n\n\n\n\n\n\n\n"; + truncatedLog += + "\n\n\n\n\n\n\n\n\n\n" + "------------------------------------------------------------\n" + "--------------------- Log truncated by ---------------------\n" + "---------------------- Prism Launcher ----------------------\n" + "----- Middle portion omitted to fit mclo.gs size limits ----\n" + "------------------------------------------------------------\n" + "\n\n\n\n\n\n\n\n\n\n"; truncatedLog += lines.mid(lines.size() - FinalMclogsLines, FinalMclogsLines).join("\n"); return truncatedLog; } From 858f6aa9b8adcb5d2ac9eadd2702a21a88f9e4c4 Mon Sep 17 00:00:00 2001 From: maskers <97827489+mskrss@users.noreply.github.com> Date: Tue, 20 Aug 2024 22:16:40 +0300 Subject: [PATCH 03/80] fix formatting Signed-off-by: maskers <97827489+mskrss@users.noreply.github.com> --- launcher/net/PasteUpload.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/net/PasteUpload.cpp b/launcher/net/PasteUpload.cpp index 92a44d5ed..953a0d722 100644 --- a/launcher/net/PasteUpload.cpp +++ b/launcher/net/PasteUpload.cpp @@ -53,7 +53,7 @@ constexpr int MaxMclogsLines = 25000; constexpr int InitialMclogsLines = 10000; constexpr int FinalMclogsLines = 14900; -QString truncateLogForMclogs(const QString &logContent) +QString truncateLogForMclogs(const QString& logContent) { QStringList lines = logContent.split("\n"); if (lines.size() > MaxMclogsLines) { From cf914526bf5330600f3cadb9f4baddb5144af21f Mon Sep 17 00:00:00 2001 From: maskers <97827489+mskrss@users.noreply.github.com> Date: Wed, 21 Aug 2024 15:59:51 +0300 Subject: [PATCH 04/80] add a warning about the log being too large Signed-off-by: maskers <97827489+mskrss@users.noreply.github.com> --- launcher/net/PasteUpload.cpp | 24 ----------------- launcher/ui/GuiUtil.cpp | 51 +++++++++++++++++++++++++++++++++++- 2 files changed, 50 insertions(+), 25 deletions(-) diff --git a/launcher/net/PasteUpload.cpp b/launcher/net/PasteUpload.cpp index 953a0d722..c67d3b23c 100644 --- a/launcher/net/PasteUpload.cpp +++ b/launcher/net/PasteUpload.cpp @@ -49,29 +49,6 @@ #include "net/Logging.h" -constexpr int MaxMclogsLines = 25000; -constexpr int InitialMclogsLines = 10000; -constexpr int FinalMclogsLines = 14900; - -QString truncateLogForMclogs(const QString& logContent) -{ - QStringList lines = logContent.split("\n"); - if (lines.size() > MaxMclogsLines) { - QString truncatedLog = lines.mid(0, InitialMclogsLines).join("\n"); - truncatedLog += - "\n\n\n\n\n\n\n\n\n\n" - "------------------------------------------------------------\n" - "--------------------- Log truncated by ---------------------\n" - "---------------------- Prism Launcher ----------------------\n" - "----- Middle portion omitted to fit mclo.gs size limits ----\n" - "------------------------------------------------------------\n" - "\n\n\n\n\n\n\n\n\n\n"; - truncatedLog += lines.mid(lines.size() - FinalMclogsLines, FinalMclogsLines).join("\n"); - return truncatedLog; - } - return logContent; -} - std::array PasteUpload::PasteTypes = { { { "0x0.st", "https://0x0.st", "" }, { "hastebin", "https://hst.sh", "/documents" }, { "paste.gg", "https://paste.gg", "/api/v1/pastes" }, @@ -121,7 +98,6 @@ void PasteUpload::executeTask() } case Mclogs: { QUrlQuery postData; - m_text = truncateLogForMclogs(m_text).toUtf8(); postData.addQueryItem("content", m_text); request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded"); rep = APPLICATION->network()->post(request, postData.toString().toUtf8()); diff --git a/launcher/ui/GuiUtil.cpp b/launcher/ui/GuiUtil.cpp index 584a34710..3b0eccd02 100644 --- a/launcher/ui/GuiUtil.cpp +++ b/launcher/ui/GuiUtil.cpp @@ -51,11 +51,35 @@ #include #include "Application.h" +constexpr int MaxMclogsLines = 25000; +constexpr int InitialMclogsLines = 10000; +constexpr int FinalMclogsLines = 14900; + +QString truncateLogForMclogs(const QString& logContent) +{ + QStringList lines = logContent.split("\n"); + if (lines.size() > MaxMclogsLines) { + QString truncatedLog = lines.mid(0, InitialMclogsLines).join("\n"); + truncatedLog += + "\n\n\n\n\n\n\n\n\n\n" + "------------------------------------------------------------\n" + "--------------------- Log truncated by ---------------------\n" + "---------------------- Prism Launcher ----------------------\n" + "----- Middle portion omitted to fit mclo.gs size limits ----\n" + "------------------------------------------------------------\n" + "\n\n\n\n\n\n\n\n\n\n"; + truncatedLog += lines.mid(lines.size() - FinalMclogsLines, FinalMclogsLines).join("\n"); + return truncatedLog; + } + return logContent; +} + std::optional GuiUtil::uploadPaste(const QString& name, const QString& text, QWidget* parentWidget) { ProgressDialog dialog(parentWidget); auto pasteTypeSetting = static_cast(APPLICATION->settings()->get("PastebinType").toInt()); auto pasteCustomAPIBaseSetting = APPLICATION->settings()->get("PastebinCustomAPIBase").toString(); + bool shouldTruncate = false; { QUrl baseUrl; @@ -75,10 +99,35 @@ std::optional GuiUtil::uploadPaste(const QString& name, const QString& if (response != QMessageBox::Yes) return {}; + + if (baseUrl.toString() == "https://api.mclo.gs" && text.count("\n") > MaxMclogsLines) { + auto truncateResponse = + CustomMessageBox::selectable(parentWidget, QObject::tr("Confirm Truncate"), + QObject::tr("The log exceeds mclo.gs' limit: %1 lines (max %2).\n" + "Prism can keep the first %3 and last %4 lines, trimming the middle.\n\n" + "If you choose 'No', mclo.gs will only keep the first %2 lines, cutting off " + "potentially useful info like crashes at the end.\n\n" + "Proceed with Prism's truncation?") + .arg(text.count("\n")) + .arg(MaxMclogsLines) + .arg(InitialMclogsLines) + .arg(FinalMclogsLines), + QMessageBox::Warning, QMessageBox::Yes | QMessageBox::No, QMessageBox::No) + ->exec(); + + if (truncateResponse == QMessageBox::Yes) + shouldTruncate = true; + } } } - std::unique_ptr paste(new PasteUpload(parentWidget, text, pasteCustomAPIBaseSetting, pasteTypeSetting)); + QString textToUpload; + if (shouldTruncate) + textToUpload = truncateLogForMclogs(text); + else + textToUpload = text; + + std::unique_ptr paste(new PasteUpload(parentWidget, textToUpload, pasteCustomAPIBaseSetting, pasteTypeSetting)); dialog.execWithTask(paste.get()); if (!paste->wasSuccessful()) { From 99bd4a89373416cea641f1421d1082ff823eba2e Mon Sep 17 00:00:00 2001 From: maskers <97827489+maskersss@users.noreply.github.com> Date: Wed, 21 Aug 2024 19:42:35 +0300 Subject: [PATCH 05/80] Apply suggestions from code review Co-authored-by: Alexandru Ionut Tripon Signed-off-by: maskers <97827489+maskersss@users.noreply.github.com> --- launcher/ui/GuiUtil.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/launcher/ui/GuiUtil.cpp b/launcher/ui/GuiUtil.cpp index 3b0eccd02..de72a7d5d 100644 --- a/launcher/ui/GuiUtil.cpp +++ b/launcher/ui/GuiUtil.cpp @@ -115,17 +115,15 @@ std::optional GuiUtil::uploadPaste(const QString& name, const QString& QMessageBox::Warning, QMessageBox::Yes | QMessageBox::No, QMessageBox::No) ->exec(); - if (truncateResponse == QMessageBox::Yes) - shouldTruncate = true; + shouldTruncate = truncateResponse == QMessageBox::Yes; } } } - QString textToUpload; - if (shouldTruncate) + QString textToUpload = text; + if (shouldTruncate) { textToUpload = truncateLogForMclogs(text); - else - textToUpload = text; + } std::unique_ptr paste(new PasteUpload(parentWidget, textToUpload, pasteCustomAPIBaseSetting, pasteTypeSetting)); From 65f852615247f6c1ba3cd81cf9e51ebc0220341b Mon Sep 17 00:00:00 2001 From: maskers <97827489+maskersss@users.noreply.github.com> Date: Wed, 21 Aug 2024 22:14:11 +0300 Subject: [PATCH 06/80] add a `Cancel` option Co-authored-by: Rachel Powers <508861+Ryex@users.noreply.github.com> Signed-off-by: maskers <97827489+maskersss@users.noreply.github.com> --- launcher/ui/GuiUtil.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/launcher/ui/GuiUtil.cpp b/launcher/ui/GuiUtil.cpp index de72a7d5d..cfc1715fc 100644 --- a/launcher/ui/GuiUtil.cpp +++ b/launcher/ui/GuiUtil.cpp @@ -112,9 +112,10 @@ std::optional GuiUtil::uploadPaste(const QString& name, const QString& .arg(MaxMclogsLines) .arg(InitialMclogsLines) .arg(FinalMclogsLines), - QMessageBox::Warning, QMessageBox::Yes | QMessageBox::No, QMessageBox::No) + QMessageBox::Warning, QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel, QMessageBox::No) ->exec(); + if (truncateResponse == QMessageBox::Cancel) { return {} ; } shouldTruncate = truncateResponse == QMessageBox::Yes; } } From 6d017b5f0b9fd878d387bf33585221ea079e305b Mon Sep 17 00:00:00 2001 From: maskers <97827489+mskrss@users.noreply.github.com> Date: Wed, 21 Aug 2024 22:39:27 +0300 Subject: [PATCH 07/80] fix formatting Signed-off-by: maskers <97827489+mskrss@users.noreply.github.com> --- launcher/ui/GuiUtil.cpp | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/launcher/ui/GuiUtil.cpp b/launcher/ui/GuiUtil.cpp index cfc1715fc..5cdd30e17 100644 --- a/launcher/ui/GuiUtil.cpp +++ b/launcher/ui/GuiUtil.cpp @@ -101,21 +101,23 @@ std::optional GuiUtil::uploadPaste(const QString& name, const QString& return {}; if (baseUrl.toString() == "https://api.mclo.gs" && text.count("\n") > MaxMclogsLines) { - auto truncateResponse = - CustomMessageBox::selectable(parentWidget, QObject::tr("Confirm Truncate"), - QObject::tr("The log exceeds mclo.gs' limit: %1 lines (max %2).\n" - "Prism can keep the first %3 and last %4 lines, trimming the middle.\n\n" - "If you choose 'No', mclo.gs will only keep the first %2 lines, cutting off " - "potentially useful info like crashes at the end.\n\n" - "Proceed with Prism's truncation?") - .arg(text.count("\n")) - .arg(MaxMclogsLines) - .arg(InitialMclogsLines) - .arg(FinalMclogsLines), - QMessageBox::Warning, QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel, QMessageBox::No) - ->exec(); + auto truncateResponse = CustomMessageBox::selectable( + parentWidget, QObject::tr("Confirm Truncate"), + QObject::tr("The log exceeds mclo.gs' limit: %1 lines (max %2).\n" + "Prism can keep the first %3 and last %4 lines, trimming the middle.\n\n" + "If you choose 'No', mclo.gs will only keep the first %2 lines, cutting off " + "potentially useful info like crashes at the end.\n\n" + "Proceed with Prism's truncation?") + .arg(text.count("\n")) + .arg(MaxMclogsLines) + .arg(InitialMclogsLines) + .arg(FinalMclogsLines), + QMessageBox::Warning, QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel, QMessageBox::No) + ->exec(); - if (truncateResponse == QMessageBox::Cancel) { return {} ; } + if (truncateResponse == QMessageBox::Cancel) { + return {}; + } shouldTruncate = truncateResponse == QMessageBox::Yes; } } From a910337e9d148937fc6a7339a7bcdd9a2db1ec03 Mon Sep 17 00:00:00 2001 From: maskers <97827489+maskersss@users.noreply.github.com> Date: Thu, 22 Aug 2024 21:42:05 +0300 Subject: [PATCH 08/80] apply suggestion from code review Co-authored-by: TheKodeToad Signed-off-by: maskers <97827489+maskersss@users.noreply.github.com> --- launcher/ui/GuiUtil.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/launcher/ui/GuiUtil.cpp b/launcher/ui/GuiUtil.cpp index 5cdd30e17..4d2e64af4 100644 --- a/launcher/ui/GuiUtil.cpp +++ b/launcher/ui/GuiUtil.cpp @@ -103,11 +103,11 @@ std::optional GuiUtil::uploadPaste(const QString& name, const QString& if (baseUrl.toString() == "https://api.mclo.gs" && text.count("\n") > MaxMclogsLines) { auto truncateResponse = CustomMessageBox::selectable( parentWidget, QObject::tr("Confirm Truncate"), - QObject::tr("The log exceeds mclo.gs' limit: %1 lines (max %2).\n" - "Prism can keep the first %3 and last %4 lines, trimming the middle.\n\n" + QObject::tr("The log has %1 lines, exceeding mclo.gs' limit of %2.\n" + "The launcher can keep the first %3 and last %4 lines, trimming the middle.\n\n" "If you choose 'No', mclo.gs will only keep the first %2 lines, cutting off " "potentially useful info like crashes at the end.\n\n" - "Proceed with Prism's truncation?") + "Proceed with truncation?") .arg(text.count("\n")) .arg(MaxMclogsLines) .arg(InitialMclogsLines) From 762d24bd02ae6a0c0f241626c9c06deeaae86574 Mon Sep 17 00:00:00 2001 From: maskers <97827489+mskrss@users.noreply.github.com> Date: Thu, 22 Aug 2024 21:44:53 +0300 Subject: [PATCH 09/80] don't mention prism in the middle of the log Signed-off-by: maskers <97827489+mskrss@users.noreply.github.com> --- launcher/ui/GuiUtil.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/launcher/ui/GuiUtil.cpp b/launcher/ui/GuiUtil.cpp index 4d2e64af4..77d4a98e2 100644 --- a/launcher/ui/GuiUtil.cpp +++ b/launcher/ui/GuiUtil.cpp @@ -63,8 +63,8 @@ QString truncateLogForMclogs(const QString& logContent) truncatedLog += "\n\n\n\n\n\n\n\n\n\n" "------------------------------------------------------------\n" - "--------------------- Log truncated by ---------------------\n" - "---------------------- Prism Launcher ----------------------\n" + "----------------------- Log truncated ----------------------\n" + "------------------------------------------------------------\n" "----- Middle portion omitted to fit mclo.gs size limits ----\n" "------------------------------------------------------------\n" "\n\n\n\n\n\n\n\n\n\n"; From 43fc9ba932ec65d274b60bafb4d3c3f1d5bf55f0 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Sun, 25 Aug 2024 13:05:08 +0100 Subject: [PATCH 10/80] Confirm Truncate -> Truncation Signed-off-by: TheKodeToad --- launcher/ui/GuiUtil.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/ui/GuiUtil.cpp b/launcher/ui/GuiUtil.cpp index 77d4a98e2..ccb4e48b5 100644 --- a/launcher/ui/GuiUtil.cpp +++ b/launcher/ui/GuiUtil.cpp @@ -102,7 +102,7 @@ std::optional GuiUtil::uploadPaste(const QString& name, const QString& if (baseUrl.toString() == "https://api.mclo.gs" && text.count("\n") > MaxMclogsLines) { auto truncateResponse = CustomMessageBox::selectable( - parentWidget, QObject::tr("Confirm Truncate"), + parentWidget, QObject::tr("Confirm Truncation"), QObject::tr("The log has %1 lines, exceeding mclo.gs' limit of %2.\n" "The launcher can keep the first %3 and last %4 lines, trimming the middle.\n\n" "If you choose 'No', mclo.gs will only keep the first %2 lines, cutting off " From 6a12c43c787db4a64748d6c3d03b34981948d7ce Mon Sep 17 00:00:00 2001 From: maskers <97827489+mskrss@users.noreply.github.com> Date: Sun, 25 Aug 2024 16:02:32 +0300 Subject: [PATCH 11/80] fix off by one error Signed-off-by: maskers <97827489+mskrss@users.noreply.github.com> --- launcher/ui/GuiUtil.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/ui/GuiUtil.cpp b/launcher/ui/GuiUtil.cpp index ccb4e48b5..94dd01169 100644 --- a/launcher/ui/GuiUtil.cpp +++ b/launcher/ui/GuiUtil.cpp @@ -68,7 +68,7 @@ QString truncateLogForMclogs(const QString& logContent) "----- Middle portion omitted to fit mclo.gs size limits ----\n" "------------------------------------------------------------\n" "\n\n\n\n\n\n\n\n\n\n"; - truncatedLog += lines.mid(lines.size() - FinalMclogsLines, FinalMclogsLines).join("\n"); + truncatedLog += lines.mid(lines.size() - FinalMclogsLines - 1).join("\n"); return truncatedLog; } return logContent; From 6b0007291bf8fd094300c21eb64cc119fb3a378d Mon Sep 17 00:00:00 2001 From: QazCetelic Date: Tue, 10 Sep 2024 22:30:29 +0200 Subject: [PATCH 12/80] Added search and support for subdirectories to icon picker Signed-off-by: QazCetelic --- launcher/icons/IconList.cpp | 142 ++++++++++++++++++----- launcher/icons/IconList.h | 4 + launcher/ui/dialogs/IconPickerDialog.cpp | 23 +++- launcher/ui/dialogs/IconPickerDialog.h | 5 + 4 files changed, 144 insertions(+), 30 deletions(-) diff --git a/launcher/icons/IconList.cpp b/launcher/icons/IconList.cpp index e4157ea2d..56ff10e51 100644 --- a/launcher/icons/IconList.cpp +++ b/launcher/icons/IconList.cpp @@ -56,7 +56,7 @@ IconList::IconList(const QStringList& builtinPaths, QString path, QObject* paren QDir instance_icons(builtinPath); auto file_info_list = instance_icons.entryInfoList(QDir::Files, QDir::Name); for (auto file_info : file_info_list) { - builtinNames.insert(file_info.completeBaseName()); + builtinNames.insert(file_info.baseName()); } } for (auto& builtinName : builtinNames) { @@ -77,10 +77,95 @@ IconList::IconList(const QStringList& builtinPaths, QString path, QObject* paren void IconList::sortIconList() { qDebug() << "Sorting icon list..."; - std::sort(icons.begin(), icons.end(), [](const MMCIcon& a, const MMCIcon& b) { return a.m_key.localeAwareCompare(b.m_key) < 0; }); + std::sort(icons.begin(), icons.end(), [](const MMCIcon& a, const MMCIcon& b) { + bool aIsSubdir = a.m_key.contains(std::filesystem::path::preferred_separator); + bool bIsSubdir = b.m_key.contains(std::filesystem::path::preferred_separator); + if (aIsSubdir != bIsSubdir) { + return !aIsSubdir; // root-level icons come first + } + return a.m_key.localeAwareCompare(b.m_key) < 0; + }); reindex(); } +// Helper function to add directories recursively +bool IconList::addPathRecursively(const QString& path) +{ + QDir dir(path); + if (!dir.exists()) + return false; + + bool watching = false; + + // Add the directory itself + watching = m_watcher->addPath(path); + + // Add all subdirectories + QFileInfoList entries = dir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot); + for (const QFileInfo& entry : entries) + { + if (addPathRecursively(entry.absoluteFilePath())) + { + watching = true; + } + } + return watching; +} + +void IconList::removePathRecursively(const QString& path) +{ + QFileInfo file_info(path); + if (file_info.isFile()) { + // Remove the icon belonging to the file + QString key = m_dir.relativeFilePath(file_info.absoluteFilePath()); + int idx = getIconIndex(key); + if (idx == -1) + return; + + } + else if (file_info.isDir()) { + // Remove the directory itself + m_watcher->removePath(path); + + const QDir dir(path); + // Remove all files within the directory + for (const QFileInfo& file : dir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot)) + { + removePathRecursively(file.absoluteFilePath()); + } + } +} + +QStringList IconList::getIconFilePaths() const +{ + QStringList icon_files {}; + QStringList directories {m_dir.absolutePath()}; + while (!directories.isEmpty()) { + QString first = directories.takeFirst(); + QDir dir(first); + for (QString& file_name : dir.entryList(QDir::AllDirs | QDir::Files |QDir::NoDotAndDotDot, QDir::Name)) { + QString full_path = dir.filePath(file_name); // Convert to full path + QFileInfo file_info(full_path); + if (file_info.isDir()) + directories.push_back(full_path); + else + icon_files.push_back(full_path); + } + } + return icon_files; +} + +QString formatName(const QDir& icons_dir, const QFileInfo& file) +{ + if (file.dir() == icons_dir) { + return file.baseName(); + } + else { + const QString delimiter = " » "; + return (icons_dir.relativeFilePath(file.dir().path()) + std::filesystem::path::preferred_separator + file.baseName()).replace(std::filesystem::path::preferred_separator, delimiter); + } +} + void IconList::directoryChanged(const QString& path) { QDir new_dir(path); @@ -95,13 +180,9 @@ void IconList::directoryChanged(const QString& path) if (!FS::ensureFolderPathExists(m_dir.absolutePath())) return; m_dir.refresh(); - auto new_list = m_dir.entryList(QDir::Files, QDir::Name); - for (auto it = new_list.begin(); it != new_list.end(); it++) { - QString& foo = (*it); - foo = m_dir.filePath(foo); - } + QStringList new_file_names_list = getIconFilePaths(); #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) - QSet new_set(new_list.begin(), new_list.end()); + QSet new_set(new_file_names_list.begin(), new_file_names_list.end()); #else auto new_set = new_list.toSet(); #endif @@ -123,21 +204,16 @@ void IconList::directoryChanged(const QString& path) QSet to_add = new_set; to_add -= current_set; - for (auto remove : to_remove) { + for (const auto& remove : to_remove) { qDebug() << "Removing " << remove; - QFileInfo rmfile(remove); - QString key = rmfile.completeBaseName(); - - QString suffix = rmfile.suffix(); - // The icon doesnt have a suffix, but it can have other .s in the name, so we account for those as well - if (!IconUtils::isIconSuffix(suffix)) - key = rmfile.fileName(); + QFileInfo removed_file(remove); + QString key = m_dir.relativeFilePath(removed_file.absoluteFilePath()); int idx = getIconIndex(key); if (idx == -1) continue; - icons[idx].remove(IconType::FileBased); - if (icons[idx].type() == IconType::ToBeDeleted) { + icons[idx].remove(FileBased); + if (icons[idx].type() == ToBeDeleted) { beginRemoveRows(QModelIndex(), idx, idx); icons.remove(idx); reindex(); @@ -149,18 +225,14 @@ void IconList::directoryChanged(const QString& path) emit iconUpdated(key); } - for (auto add : to_add) { + for (const auto& add : to_add) { qDebug() << "Adding " << add; QFileInfo addfile(add); - QString key = addfile.completeBaseName(); + QString key = m_dir.relativeFilePath(addfile.absoluteFilePath()); + QString name = formatName(m_dir, addfile); - QString suffix = addfile.suffix(); - // The icon doesnt have a suffix, but it can have other .s in the name, so we account for those as well - if (!IconUtils::isIconSuffix(suffix)) - key = addfile.fileName(); - - if (addIcon(key, QString(), addfile.filePath(), IconType::FileBased)) { + if (addIcon(key, name, addfile.filePath(), IconType::FileBased)) { m_watcher->addPath(add); emit iconUpdated(key); } @@ -175,7 +247,7 @@ void IconList::fileChanged(const QString& path) QFileInfo checkfile(path); if (!checkfile.exists()) return; - QString key = checkfile.completeBaseName(); + QString key = m_dir.relativeFilePath(checkfile.absoluteFilePath()); int idx = getIconIndex(key); if (idx == -1) return; @@ -200,7 +272,7 @@ void IconList::startWatching() { auto abs_path = m_dir.absolutePath(); FS::ensureFolderPathExists(abs_path); - is_watching = m_watcher->addPath(abs_path); + is_watching = addPathRecursively(abs_path); if (is_watching) { qDebug() << "Started watching " << abs_path; } else { @@ -312,6 +384,7 @@ bool IconList::iconFileExists(const QString& key) const return iconEntry && iconEntry->has(IconType::FileBased); } +/// Returns the icon with the given key or nullptr if it doesn't exist. const MMCIcon* IconList::icon(const QString& key) const { int iconIdx = getIconIndex(key); @@ -394,6 +467,7 @@ void IconList::reindex() for (auto& iter : icons) { name_index[iter.m_key] = i; i++; + emit iconUpdated(iter.m_key); // prevents incorrect indices with proxy model } } @@ -425,3 +499,15 @@ QString IconList::getDirectory() const { return m_dir.absolutePath(); } + +/// Returns the directory of the icon with the given key or the default directory if it's a builtin icon. +QString IconList::iconDirectory(const QString& key) const +{ + for (auto mmc_icon : icons) { + if (mmc_icon.m_key == key && mmc_icon.has(IconType::FileBased)) { + QFileInfo icon_file(mmc_icon.getFilePath()); + return icon_file.dir().path(); + } + } + return getDirectory(); +} diff --git a/launcher/icons/IconList.h b/launcher/icons/IconList.h index 553946c42..fcd172561 100644 --- a/launcher/icons/IconList.h +++ b/launcher/icons/IconList.h @@ -72,6 +72,7 @@ class IconList : public QAbstractListModel { bool deleteIcon(const QString& key); bool trashIcon(const QString& key); bool iconFileExists(const QString& key) const; + QString iconDirectory(const QString& key) const; void installIcons(const QStringList& iconFiles); void installIcon(const QString& file, const QString& name); @@ -91,6 +92,9 @@ class IconList : public QAbstractListModel { IconList& operator=(const IconList&) = delete; void reindex(); void sortIconList(); + bool addPathRecursively(const QString& path); + void removePathRecursively(const QString& path); + QStringList getIconFilePaths() const; public slots: void directoryChanged(const QString& path); diff --git a/launcher/ui/dialogs/IconPickerDialog.cpp b/launcher/ui/dialogs/IconPickerDialog.cpp index a196fd587..a3f1d7ea4 100644 --- a/launcher/ui/dialogs/IconPickerDialog.cpp +++ b/launcher/ui/dialogs/IconPickerDialog.cpp @@ -16,6 +16,8 @@ #include #include #include +#include +#include #include "Application.h" @@ -33,6 +35,15 @@ IconPickerDialog::IconPickerDialog(QWidget* parent) : QDialog(parent), ui(new Ui ui->setupUi(this); setWindowModality(Qt::WindowModal); + searchBar = new QLineEdit(this); + searchBar->setPlaceholderText(tr("Search...")); + ui->verticalLayout->insertWidget(0, searchBar); + + proxyModel = new QSortFilterProxyModel(this); + proxyModel->setSourceModel(APPLICATION->icons().get()); + proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive); + ui->iconView->setModel(proxyModel); + auto contentsWidget = ui->iconView; contentsWidget->setViewMode(QListView::IconMode); contentsWidget->setFlow(QListView::LeftToRight); @@ -57,7 +68,7 @@ IconPickerDialog::IconPickerDialog(QWidget* parent) : QDialog(parent), ui(new Ui contentsWidget->installEventFilter(this); - contentsWidget->setModel(APPLICATION->icons().get()); + contentsWidget->setModel(proxyModel); // NOTE: ResetRole forces the button to be on the left, while the OK/Cancel ones are on the right. We win. auto buttonAdd = ui->buttonBox->addButton(tr("Add Icon"), QDialogButtonBox::ResetRole); @@ -73,6 +84,9 @@ IconPickerDialog::IconPickerDialog(QWidget* parent) : QDialog(parent), ui(new Ui auto buttonFolder = ui->buttonBox->addButton(tr("Open Folder"), QDialogButtonBox::ResetRole); connect(buttonFolder, &QPushButton::clicked, this, &IconPickerDialog::openFolder); + connect(searchBar, &QLineEdit::textChanged, this, &IconPickerDialog::filterIcons); + // Prevent incorrect indices from e.g. filesystem changes + connect(APPLICATION->icons().get(), &IconList::iconUpdated, this, [this]() { proxyModel->invalidate(); }); } bool IconPickerDialog::eventFilter(QObject* obj, QEvent* evt) @@ -159,5 +173,10 @@ IconPickerDialog::~IconPickerDialog() void IconPickerDialog::openFolder() { - DesktopServices::openPath(APPLICATION->icons()->getDirectory(), true); + DesktopServices::openPath(APPLICATION->icons()->iconDirectory(selectedIconKey), true); } + +void IconPickerDialog::filterIcons(const QString& query) +{ + proxyModel->setFilterFixedString(query); +} \ No newline at end of file diff --git a/launcher/ui/dialogs/IconPickerDialog.h b/launcher/ui/dialogs/IconPickerDialog.h index 37e53dcce..db1315338 100644 --- a/launcher/ui/dialogs/IconPickerDialog.h +++ b/launcher/ui/dialogs/IconPickerDialog.h @@ -16,6 +16,8 @@ #pragma once #include #include +#include +#include namespace Ui { class IconPickerDialog; @@ -36,6 +38,8 @@ class IconPickerDialog : public QDialog { private: Ui::IconPickerDialog* ui; QPushButton* buttonRemove; + QLineEdit* searchBar; + QSortFilterProxyModel* proxyModel; private slots: void selectionChanged(QItemSelection, QItemSelection); @@ -44,4 +48,5 @@ class IconPickerDialog : public QDialog { void addNewIcon(); void removeSelectedIcon(); void openFolder(); + void filterIcons(const QString& text); }; From 40c3866f635bcb0c084f9afc5c9bcec4a50fa036 Mon Sep 17 00:00:00 2001 From: QazCetelic Date: Wed, 11 Sep 2024 09:22:28 +0200 Subject: [PATCH 13/80] clang-tidy formatting Signed-off-by: QazCetelic --- launcher/icons/IconList.cpp | 54 +++++++++++------------- launcher/icons/IconList.h | 4 +- launcher/ui/dialogs/IconPickerDialog.cpp | 2 +- 3 files changed, 28 insertions(+), 32 deletions(-) diff --git a/launcher/icons/IconList.cpp b/launcher/icons/IconList.cpp index 56ff10e51..a9d5bda98 100644 --- a/launcher/icons/IconList.cpp +++ b/launcher/icons/IconList.cpp @@ -47,19 +47,19 @@ #define MAX_SIZE 1024 -IconList::IconList(const QStringList& builtinPaths, QString path, QObject* parent) : QAbstractListModel(parent) +IconList::IconList(const QStringList& builtinPaths, const QString& path, QObject* parent) : QAbstractListModel(parent) { QSet builtinNames; // add builtin icons - for (auto& builtinPath : builtinPaths) { + for (const auto& builtinPath : builtinPaths) { QDir instance_icons(builtinPath); auto file_info_list = instance_icons.entryInfoList(QDir::Files, QDir::Name); - for (auto file_info : file_info_list) { + for (const auto& file_info : file_info_list) { builtinNames.insert(file_info.baseName()); } } - for (auto& builtinName : builtinNames) { + for (const auto& builtinName : builtinNames) { addThemeIcon(builtinName); } @@ -81,7 +81,7 @@ void IconList::sortIconList() bool aIsSubdir = a.m_key.contains(std::filesystem::path::preferred_separator); bool bIsSubdir = b.m_key.contains(std::filesystem::path::preferred_separator); if (aIsSubdir != bIsSubdir) { - return !aIsSubdir; // root-level icons come first + return !aIsSubdir; // root-level icons come first } return a.m_key.localeAwareCompare(b.m_key) < 0; }); @@ -102,10 +102,8 @@ bool IconList::addPathRecursively(const QString& path) // Add all subdirectories QFileInfoList entries = dir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot); - for (const QFileInfo& entry : entries) - { - if (addPathRecursively(entry.absoluteFilePath())) - { + for (const QFileInfo& entry : entries) { + if (addPathRecursively(entry.absoluteFilePath())) { watching = true; } } @@ -122,15 +120,13 @@ void IconList::removePathRecursively(const QString& path) if (idx == -1) return; - } - else if (file_info.isDir()) { + } else if (file_info.isDir()) { // Remove the directory itself m_watcher->removePath(path); const QDir dir(path); // Remove all files within the directory - for (const QFileInfo& file : dir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot)) - { + for (const QFileInfo& file : dir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot)) { removePathRecursively(file.absoluteFilePath()); } } @@ -138,13 +134,13 @@ void IconList::removePathRecursively(const QString& path) QStringList IconList::getIconFilePaths() const { - QStringList icon_files {}; - QStringList directories {m_dir.absolutePath()}; + QStringList icon_files{}; + QStringList directories{ m_dir.absolutePath() }; while (!directories.isEmpty()) { QString first = directories.takeFirst(); QDir dir(first); - for (QString& file_name : dir.entryList(QDir::AllDirs | QDir::Files |QDir::NoDotAndDotDot, QDir::Name)) { - QString full_path = dir.filePath(file_name); // Convert to full path + for (QString& file_name : dir.entryList(QDir::AllDirs | QDir::Files | QDir::NoDotAndDotDot, QDir::Name)) { + QString full_path = dir.filePath(file_name); // Convert to full path QFileInfo file_info(full_path); if (file_info.isDir()) directories.push_back(full_path); @@ -159,10 +155,10 @@ QString formatName(const QDir& icons_dir, const QFileInfo& file) { if (file.dir() == icons_dir) { return file.baseName(); - } - else { + } else { const QString delimiter = " » "; - return (icons_dir.relativeFilePath(file.dir().path()) + std::filesystem::path::preferred_separator + file.baseName()).replace(std::filesystem::path::preferred_separator, delimiter); + return (icons_dir.relativeFilePath(file.dir().path()) + std::filesystem::path::preferred_separator + file.baseName()) + .replace(std::filesystem::path::preferred_separator, delimiter); } } @@ -252,7 +248,7 @@ void IconList::fileChanged(const QString& path) if (idx == -1) return; QIcon icon(path); - if (!icon.availableSizes().size()) + if (icon.availableSizes().empty()) return; icons[idx].m_images[IconType::FileBased].icon = icon; @@ -260,7 +256,7 @@ void IconList::fileChanged(const QString& path) emit iconUpdated(key); } -void IconList::SettingChanged(const Setting& setting, QVariant value) +void IconList::SettingChanged(const Setting& setting, const QVariant& value) { if (setting.id() != "IconsDir") return; @@ -335,12 +331,12 @@ Qt::ItemFlags IconList::flags(const QModelIndex& index) const QVariant IconList::data(const QModelIndex& index, int role) const { if (!index.isValid()) - return QVariant(); + return {}; int row = index.row(); if (row < 0 || row >= icons.size()) - return QVariant(); + return {}; switch (role) { case Qt::DecorationRole: @@ -350,7 +346,7 @@ QVariant IconList::data(const QModelIndex& index, int role) const case Qt::UserRole: return icons[row].m_key; default: - return QVariant(); + return {}; } } @@ -361,7 +357,7 @@ int IconList::rowCount(const QModelIndex& parent) const void IconList::installIcons(const QStringList& iconFiles) { - for (QString file : iconFiles) + for (const QString& file : iconFiles) installIcon(file, {}); } @@ -467,7 +463,7 @@ void IconList::reindex() for (auto& iter : icons) { name_index[iter.m_key] = i; i++; - emit iconUpdated(iter.m_key); // prevents incorrect indices with proxy model + emit iconUpdated(iter.m_key); // prevents incorrect indices with proxy model } } @@ -483,7 +479,7 @@ QIcon IconList::getIcon(const QString& key) const if (icon_index != -1) return icons[icon_index].icon(); - return QIcon(); + return {}; } int IconList::getIconIndex(const QString& key) const @@ -503,7 +499,7 @@ QString IconList::getDirectory() const /// Returns the directory of the icon with the given key or the default directory if it's a builtin icon. QString IconList::iconDirectory(const QString& key) const { - for (auto mmc_icon : icons) { + for (const auto& mmc_icon : icons) { if (mmc_icon.m_key == key && mmc_icon.has(IconType::FileBased)) { QFileInfo icon_file(mmc_icon.getFilePath()); return icon_file.dir().path(); diff --git a/launcher/icons/IconList.h b/launcher/icons/IconList.h index fcd172561..6213b7da3 100644 --- a/launcher/icons/IconList.h +++ b/launcher/icons/IconList.h @@ -51,7 +51,7 @@ class QFileSystemWatcher; class IconList : public QAbstractListModel { Q_OBJECT public: - explicit IconList(const QStringList& builtinPaths, QString path, QObject* parent = 0); + explicit IconList(const QStringList& builtinPaths, const QString& path, QObject* parent = 0); virtual ~IconList() {}; QIcon getIcon(const QString& key) const; @@ -101,7 +101,7 @@ class IconList : public QAbstractListModel { protected slots: void fileChanged(const QString& path); - void SettingChanged(const Setting& setting, QVariant value); + void SettingChanged(const Setting& setting, const QVariant& value); private: shared_qobject_ptr m_watcher; diff --git a/launcher/ui/dialogs/IconPickerDialog.cpp b/launcher/ui/dialogs/IconPickerDialog.cpp index a3f1d7ea4..80effec07 100644 --- a/launcher/ui/dialogs/IconPickerDialog.cpp +++ b/launcher/ui/dialogs/IconPickerDialog.cpp @@ -15,9 +15,9 @@ #include #include +#include #include #include -#include #include "Application.h" From 0a576a0f6725aa2db1cdad7c153bfac25f2caef7 Mon Sep 17 00:00:00 2001 From: QazCetelic Date: Wed, 11 Sep 2024 09:31:16 +0200 Subject: [PATCH 14/80] fixes for ci errors Signed-off-by: QazCetelic --- launcher/icons/IconList.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/launcher/icons/IconList.cpp b/launcher/icons/IconList.cpp index a9d5bda98..824bee617 100644 --- a/launcher/icons/IconList.cpp +++ b/launcher/icons/IconList.cpp @@ -35,6 +35,7 @@ */ #include "IconList.h" +#include #include #include #include @@ -180,7 +181,7 @@ void IconList::directoryChanged(const QString& path) #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) QSet new_set(new_file_names_list.begin(), new_file_names_list.end()); #else - auto new_set = new_list.toSet(); + auto new_set = new_file_names_list.toSet(); #endif QList current_list; for (auto& it : icons) { From 506ec642733e9c7c11ccb7c72619697c52307687 Mon Sep 17 00:00:00 2001 From: QazCetelic Date: Wed, 11 Sep 2024 09:43:45 +0200 Subject: [PATCH 15/80] fixes for ci errors II Signed-off-by: QazCetelic --- launcher/icons/IconList.cpp | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/launcher/icons/IconList.cpp b/launcher/icons/IconList.cpp index 824bee617..66f6ad1f3 100644 --- a/launcher/icons/IconList.cpp +++ b/launcher/icons/IconList.cpp @@ -35,7 +35,6 @@ */ #include "IconList.h" -#include #include #include #include @@ -154,13 +153,13 @@ QStringList IconList::getIconFilePaths() const QString formatName(const QDir& icons_dir, const QFileInfo& file) { - if (file.dir() == icons_dir) { + if (file.dir() == icons_dir) return file.baseName(); - } else { - const QString delimiter = " » "; - return (icons_dir.relativeFilePath(file.dir().path()) + std::filesystem::path::preferred_separator + file.baseName()) - .replace(std::filesystem::path::preferred_separator, delimiter); - } + + constexpr auto delimiter = " » "; + constexpr auto fs_separator = std::filesystem::path::preferred_separator; + QString relative_path_without_extension = icons_dir.relativeFilePath(file.dir().path()) + fs_separator + file.baseName(); + return relative_path_without_extension.replace(fs_separator, delimiter); } void IconList::directoryChanged(const QString& path) @@ -311,7 +310,7 @@ bool IconList::dropMimeData(const QMimeData* data, if (data->hasUrls()) { auto urls = data->urls(); QStringList iconFiles; - for (auto url : urls) { + for (const auto& url : urls) { // only local files may be dropped... if (!url.isLocalFile()) continue; From f7f7c4b43ef2871d71fb3214bcafbd32e77bf85d Mon Sep 17 00:00:00 2001 From: QazCetelic Date: Wed, 11 Sep 2024 09:55:27 +0200 Subject: [PATCH 16/80] fixes for ci errors III Signed-off-by: QazCetelic --- launcher/icons/IconList.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/launcher/icons/IconList.cpp b/launcher/icons/IconList.cpp index 66f6ad1f3..df1905502 100644 --- a/launcher/icons/IconList.cpp +++ b/launcher/icons/IconList.cpp @@ -35,6 +35,7 @@ */ #include "IconList.h" +#include #include #include #include From 7b49fd65085b662875ed673b5319d2155efce5bd Mon Sep 17 00:00:00 2001 From: QazCetelic Date: Wed, 11 Sep 2024 10:07:05 +0200 Subject: [PATCH 17/80] fixes for ci errors IV Signed-off-by: QazCetelic --- launcher/icons/IconList.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/launcher/icons/IconList.cpp b/launcher/icons/IconList.cpp index df1905502..e226ab471 100644 --- a/launcher/icons/IconList.cpp +++ b/launcher/icons/IconList.cpp @@ -35,7 +35,6 @@ */ #include "IconList.h" -#include #include #include #include @@ -79,8 +78,8 @@ void IconList::sortIconList() { qDebug() << "Sorting icon list..."; std::sort(icons.begin(), icons.end(), [](const MMCIcon& a, const MMCIcon& b) { - bool aIsSubdir = a.m_key.contains(std::filesystem::path::preferred_separator); - bool bIsSubdir = b.m_key.contains(std::filesystem::path::preferred_separator); + bool aIsSubdir = a.m_key.contains(QDir::separator()); + bool bIsSubdir = b.m_key.contains(QDir::separator()); if (aIsSubdir != bIsSubdir) { return !aIsSubdir; // root-level icons come first } @@ -158,9 +157,8 @@ QString formatName(const QDir& icons_dir, const QFileInfo& file) return file.baseName(); constexpr auto delimiter = " » "; - constexpr auto fs_separator = std::filesystem::path::preferred_separator; - QString relative_path_without_extension = icons_dir.relativeFilePath(file.dir().path()) + fs_separator + file.baseName(); - return relative_path_without_extension.replace(fs_separator, delimiter); + QString relative_path_without_extension = icons_dir.relativeFilePath(file.dir().path()) + QDir::separator() + file.baseName(); + return relative_path_without_extension.replace(QDir::separator(), delimiter); } void IconList::directoryChanged(const QString& path) From e35faa5522449a8ed65bd855274ce6e54492ba42 Mon Sep 17 00:00:00 2001 From: QazCetelic Date: Sun, 15 Sep 2024 09:04:23 +0200 Subject: [PATCH 18/80] Feedback I Signed-off-by: QazCetelic --- launcher/icons/IconList.cpp | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/launcher/icons/IconList.cpp b/launcher/icons/IconList.cpp index e226ab471..b60e67bec 100644 --- a/launcher/icons/IconList.cpp +++ b/launcher/icons/IconList.cpp @@ -95,10 +95,8 @@ bool IconList::addPathRecursively(const QString& path) if (!dir.exists()) return false; - bool watching = false; - // Add the directory itself - watching = m_watcher->addPath(path); + bool watching = m_watcher->addPath(path); // Add all subdirectories QFileInfoList entries = dir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot); @@ -134,21 +132,19 @@ void IconList::removePathRecursively(const QString& path) QStringList IconList::getIconFilePaths() const { - QStringList icon_files{}; + QStringList iconFiles{}; QStringList directories{ m_dir.absolutePath() }; while (!directories.isEmpty()) { QString first = directories.takeFirst(); QDir dir(first); - for (QString& file_name : dir.entryList(QDir::AllDirs | QDir::Files | QDir::NoDotAndDotDot, QDir::Name)) { - QString full_path = dir.filePath(file_name); // Convert to full path - QFileInfo file_info(full_path); - if (file_info.isDir()) - directories.push_back(full_path); + for (QFileInfo& fileInfo : dir.entryInfoList(QDir::AllDirs | QDir::Files | QDir::NoDotAndDotDot, QDir::Name)) { + if (fileInfo.isDir()) + directories.push_back(fileInfo.absoluteFilePath()); else - icon_files.push_back(full_path); + iconFiles.push_back(fileInfo.absoluteFilePath()); } } - return icon_files; + return iconFiles; } QString formatName(const QDir& icons_dir, const QFileInfo& file) @@ -157,8 +153,8 @@ QString formatName(const QDir& icons_dir, const QFileInfo& file) return file.baseName(); constexpr auto delimiter = " » "; - QString relative_path_without_extension = icons_dir.relativeFilePath(file.dir().path()) + QDir::separator() + file.baseName(); - return relative_path_without_extension.replace(QDir::separator(), delimiter); + QString relativePathWithoutExtension = icons_dir.relativeFilePath(file.dir().path()) + QDir::separator() + file.baseName(); + return relativePathWithoutExtension.replace(QDir::separator(), delimiter); } void IconList::directoryChanged(const QString& path) From a58e81d7441ad5887e0bb3d7f7b3ab1887115341 Mon Sep 17 00:00:00 2001 From: QazCetelic Date: Tue, 24 Sep 2024 09:58:47 +0200 Subject: [PATCH 19/80] snake_case to camelCase Signed-off-by: QazCetelic --- launcher/icons/IconList.cpp | 38 ++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/launcher/icons/IconList.cpp b/launcher/icons/IconList.cpp index b60e67bec..016affe29 100644 --- a/launcher/icons/IconList.cpp +++ b/launcher/icons/IconList.cpp @@ -147,13 +147,13 @@ QStringList IconList::getIconFilePaths() const return iconFiles; } -QString formatName(const QDir& icons_dir, const QFileInfo& file) +QString formatName(const QDir& iconsDir, const QFileInfo& file) { - if (file.dir() == icons_dir) + if (file.dir() == iconsDir) return file.baseName(); constexpr auto delimiter = " » "; - QString relativePathWithoutExtension = icons_dir.relativeFilePath(file.dir().path()) + QDir::separator() + file.baseName(); + QString relativePathWithoutExtension = iconsDir.relativeFilePath(file.dir().path()) + QDir::separator() + file.baseName(); return relativePathWithoutExtension.replace(QDir::separator(), delimiter); } @@ -171,9 +171,9 @@ void IconList::directoryChanged(const QString& path) if (!FS::ensureFolderPathExists(m_dir.absolutePath())) return; m_dir.refresh(); - QStringList new_file_names_list = getIconFilePaths(); + QStringList newFileNamesList = getIconFilePaths(); #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) - QSet new_set(new_file_names_list.begin(), new_file_names_list.end()); + QSet new_set(newFileNamesList.begin(), newFileNamesList.end()); #else auto new_set = new_file_names_list.toSet(); #endif @@ -192,13 +192,13 @@ void IconList::directoryChanged(const QString& path) QSet to_remove = current_set; to_remove -= new_set; - QSet to_add = new_set; - to_add -= current_set; + QSet toAdd = new_set; + toAdd -= current_set; for (const auto& remove : to_remove) { qDebug() << "Removing " << remove; - QFileInfo removed_file(remove); - QString key = m_dir.relativeFilePath(removed_file.absoluteFilePath()); + QFileInfo removedFile(remove); + QString key = m_dir.relativeFilePath(removedFile.absoluteFilePath()); int idx = getIconIndex(key); if (idx == -1) @@ -216,7 +216,7 @@ void IconList::directoryChanged(const QString& path) emit iconUpdated(key); } - for (const auto& add : to_add) { + for (const auto& add : toAdd) { qDebug() << "Adding " << add; QFileInfo addfile(add); @@ -464,16 +464,16 @@ void IconList::reindex() QIcon IconList::getIcon(const QString& key) const { - int icon_index = getIconIndex(key); + int iconIndex = getIconIndex(key); - if (icon_index != -1) - return icons[icon_index].icon(); + if (iconIndex != -1) + return icons[iconIndex].icon(); // Fallback for icons that don't exist. - icon_index = getIconIndex("grass"); + iconIndex = getIconIndex("grass"); - if (icon_index != -1) - return icons[icon_index].icon(); + if (iconIndex != -1) + return icons[iconIndex].icon(); return {}; } @@ -494,9 +494,9 @@ QString IconList::getDirectory() const /// Returns the directory of the icon with the given key or the default directory if it's a builtin icon. QString IconList::iconDirectory(const QString& key) const { - for (const auto& mmc_icon : icons) { - if (mmc_icon.m_key == key && mmc_icon.has(IconType::FileBased)) { - QFileInfo icon_file(mmc_icon.getFilePath()); + for (const auto& mmcIcon : icons) { + if (mmcIcon.m_key == key && mmcIcon.has(IconType::FileBased)) { + QFileInfo icon_file(mmcIcon.getFilePath()); return icon_file.dir().path(); } } From b675406b1ad3b56e67ee56605d2f85a8f0947246 Mon Sep 17 00:00:00 2001 From: QazCetelic Date: Tue, 24 Sep 2024 10:16:26 +0200 Subject: [PATCH 20/80] Split set creation into a separate function for readability Signed-off-by: QazCetelic --- launcher/icons/IconList.cpp | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/launcher/icons/IconList.cpp b/launcher/icons/IconList.cpp index 016affe29..0903131ce 100644 --- a/launcher/icons/IconList.cpp +++ b/launcher/icons/IconList.cpp @@ -157,6 +157,16 @@ QString formatName(const QDir& iconsDir, const QFileInfo& file) return relativePathWithoutExtension.replace(QDir::separator(), delimiter); } +QSet toStringSet(const QList& list) // Split into a separate function because the preprocessing impedes readability +{ +#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) + QSet set(list.begin(), list.end()); +#else + auto set = list.toSet(); +#endif + return set; +} + void IconList::directoryChanged(const QString& path) { QDir new_dir(path); @@ -171,31 +181,23 @@ void IconList::directoryChanged(const QString& path) if (!FS::ensureFolderPathExists(m_dir.absolutePath())) return; m_dir.refresh(); - QStringList newFileNamesList = getIconFilePaths(); -#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) - QSet new_set(newFileNamesList.begin(), newFileNamesList.end()); -#else - auto new_set = new_file_names_list.toSet(); -#endif + const QStringList newFileNamesList = getIconFilePaths(); + const QSet newSet = toStringSet(newFileNamesList); QList current_list; for (auto& it : icons) { if (!it.has(IconType::FileBased)) continue; current_list.push_back(it.m_images[IconType::FileBased].filename); } -#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) - QSet current_set(current_list.begin(), current_list.end()); -#else - QSet current_set = current_list.toSet(); -#endif + const QSet currentSet = toStringSet(current_list); - QSet to_remove = current_set; - to_remove -= new_set; + QSet toRemove = currentSet; + toRemove -= newSet; - QSet toAdd = new_set; - toAdd -= current_set; + QSet toAdd = newSet; + toAdd -= currentSet; - for (const auto& remove : to_remove) { + for (const auto& remove : toRemove) { qDebug() << "Removing " << remove; QFileInfo removedFile(remove); QString key = m_dir.relativeFilePath(removedFile.absoluteFilePath()); From f641f3acda6e96ad18dd24e16eee62e50e7bb29b Mon Sep 17 00:00:00 2001 From: QazCetelic Date: Tue, 24 Sep 2024 12:32:49 +0200 Subject: [PATCH 21/80] Refactoring Signed-off-by: QazCetelic --- launcher/icons/IconList.cpp | 29 +++++++++++------------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/launcher/icons/IconList.cpp b/launcher/icons/IconList.cpp index 0903131ce..0edc97681 100644 --- a/launcher/icons/IconList.cpp +++ b/launcher/icons/IconList.cpp @@ -169,8 +169,8 @@ QSet toStringSet(const QList& list) // Split into a separate f void IconList::directoryChanged(const QString& path) { - QDir new_dir(path); - if (m_dir.absolutePath() != new_dir.absolutePath()) { + QDir newDir(path); + if (m_dir.absolutePath() != newDir.absolutePath()) { m_dir.setPath(path); m_dir.refresh(); if (is_watching) @@ -183,19 +183,14 @@ void IconList::directoryChanged(const QString& path) m_dir.refresh(); const QStringList newFileNamesList = getIconFilePaths(); const QSet newSet = toStringSet(newFileNamesList); - QList current_list; - for (auto& it : icons) { + QSet currentSet; + for (const MMCIcon& it : icons) { if (!it.has(IconType::FileBased)) continue; - current_list.push_back(it.m_images[IconType::FileBased].filename); + currentSet.insert(it.m_images[IconType::FileBased].filename); } - const QSet currentSet = toStringSet(current_list); - - QSet toRemove = currentSet; - toRemove -= newSet; - - QSet toAdd = newSet; - toAdd -= currentSet; + QSet toRemove = currentSet - newSet; + QSet toAdd = newSet - currentSet; for (const auto& remove : toRemove) { qDebug() << "Removing " << remove; @@ -456,11 +451,9 @@ void IconList::saveIcon(const QString& key, const QString& path, const char* for void IconList::reindex() { name_index.clear(); - int i = 0; - for (auto& iter : icons) { - name_index[iter.m_key] = i; - i++; - emit iconUpdated(iter.m_key); // prevents incorrect indices with proxy model + for (int i = 0; i < icons.size(); i++) { + name_index[icons[i].m_key] = i; + emit iconUpdated(icons[i].m_key); // prevents incorrect indices with proxy model } } @@ -471,7 +464,7 @@ QIcon IconList::getIcon(const QString& key) const if (iconIndex != -1) return icons[iconIndex].icon(); - // Fallback for icons that don't exist. + // Fallback for icons that don't exist.b iconIndex = getIconIndex("grass"); if (iconIndex != -1) From 5b6d551650e4590567321647ce68ae2043a8180c Mon Sep 17 00:00:00 2001 From: Edgars Cirulis Date: Thu, 10 Oct 2024 03:45:35 +0300 Subject: [PATCH 22/80] chore: update Qt to 6.8.0 Signed-off-by: Edgars Cirulis --- .github/workflows/build.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5dc02edf3..39dc2305e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -82,7 +82,7 @@ jobs: qt_ver: 6 qt_host: windows qt_arch: "" - qt_version: "6.7.3" + qt_version: "6.8.0" qt_modules: "qt5compat qtimageformats qtnetworkauth" nscurl_tag: "v24.9.26.122" nscurl_sha256: "AEE6C4BE3CB6455858E9C1EE4B3AFE0DB9960FA03FE99CCDEDC28390D57CCBB0" @@ -95,7 +95,7 @@ jobs: qt_ver: 6 qt_host: windows qt_arch: "win64_msvc2019_arm64" - qt_version: "6.7.3" + qt_version: "6.8.0" qt_modules: "qt5compat qtimageformats qtnetworkauth" nscurl_tag: "v24.9.26.122" nscurl_sha256: "AEE6C4BE3CB6455858E9C1EE4B3AFE0DB9960FA03FE99CCDEDC28390D57CCBB0" @@ -106,7 +106,7 @@ jobs: qt_ver: 6 qt_host: mac qt_arch: "" - qt_version: "6.7.3" + qt_version: "6.8.0" qt_modules: "qt5compat qtimageformats qtnetworkauth" - os: macos-14 From b39098dbc5b371e31ce585f7534ffdb00096c2b5 Mon Sep 17 00:00:00 2001 From: Edgars Cirulis Date: Thu, 10 Oct 2024 03:47:11 +0300 Subject: [PATCH 23/80] ci: fix qt-6.8 workflow Signed-off-by: Edgars Cirulis --- .github/workflows/build.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 39dc2305e..017bc68e9 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -80,8 +80,8 @@ jobs: architecture: "x64" vcvars_arch: "amd64" qt_ver: 6 - qt_host: windows - qt_arch: "" + qt_host: "windows" + qt_arch: "win64_msvc2022_64" qt_version: "6.8.0" qt_modules: "qt5compat qtimageformats qtnetworkauth" nscurl_tag: "v24.9.26.122" @@ -93,8 +93,8 @@ jobs: architecture: "arm64" vcvars_arch: "amd64_arm64" qt_ver: 6 - qt_host: windows - qt_arch: "win64_msvc2019_arm64" + qt_host: "windows" + qt_arch: "win64_msvc2022_arm64_cross_compiled" qt_version: "6.8.0" qt_modules: "qt5compat qtimageformats qtnetworkauth" nscurl_tag: "v24.9.26.122" @@ -223,7 +223,7 @@ jobs: version: ${{ matrix.qt_version }} host: "windows" target: "desktop" - arch: "" + arch: ${{ matrix.qt_arch }} modules: ${{ matrix.qt_modules }} cache: ${{ inputs.is_qt_cached }} cache-key-prefix: host-qt-arm64-windows @@ -264,7 +264,7 @@ jobs: - name: Add QT_HOST_PATH var (Windows MSVC arm64) if: runner.os == 'Windows' && matrix.architecture == 'arm64' run: | - echo "QT_HOST_PATH=${{ github.workspace }}\HostQt\Qt\${{ matrix.qt_version }}\msvc2019_64" >> $env:GITHUB_ENV + echo "QT_HOST_PATH=${{ github.workspace }}\HostQt\Qt\${{ matrix.qt_version }}\msvc2022_64" >> $env:GITHUB_ENV - name: Setup java (macOS) if: runner.os == 'macOS' From 0beaa94311a00cdc02ef5ff7d182849fce419aa9 Mon Sep 17 00:00:00 2001 From: Edgars Cirulis Date: Thu, 10 Oct 2024 15:23:48 +0300 Subject: [PATCH 24/80] ci: uprev qt install action to v4 Signed-off-by: Edgars Cirulis --- .github/workflows/build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 017bc68e9..a96278ba3 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -216,7 +216,7 @@ jobs: - name: Install host Qt (Windows MSVC arm64) if: runner.os == 'Windows' && matrix.architecture == 'arm64' - uses: jurplel/install-qt-action@v3 + uses: jurplel/install-qt-action@v4 with: aqtversion: "==3.1.*" py7zrversion: ">=0.20.2" @@ -232,7 +232,7 @@ jobs: - name: Install Qt (macOS, Linux & Windows MSVC) if: matrix.msystem == '' - uses: jurplel/install-qt-action@v3 + uses: jurplel/install-qt-action@v4 with: aqtversion: "==3.1.*" py7zrversion: ">=0.20.2" From 08f5148a9a4e574dd3ef4e7dc1e46a05ffd9dd5e Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 6 Oct 2023 09:17:03 +0300 Subject: [PATCH 25/80] Added mouse interactions for labels in ProgressDialog Signed-off-by: Trial97 --- launcher/ui/dialogs/ProfileSetupDialog.ui | 3 +++ launcher/ui/widgets/SubTaskProgressBar.ui | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/launcher/ui/dialogs/ProfileSetupDialog.ui b/launcher/ui/dialogs/ProfileSetupDialog.ui index 9dbabb4b3..947110da7 100644 --- a/launcher/ui/dialogs/ProfileSetupDialog.ui +++ b/launcher/ui/dialogs/ProfileSetupDialog.ui @@ -30,6 +30,9 @@ Choose your name carefully: true + + Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + nameEdit diff --git a/launcher/ui/widgets/SubTaskProgressBar.ui b/launcher/ui/widgets/SubTaskProgressBar.ui index 5431eab60..aabb68329 100644 --- a/launcher/ui/widgets/SubTaskProgressBar.ui +++ b/launcher/ui/widgets/SubTaskProgressBar.ui @@ -47,6 +47,9 @@ true + + Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + @@ -68,6 +71,9 @@ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + From c12beb43a0f3dad6e66fd42192dbbf1f78fb6c53 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Mon, 21 Aug 2023 19:47:47 +0300 Subject: [PATCH 26/80] correctly expand env vars Signed-off-by: Trial97 --- launcher/launch/LaunchTask.cpp | 62 +++++++++++++++++---- launcher/launch/LaunchTask.h | 3 +- launcher/launch/steps/PostLaunchCommand.cpp | 12 ++-- launcher/launch/steps/PreLaunchCommand.cpp | 13 ++--- 4 files changed, 60 insertions(+), 30 deletions(-) diff --git a/launcher/launch/LaunchTask.cpp b/launcher/launch/LaunchTask.cpp index 0251b302d..976221471 100644 --- a/launcher/launch/LaunchTask.cpp +++ b/launcher/launch/LaunchTask.cpp @@ -254,20 +254,60 @@ void LaunchTask::emitFailed(QString reason) Task::emitFailed(reason); } -void LaunchTask::substituteVariables(QStringList& args) const +QString expandVariables(const QString& input, QProcessEnvironment dict) { - auto env = m_instance->createEnvironment(); + QString result = input; - for (auto key : env.keys()) { - args.replaceInStrings("$" + key, env.value(key)); + enum { base, maybeBrace, variable, brace } state = base; + int startIdx = -1; + for (int i = 0; i < result.length();) { + QChar c = result.at(i++); + switch (state) { + case base: + if (c == '$') + state = maybeBrace; + break; + case maybeBrace: + if (c == '{') { + state = brace; + startIdx = i; + } else if (c.isLetterOrNumber() || c == '_') { + state = variable; + startIdx = i - 1; + } else { + state = base; + } + break; + case brace: + if (c == '}') { + const auto res = dict.value(result.mid(startIdx, i - 1 - startIdx), ""); + if (!res.isEmpty()) { + result.replace(startIdx - 2, i - startIdx + 2, res); + i = startIdx - 2 + res.length(); + } + state = base; + } + break; + case variable: + if (!c.isLetterOrNumber() && c != '_') { + const auto res = dict.value(result.mid(startIdx, i - startIdx - 1), ""); + if (!res.isEmpty()) { + result.replace(startIdx - 1, i - startIdx, res); + i = startIdx - 1 + res.length(); + } + state = base; + } + break; + } } + if (state == variable) { + if (const auto res = dict.value(result.mid(startIdx), ""); !res.isEmpty()) + result.replace(startIdx - 1, result.length() - startIdx + 1, res); + } + return result; } -void LaunchTask::substituteVariables(QString& cmd) const +QString LaunchTask::substituteVariables(QString& cmd) const { - auto env = m_instance->createEnvironment(); - - for (auto key : env.keys()) { - cmd.replace("$" + key, env.value(key)); - } -} + return expandVariables(cmd, m_instance->createEnvironment()); +} \ No newline at end of file diff --git a/launcher/launch/LaunchTask.h b/launcher/launch/LaunchTask.h index 56065af5b..1f1b5222b 100644 --- a/launcher/launch/LaunchTask.h +++ b/launcher/launch/LaunchTask.h @@ -87,8 +87,7 @@ class LaunchTask : public Task { shared_qobject_ptr getLogModel(); public: - void substituteVariables(QStringList& args) const; - void substituteVariables(QString& cmd) const; + QString substituteVariables(QString& cmd) const; QString censorPrivateInfo(QString in); protected: /* methods */ diff --git a/launcher/launch/steps/PostLaunchCommand.cpp b/launcher/launch/steps/PostLaunchCommand.cpp index 725101224..946560c10 100644 --- a/launcher/launch/steps/PostLaunchCommand.cpp +++ b/launcher/launch/steps/PostLaunchCommand.cpp @@ -47,19 +47,15 @@ PostLaunchCommand::PostLaunchCommand(LaunchTask* parent) : LaunchStep(parent) void PostLaunchCommand::executeTask() { - // FIXME: where to put this? + auto cmd = m_parent->substituteVariables(m_command); + emit logLine(tr("Running Post-Launch command: %1").arg(cmd), MessageLevel::Launcher); #if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) - auto args = QProcess::splitCommand(m_command); - m_parent->substituteVariables(args); + auto args = QProcess::splitCommand(cmd); - emit logLine(tr("Running Post-Launch command: %1").arg(args.join(' ')), MessageLevel::Launcher); const QString program = args.takeFirst(); m_process.start(program, args); #else - m_parent->substituteVariables(m_command); - - emit logLine(tr("Running Post-Launch command: %1").arg(m_command), MessageLevel::Launcher); - m_process.start(m_command); + m_process.start(cmd); #endif } diff --git a/launcher/launch/steps/PreLaunchCommand.cpp b/launcher/launch/steps/PreLaunchCommand.cpp index 6d071a66e..3505febf7 100644 --- a/launcher/launch/steps/PreLaunchCommand.cpp +++ b/launcher/launch/steps/PreLaunchCommand.cpp @@ -47,19 +47,14 @@ PreLaunchCommand::PreLaunchCommand(LaunchTask* parent) : LaunchStep(parent) void PreLaunchCommand::executeTask() { - // FIXME: where to put this? + auto cmd = m_parent->substituteVariables(m_command); + emit logLine(tr("Running Pre-Launch command: %1").arg(cmd), MessageLevel::Launcher); #if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) - auto args = QProcess::splitCommand(m_command); - m_parent->substituteVariables(args); - - emit logLine(tr("Running Pre-Launch command: %1").arg(args.join(' ')), MessageLevel::Launcher); + auto args = QProcess::splitCommand(cmd); const QString program = args.takeFirst(); m_process.start(program, args); #else - m_parent->substituteVariables(m_command); - - emit logLine(tr("Running Pre-Launch command: %1").arg(m_command), MessageLevel::Launcher); - m_process.start(m_command); + m_process.start(cmd); #endif } From 09a118e85e3646ded9d7b2704d2f95a589ca19b9 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sat, 18 Nov 2023 11:18:50 +0200 Subject: [PATCH 27/80] expand env from wrapped cmd Signed-off-by: Trial97 --- launcher/launch/LaunchTask.cpp | 6 +++--- launcher/launch/LaunchTask.h | 2 +- launcher/minecraft/launch/LauncherPartLaunch.cpp | 1 + 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/launcher/launch/LaunchTask.cpp b/launcher/launch/LaunchTask.cpp index 976221471..4b93d2077 100644 --- a/launcher/launch/LaunchTask.cpp +++ b/launcher/launch/LaunchTask.cpp @@ -307,7 +307,7 @@ QString expandVariables(const QString& input, QProcessEnvironment dict) return result; } -QString LaunchTask::substituteVariables(QString& cmd) const +QString LaunchTask::substituteVariables(QString& cmd, bool isLaunch) const { - return expandVariables(cmd, m_instance->createEnvironment()); -} \ No newline at end of file + return expandVariables(cmd, isLaunch ? m_instance->createLaunchEnvironment() : m_instance->createEnvironment()); +} diff --git a/launcher/launch/LaunchTask.h b/launcher/launch/LaunchTask.h index 1f1b5222b..2e87ece95 100644 --- a/launcher/launch/LaunchTask.h +++ b/launcher/launch/LaunchTask.h @@ -87,7 +87,7 @@ class LaunchTask : public Task { shared_qobject_ptr getLogModel(); public: - QString substituteVariables(QString& cmd) const; + QString substituteVariables(QString& cmd, bool isLaunch = false) const; QString censorPrivateInfo(QString in); protected: /* methods */ diff --git a/launcher/minecraft/launch/LauncherPartLaunch.cpp b/launcher/minecraft/launch/LauncherPartLaunch.cpp index d9a2b9b6b..2e842632a 100644 --- a/launcher/minecraft/launch/LauncherPartLaunch.cpp +++ b/launcher/minecraft/launch/LauncherPartLaunch.cpp @@ -131,6 +131,7 @@ void LauncherPartLaunch::executeTask() QString wrapperCommandStr = instance->getWrapperCommand().trimmed(); if (!wrapperCommandStr.isEmpty()) { + wrapperCommandStr = m_parent->substituteVariables(wrapperCommandStr); auto wrapperArgs = Commandline::splitArgs(wrapperCommandStr); auto wrapperCommand = wrapperArgs.takeFirst(); auto realWrapperCommand = QStandardPaths::findExecutable(wrapperCommand); From f77f0207f779e2fe0df58f89295be3ef44853489 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 1 Nov 2024 13:44:06 +0200 Subject: [PATCH 28/80] fix the flame loaders match Signed-off-by: Trial97 --- launcher/minecraft/mod/Mod.cpp | 8 ++-- launcher/modplatform/ModIndex.cpp | 13 ++++++ launcher/modplatform/ModIndex.h | 1 + launcher/modplatform/flame/FlameAPI.cpp | 40 +++++++++++++------ launcher/modplatform/flame/FlameCheckUpdate.h | 1 - .../modrinth/ModrinthCheckUpdate.cpp | 12 +++--- launcher/modplatform/packwiz/Packwiz.cpp | 7 +--- launcher/ui/dialogs/ResourceUpdateDialog.cpp | 1 + 8 files changed, 52 insertions(+), 31 deletions(-) diff --git a/launcher/minecraft/mod/Mod.cpp b/launcher/minecraft/mod/Mod.cpp index 4986d8ee1..50fb45d77 100644 --- a/launcher/minecraft/mod/Mod.cpp +++ b/launcher/minecraft/mod/Mod.cpp @@ -48,6 +48,7 @@ #include "Version.h" #include "minecraft/mod/ModDetails.h" #include "minecraft/mod/tasks/LocalModParseTask.h" +#include "modplatform/ModIndex.h" Mod::Mod(const QFileInfo& file) : Resource(file), m_local_details() { @@ -157,11 +158,8 @@ auto Mod::loaders() const -> QString if (metadata()) { QStringList loaders; auto modLoaders = metadata()->loaders; - for (auto loader : { ModPlatform::NeoForge, ModPlatform::Forge, ModPlatform::Cauldron, ModPlatform::LiteLoader, ModPlatform::Fabric, - ModPlatform::Quilt }) { - if (modLoaders & loader) { - loaders << getModLoaderAsString(loader); - } + for (auto loader : ModPlatform::modLoaderTypesToList(modLoaders)) { + loaders << getModLoaderAsString(loader); } return loaders.join(", "); } diff --git a/launcher/modplatform/ModIndex.cpp b/launcher/modplatform/ModIndex.cpp index 8c85ae122..c3ecccf8e 100644 --- a/launcher/modplatform/ModIndex.cpp +++ b/launcher/modplatform/ModIndex.cpp @@ -31,6 +31,19 @@ static const QMap s_indexed_version_ty { "alpha", IndexedVersionType::VersionType::Alpha } }; +static const QList loaderList = { NeoForge, Forge, Cauldron, LiteLoader, Quilt, Fabric }; + +QList modLoaderTypesToList(ModLoaderTypes flags) +{ + QList flagList; + for (auto flag : loaderList) { + if (flags.testFlag(flag)) { + flagList.append(flag); + } + } + return flagList; +} + IndexedVersionType::IndexedVersionType(const QString& type) : IndexedVersionType(enumFromString(type)) {} IndexedVersionType::IndexedVersionType(const IndexedVersionType::VersionType& type) diff --git a/launcher/modplatform/ModIndex.h b/launcher/modplatform/ModIndex.h index d5ee12473..8fae1bf6c 100644 --- a/launcher/modplatform/ModIndex.h +++ b/launcher/modplatform/ModIndex.h @@ -32,6 +32,7 @@ namespace ModPlatform { enum ModLoaderType { NeoForge = 1 << 0, Forge = 1 << 1, Cauldron = 1 << 2, LiteLoader = 1 << 3, Fabric = 1 << 4, Quilt = 1 << 5 }; Q_DECLARE_FLAGS(ModLoaderTypes, ModLoaderType) +QList modLoaderTypesToList(ModLoaderTypes flags); enum class ResourceProvider { MODRINTH, FLAME }; diff --git a/launcher/modplatform/flame/FlameAPI.cpp b/launcher/modplatform/flame/FlameAPI.cpp index ddd48c2b1..53eadcf02 100644 --- a/launcher/modplatform/flame/FlameAPI.cpp +++ b/launcher/modplatform/flame/FlameAPI.cpp @@ -270,21 +270,35 @@ std::optional FlameAPI::getLatestVersion(QList instanceLoaders, ModPlatform::ModLoaderTypes modLoaders) { - // edge case: mod has installed for forge but the instance is fabric => fabric version will be prioritizated on update - auto bestVersion = [&versions](ModPlatform::ModLoaderTypes loader) { - std::optional ver; - for (auto file_tmp : versions) { - if (file_tmp.loaders & loader && (!ver.has_value() || file_tmp.date > ver->date)) { - ver = file_tmp; + QHash bestMatch; + auto checkVersion = [&bestMatch](const ModPlatform::IndexedVersion& version, const ModPlatform::ModLoaderType& loader) { + if (bestMatch.contains(loader)) { + auto best = bestMatch.value(loader); + if (version.date > best.date) { + bestMatch[loader] = version; + } + } else { + bestMatch[loader] = version; + } + }; + for (auto file_tmp : versions) { + auto loaders = ModPlatform::modLoaderTypesToList(file_tmp.loaders); + if (loaders.isEmpty()) { + checkVersion(file_tmp, ModPlatform::ModLoaderType(0)); + } else { + for (auto loader : loaders) { + checkVersion(file_tmp, loader); } } - return ver; - }; - for (auto l : instanceLoaders) { - auto ver = bestVersion(l); - if (ver.has_value()) { - return ver; + } + // edge case: mod has installed for forge but the instance is fabric => fabric version will be prioritizated on update + auto currentLoaders = instanceLoaders + ModPlatform::modLoaderTypesToList(modLoaders); + currentLoaders.append(ModPlatform::ModLoaderType(0)); // add a fallback in case the versions do not define a loader + + for (auto loader : currentLoaders) { + if (bestMatch.contains(loader)) { + return bestMatch.value(loader); } } - return bestVersion(modLoaders); + return {}; } diff --git a/launcher/modplatform/flame/FlameCheckUpdate.h b/launcher/modplatform/flame/FlameCheckUpdate.h index 2b5c6ac17..6543a0e04 100644 --- a/launcher/modplatform/flame/FlameCheckUpdate.h +++ b/launcher/modplatform/flame/FlameCheckUpdate.h @@ -1,6 +1,5 @@ #pragma once -#include "Application.h" #include "modplatform/CheckUpdateTask.h" #include "net/NetJob.h" diff --git a/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp b/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp index 52db95077..e86447989 100644 --- a/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp +++ b/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp @@ -8,6 +8,7 @@ #include "QObjectPtr.h" #include "ResourceDownloadTask.h" +#include "modplatform/ModIndex.h" #include "modplatform/helpers/HashUtils.h" #include "tasks/ConcurrentTask.h" @@ -99,8 +100,7 @@ void ModrinthCheckUpdate::checkVersionsResponse(std::shared_ptr resp // If the returned project is empty, but we have Modrinth metadata, // it means this specific version is not available if (project_obj.isEmpty()) { - qDebug() << "Mod " << m_mappings.find(hash).value()->name() << " got an empty response." - << "Hash: " << hash; + qDebug() << "Mod " << m_mappings.find(hash).value()->name() << " got an empty response." << "Hash: " << hash; ++iter; continue; } @@ -108,10 +108,8 @@ void ModrinthCheckUpdate::checkVersionsResponse(std::shared_ptr resp // Sometimes a version may have multiple files, one with "forge" and one with "fabric", // so we may want to filter it QString loader_filter; - static auto flags = { ModPlatform::ModLoaderType::NeoForge, ModPlatform::ModLoaderType::Forge, - ModPlatform::ModLoaderType::Quilt, ModPlatform::ModLoaderType::Fabric }; - for (auto flag : flags) { - if (loader.has_value() && loader->testFlag(flag)) { + if (loader.has_value()) { + for (auto flag : ModPlatform::modLoaderTypesToList(*loader)) { loader_filter = ModPlatform::getModLoaderAsString(flag); break; } @@ -173,7 +171,7 @@ void ModrinthCheckUpdate::checkNextLoader() m_loader_idx++; return; } - + if (m_loader_idx < m_loaders_list.size()) { getUpdateModsForLoader(m_loaders_list.at(m_loader_idx)); m_loader_idx++; diff --git a/launcher/modplatform/packwiz/Packwiz.cpp b/launcher/modplatform/packwiz/Packwiz.cpp index bbccb72b8..a3bb74399 100644 --- a/launcher/modplatform/packwiz/Packwiz.cpp +++ b/launcher/modplatform/packwiz/Packwiz.cpp @@ -190,11 +190,8 @@ void V1::updateModIndex(const QDir& index_dir, Mod& mod) } toml::array loaders; - for (auto loader : { ModPlatform::NeoForge, ModPlatform::Forge, ModPlatform::Cauldron, ModPlatform::LiteLoader, ModPlatform::Fabric, - ModPlatform::Quilt }) { - if (mod.loaders & loader) { - loaders.push_back(getModLoaderAsString(loader).toStdString()); - } + for (auto loader : ModPlatform::modLoaderTypesToList(mod.loaders)) { + loaders.push_back(getModLoaderAsString(loader).toStdString()); } toml::array mcVersions; for (auto version : mod.mcVersions) { diff --git a/launcher/ui/dialogs/ResourceUpdateDialog.cpp b/launcher/ui/dialogs/ResourceUpdateDialog.cpp index 958bc9683..bfa1fae2b 100644 --- a/launcher/ui/dialogs/ResourceUpdateDialog.cpp +++ b/launcher/ui/dialogs/ResourceUpdateDialog.cpp @@ -1,4 +1,5 @@ #include "ResourceUpdateDialog.h" +#include "Application.h" #include "ChooseProviderDialog.h" #include "CustomMessageBox.h" #include "ProgressDialog.h" From abbebff400a697023f159c2f00087031a470b577 Mon Sep 17 00:00:00 2001 From: QazCetelic Date: Sun, 17 Nov 2024 20:35:24 +0100 Subject: [PATCH 29/80] Removed bug when renaming icon file in nested folder while application is running Signed-off-by: QazCetelic --- launcher/icons/IconList.cpp | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/launcher/icons/IconList.cpp b/launcher/icons/IconList.cpp index 0edc97681..20a907ed3 100644 --- a/launcher/icons/IconList.cpp +++ b/launcher/icons/IconList.cpp @@ -147,22 +147,23 @@ QStringList IconList::getIconFilePaths() const return iconFiles; } -QString formatName(const QDir& iconsDir, const QFileInfo& file) +QString formatName(const QDir& iconsDir, const QFileInfo& iconFile) { - if (file.dir() == iconsDir) - return file.baseName(); + if (iconFile.dir() == iconsDir) + return iconFile.baseName(); constexpr auto delimiter = " » "; - QString relativePathWithoutExtension = iconsDir.relativeFilePath(file.dir().path()) + QDir::separator() + file.baseName(); + QString relativePathWithoutExtension = iconsDir.relativeFilePath(iconFile.dir().path()) + QDir::separator() + iconFile.baseName(); return relativePathWithoutExtension.replace(QDir::separator(), delimiter); } -QSet toStringSet(const QList& list) // Split into a separate function because the preprocessing impedes readability +/// Split into a separate function because the preprocessing impedes readability +QSet toStringSet(const QList& list) { #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) QSet set(list.begin(), list.end()); #else - auto set = list.toSet(); + QSet set = list.toSet(); #endif return set; } @@ -171,7 +172,8 @@ void IconList::directoryChanged(const QString& path) { QDir newDir(path); if (m_dir.absolutePath() != newDir.absolutePath()) { - m_dir.setPath(path); + if (!path.startsWith(m_dir.absolutePath())) + m_dir.setPath(path); m_dir.refresh(); if (is_watching) stopWatching(); @@ -192,9 +194,9 @@ void IconList::directoryChanged(const QString& path) QSet toRemove = currentSet - newSet; QSet toAdd = newSet - currentSet; - for (const auto& remove : toRemove) { - qDebug() << "Removing " << remove; - QFileInfo removedFile(remove); + for (const QString& removedPath : toRemove) { + qDebug() << "Removing icon " << removedPath; + QFileInfo removedFile(removedPath); QString key = m_dir.relativeFilePath(removedFile.absoluteFilePath()); int idx = getIconIndex(key); @@ -209,19 +211,19 @@ void IconList::directoryChanged(const QString& path) } else { dataChanged(index(idx), index(idx)); } - m_watcher->removePath(remove); + m_watcher->removePath(removedPath); emit iconUpdated(key); } - for (const auto& add : toAdd) { - qDebug() << "Adding " << add; + for (const QString& addedPath : toAdd) { + qDebug() << "Adding icon " << addedPath; - QFileInfo addfile(add); + QFileInfo addfile(addedPath); QString key = m_dir.relativeFilePath(addfile.absoluteFilePath()); QString name = formatName(m_dir, addfile); if (addIcon(key, name, addfile.filePath(), IconType::FileBased)) { - m_watcher->addPath(add); + m_watcher->addPath(addedPath); emit iconUpdated(key); } } @@ -231,7 +233,7 @@ void IconList::directoryChanged(const QString& path) void IconList::fileChanged(const QString& path) { - qDebug() << "Checking " << path; + qDebug() << "Checking icon " << path; QFileInfo checkfile(path); if (!checkfile.exists()) return; From e74592fa0968dce50e4bdc4cd6b06d0b3de06eca Mon Sep 17 00:00:00 2001 From: QazCetelic Date: Sun, 17 Nov 2024 20:43:09 +0100 Subject: [PATCH 30/80] Code style conventions (camelCase, m_ prefix) Signed-off-by: QazCetelic --- launcher/icons/IconList.cpp | 84 ++++++++++++++++++------------------- launcher/icons/IconList.h | 6 +-- 2 files changed, 45 insertions(+), 45 deletions(-) diff --git a/launcher/icons/IconList.cpp b/launcher/icons/IconList.cpp index 20a907ed3..9cfab903a 100644 --- a/launcher/icons/IconList.cpp +++ b/launcher/icons/IconList.cpp @@ -53,10 +53,10 @@ IconList::IconList(const QStringList& builtinPaths, const QString& path, QObject // add builtin icons for (const auto& builtinPath : builtinPaths) { - QDir instance_icons(builtinPath); - auto file_info_list = instance_icons.entryInfoList(QDir::Files, QDir::Name); - for (const auto& file_info : file_info_list) { - builtinNames.insert(file_info.baseName()); + QDir instanceIcons(builtinPath); + auto fileInfoList = instanceIcons.entryInfoList(QDir::Files, QDir::Name); + for (const auto& fileInfo : fileInfoList) { + builtinNames.insert(fileInfo.baseName()); } } for (const auto& builtinName : builtinNames) { @@ -64,7 +64,7 @@ IconList::IconList(const QStringList& builtinPaths, const QString& path, QObject } m_watcher.reset(new QFileSystemWatcher()); - is_watching = false; + m_is_watching = false; connect(m_watcher.get(), &QFileSystemWatcher::directoryChanged, this, &IconList::directoryChanged); connect(m_watcher.get(), &QFileSystemWatcher::fileChanged, this, &IconList::fileChanged); @@ -77,7 +77,7 @@ IconList::IconList(const QStringList& builtinPaths, const QString& path, QObject void IconList::sortIconList() { qDebug() << "Sorting icon list..."; - std::sort(icons.begin(), icons.end(), [](const MMCIcon& a, const MMCIcon& b) { + std::sort(m_icons.begin(), m_icons.end(), [](const MMCIcon& a, const MMCIcon& b) { bool aIsSubdir = a.m_key.contains(QDir::separator()); bool bIsSubdir = b.m_key.contains(QDir::separator()); if (aIsSubdir != bIsSubdir) { @@ -175,7 +175,7 @@ void IconList::directoryChanged(const QString& path) if (!path.startsWith(m_dir.absolutePath())) m_dir.setPath(path); m_dir.refresh(); - if (is_watching) + if (m_is_watching) stopWatching(); startWatching(); } @@ -186,7 +186,7 @@ void IconList::directoryChanged(const QString& path) const QStringList newFileNamesList = getIconFilePaths(); const QSet newSet = toStringSet(newFileNamesList); QSet currentSet; - for (const MMCIcon& it : icons) { + for (const MMCIcon& it : m_icons) { if (!it.has(IconType::FileBased)) continue; currentSet.insert(it.m_images[IconType::FileBased].filename); @@ -202,10 +202,10 @@ void IconList::directoryChanged(const QString& path) int idx = getIconIndex(key); if (idx == -1) continue; - icons[idx].remove(FileBased); - if (icons[idx].type() == ToBeDeleted) { + m_icons[idx].remove(FileBased); + if (m_icons[idx].type() == ToBeDeleted) { beginRemoveRows(QModelIndex(), idx, idx); - icons.remove(idx); + m_icons.remove(idx); reindex(); endRemoveRows(); } else { @@ -245,7 +245,7 @@ void IconList::fileChanged(const QString& path) if (icon.availableSizes().empty()) return; - icons[idx].m_images[IconType::FileBased].icon = icon; + m_icons[idx].m_images[IconType::FileBased].icon = icon; dataChanged(index(idx), index(idx)); emit iconUpdated(key); } @@ -262,8 +262,8 @@ void IconList::startWatching() { auto abs_path = m_dir.absolutePath(); FS::ensureFolderPathExists(abs_path); - is_watching = addPathRecursively(abs_path); - if (is_watching) { + m_is_watching = addPathRecursively(abs_path); + if (m_is_watching) { qDebug() << "Started watching " << abs_path; } else { qDebug() << "Failed to start watching " << abs_path; @@ -274,7 +274,7 @@ void IconList::stopWatching() { m_watcher->removePaths(m_watcher->files()); m_watcher->removePaths(m_watcher->directories()); - is_watching = false; + m_is_watching = false; } QStringList IconList::mimeTypes() const @@ -329,16 +329,16 @@ QVariant IconList::data(const QModelIndex& index, int role) const int row = index.row(); - if (row < 0 || row >= icons.size()) + if (row < 0 || row >= m_icons.size()) return {}; switch (role) { case Qt::DecorationRole: - return icons[row].icon(); + return m_icons[row].icon(); case Qt::DisplayRole: - return icons[row].name(); + return m_icons[row].name(); case Qt::UserRole: - return icons[row].m_key; + return m_icons[row].m_key; default: return {}; } @@ -346,7 +346,7 @@ QVariant IconList::data(const QModelIndex& index, int role) const int IconList::rowCount(const QModelIndex& parent) const { - return parent.isValid() ? 0 : icons.size(); + return parent.isValid() ? 0 : m_icons.size(); } void IconList::installIcons(const QStringList& iconFiles) @@ -380,7 +380,7 @@ const MMCIcon* IconList::icon(const QString& key) const int iconIdx = getIconIndex(key); if (iconIdx == -1) return nullptr; - return &icons[iconIdx]; + return &m_icons[iconIdx]; } bool IconList::deleteIcon(const QString& key) @@ -395,22 +395,22 @@ bool IconList::trashIcon(const QString& key) bool IconList::addThemeIcon(const QString& key) { - auto iter = name_index.find(key); - if (iter != name_index.end()) { - auto& oldOne = icons[*iter]; + auto iter = m_name_index.find(key); + if (iter != m_name_index.end()) { + auto& oldOne = m_icons[*iter]; oldOne.replace(Builtin, key); dataChanged(index(*iter), index(*iter)); return true; } // add a new icon - beginInsertRows(QModelIndex(), icons.size(), icons.size()); + beginInsertRows(QModelIndex(), m_icons.size(), m_icons.size()); { MMCIcon mmc_icon; mmc_icon.m_name = key; mmc_icon.m_key = key; mmc_icon.replace(Builtin, key); - icons.push_back(mmc_icon); - name_index[key] = icons.size() - 1; + m_icons.push_back(mmc_icon); + m_name_index[key] = m_icons.size() - 1; } endInsertRows(); return true; @@ -422,22 +422,22 @@ bool IconList::addIcon(const QString& key, const QString& name, const QString& p QIcon icon(path); if (icon.isNull()) return false; - auto iter = name_index.find(key); - if (iter != name_index.end()) { - auto& oldOne = icons[*iter]; + auto iter = m_name_index.find(key); + if (iter != m_name_index.end()) { + auto& oldOne = m_icons[*iter]; oldOne.replace(type, icon, path); dataChanged(index(*iter), index(*iter)); return true; } // add a new icon - beginInsertRows(QModelIndex(), icons.size(), icons.size()); + beginInsertRows(QModelIndex(), m_icons.size(), m_icons.size()); { MMCIcon mmc_icon; mmc_icon.m_name = name; mmc_icon.m_key = key; mmc_icon.replace(type, icon, path); - icons.push_back(mmc_icon); - name_index[key] = icons.size() - 1; + m_icons.push_back(mmc_icon); + m_name_index[key] = m_icons.size() - 1; } endInsertRows(); return true; @@ -452,10 +452,10 @@ void IconList::saveIcon(const QString& key, const QString& path, const char* for void IconList::reindex() { - name_index.clear(); - for (int i = 0; i < icons.size(); i++) { - name_index[icons[i].m_key] = i; - emit iconUpdated(icons[i].m_key); // prevents incorrect indices with proxy model + m_name_index.clear(); + for (int i = 0; i < m_icons.size(); i++) { + m_name_index[m_icons[i].m_key] = i; + emit iconUpdated(m_icons[i].m_key); // prevents incorrect indices with proxy model } } @@ -464,20 +464,20 @@ QIcon IconList::getIcon(const QString& key) const int iconIndex = getIconIndex(key); if (iconIndex != -1) - return icons[iconIndex].icon(); + return m_icons[iconIndex].icon(); // Fallback for icons that don't exist.b iconIndex = getIconIndex("grass"); if (iconIndex != -1) - return icons[iconIndex].icon(); + return m_icons[iconIndex].icon(); return {}; } int IconList::getIconIndex(const QString& key) const { - auto iter = name_index.find(key == "default" ? "grass" : key); - if (iter != name_index.end()) + auto iter = m_name_index.find(key == "default" ? "grass" : key); + if (iter != m_name_index.end()) return *iter; return -1; @@ -491,7 +491,7 @@ QString IconList::getDirectory() const /// Returns the directory of the icon with the given key or the default directory if it's a builtin icon. QString IconList::iconDirectory(const QString& key) const { - for (const auto& mmcIcon : icons) { + for (const auto& mmcIcon : m_icons) { if (mmcIcon.m_key == key && mmcIcon.has(IconType::FileBased)) { QFileInfo icon_file(mmcIcon.getFilePath()); return icon_file.dir().path(); diff --git a/launcher/icons/IconList.h b/launcher/icons/IconList.h index 6213b7da3..04c2738ef 100644 --- a/launcher/icons/IconList.h +++ b/launcher/icons/IconList.h @@ -105,8 +105,8 @@ class IconList : public QAbstractListModel { private: shared_qobject_ptr m_watcher; - bool is_watching; - QMap name_index; - QVector icons; + bool m_is_watching; + QMap m_name_index; + QVector m_icons; QDir m_dir; }; From 6ca18c62660baab20fe6a3e7fd7b6b05a837ce0d Mon Sep 17 00:00:00 2001 From: QazCetelic Date: Mon, 18 Nov 2024 19:19:02 +0100 Subject: [PATCH 31/80] Refactoring Signed-off-by: QazCetelic --- launcher/icons/IconList.cpp | 27 ++------------------------- launcher/icons/IconList.h | 1 - 2 files changed, 2 insertions(+), 26 deletions(-) diff --git a/launcher/icons/IconList.cpp b/launcher/icons/IconList.cpp index 9cfab903a..eb047b130 100644 --- a/launcher/icons/IconList.cpp +++ b/launcher/icons/IconList.cpp @@ -108,28 +108,6 @@ bool IconList::addPathRecursively(const QString& path) return watching; } -void IconList::removePathRecursively(const QString& path) -{ - QFileInfo file_info(path); - if (file_info.isFile()) { - // Remove the icon belonging to the file - QString key = m_dir.relativeFilePath(file_info.absoluteFilePath()); - int idx = getIconIndex(key); - if (idx == -1) - return; - - } else if (file_info.isDir()) { - // Remove the directory itself - m_watcher->removePath(path); - - const QDir dir(path); - // Remove all files within the directory - for (const QFileInfo& file : dir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot)) { - removePathRecursively(file.absoluteFilePath()); - } - } -} - QStringList IconList::getIconFilePaths() const { QStringList iconFiles{}; @@ -179,9 +157,8 @@ void IconList::directoryChanged(const QString& path) stopWatching(); startWatching(); } - if (!m_dir.exists()) - if (!FS::ensureFolderPathExists(m_dir.absolutePath())) - return; + if (!m_dir.exists() && !FS::ensureFolderPathExists(m_dir.absolutePath())) + return; m_dir.refresh(); const QStringList newFileNamesList = getIconFilePaths(); const QSet newSet = toStringSet(newFileNamesList); diff --git a/launcher/icons/IconList.h b/launcher/icons/IconList.h index 04c2738ef..ec6b6d60e 100644 --- a/launcher/icons/IconList.h +++ b/launcher/icons/IconList.h @@ -93,7 +93,6 @@ class IconList : public QAbstractListModel { void reindex(); void sortIconList(); bool addPathRecursively(const QString& path); - void removePathRecursively(const QString& path); QStringList getIconFilePaths() const; public slots: From 33ff3b4f361df1429bd6490d0714e7c7bf90f143 Mon Sep 17 00:00:00 2001 From: QazCetelic Date: Sat, 23 Nov 2024 18:10:33 +0100 Subject: [PATCH 32/80] Fix naming Signed-off-by: QazCetelic --- launcher/icons/IconList.cpp | 34 +++++++++++++++++----------------- launcher/icons/IconList.h | 4 ++-- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/launcher/icons/IconList.cpp b/launcher/icons/IconList.cpp index eb047b130..faeb3f2c7 100644 --- a/launcher/icons/IconList.cpp +++ b/launcher/icons/IconList.cpp @@ -64,7 +64,7 @@ IconList::IconList(const QStringList& builtinPaths, const QString& path, QObject } m_watcher.reset(new QFileSystemWatcher()); - m_is_watching = false; + m_isWatching = false; connect(m_watcher.get(), &QFileSystemWatcher::directoryChanged, this, &IconList::directoryChanged); connect(m_watcher.get(), &QFileSystemWatcher::fileChanged, this, &IconList::fileChanged); @@ -153,7 +153,7 @@ void IconList::directoryChanged(const QString& path) if (!path.startsWith(m_dir.absolutePath())) m_dir.setPath(path); m_dir.refresh(); - if (m_is_watching) + if (m_isWatching) stopWatching(); startWatching(); } @@ -239,8 +239,8 @@ void IconList::startWatching() { auto abs_path = m_dir.absolutePath(); FS::ensureFolderPathExists(abs_path); - m_is_watching = addPathRecursively(abs_path); - if (m_is_watching) { + m_isWatching = addPathRecursively(abs_path); + if (m_isWatching) { qDebug() << "Started watching " << abs_path; } else { qDebug() << "Failed to start watching " << abs_path; @@ -251,7 +251,7 @@ void IconList::stopWatching() { m_watcher->removePaths(m_watcher->files()); m_watcher->removePaths(m_watcher->directories()); - m_is_watching = false; + m_isWatching = false; } QStringList IconList::mimeTypes() const @@ -372,8 +372,8 @@ bool IconList::trashIcon(const QString& key) bool IconList::addThemeIcon(const QString& key) { - auto iter = m_name_index.find(key); - if (iter != m_name_index.end()) { + auto iter = m_nameIndex.find(key); + if (iter != m_nameIndex.end()) { auto& oldOne = m_icons[*iter]; oldOne.replace(Builtin, key); dataChanged(index(*iter), index(*iter)); @@ -387,7 +387,7 @@ bool IconList::addThemeIcon(const QString& key) mmc_icon.m_key = key; mmc_icon.replace(Builtin, key); m_icons.push_back(mmc_icon); - m_name_index[key] = m_icons.size() - 1; + m_nameIndex[key] = m_icons.size() - 1; } endInsertRows(); return true; @@ -399,8 +399,8 @@ bool IconList::addIcon(const QString& key, const QString& name, const QString& p QIcon icon(path); if (icon.isNull()) return false; - auto iter = m_name_index.find(key); - if (iter != m_name_index.end()) { + auto iter = m_nameIndex.find(key); + if (iter != m_nameIndex.end()) { auto& oldOne = m_icons[*iter]; oldOne.replace(type, icon, path); dataChanged(index(*iter), index(*iter)); @@ -414,7 +414,7 @@ bool IconList::addIcon(const QString& key, const QString& name, const QString& p mmc_icon.m_key = key; mmc_icon.replace(type, icon, path); m_icons.push_back(mmc_icon); - m_name_index[key] = m_icons.size() - 1; + m_nameIndex[key] = m_icons.size() - 1; } endInsertRows(); return true; @@ -429,9 +429,9 @@ void IconList::saveIcon(const QString& key, const QString& path, const char* for void IconList::reindex() { - m_name_index.clear(); + m_nameIndex.clear(); for (int i = 0; i < m_icons.size(); i++) { - m_name_index[m_icons[i].m_key] = i; + m_nameIndex[m_icons[i].m_key] = i; emit iconUpdated(m_icons[i].m_key); // prevents incorrect indices with proxy model } } @@ -453,8 +453,8 @@ QIcon IconList::getIcon(const QString& key) const int IconList::getIconIndex(const QString& key) const { - auto iter = m_name_index.find(key == "default" ? "grass" : key); - if (iter != m_name_index.end()) + auto iter = m_nameIndex.find(key == "default" ? "grass" : key); + if (iter != m_nameIndex.end()) return *iter; return -1; @@ -470,8 +470,8 @@ QString IconList::iconDirectory(const QString& key) const { for (const auto& mmcIcon : m_icons) { if (mmcIcon.m_key == key && mmcIcon.has(IconType::FileBased)) { - QFileInfo icon_file(mmcIcon.getFilePath()); - return icon_file.dir().path(); + QFileInfo iconFile(mmcIcon.getFilePath()); + return iconFile.dir().path(); } } return getDirectory(); diff --git a/launcher/icons/IconList.h b/launcher/icons/IconList.h index ec6b6d60e..8936195c3 100644 --- a/launcher/icons/IconList.h +++ b/launcher/icons/IconList.h @@ -104,8 +104,8 @@ class IconList : public QAbstractListModel { private: shared_qobject_ptr m_watcher; - bool m_is_watching; - QMap m_name_index; + bool m_isWatching; + QMap m_nameIndex; QVector m_icons; QDir m_dir; }; From a09af619cee3265710097724f539d9457695658d Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sun, 24 Nov 2024 20:29:07 +0200 Subject: [PATCH 33/80] Make FTB Import note italic to match others Signed-off-by: Trial97 --- launcher/ui/pages/modplatform/import_ftb/ImportFTBPage.ui | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/launcher/ui/pages/modplatform/import_ftb/ImportFTBPage.ui b/launcher/ui/pages/modplatform/import_ftb/ImportFTBPage.ui index 18c604ca4..337c3e474 100644 --- a/launcher/ui/pages/modplatform/import_ftb/ImportFTBPage.ui +++ b/launcher/ui/pages/modplatform/import_ftb/ImportFTBPage.ui @@ -13,6 +13,11 @@ + + + true + + Note: If your FTB instances are not in the default location, select it using the button next to search. From 4a50e949672461b5b69b039ff240ced6dad9bdd5 Mon Sep 17 00:00:00 2001 From: guihkx <626206+guihkx@users.noreply.github.com> Date: Tue, 26 Nov 2024 13:51:09 -0300 Subject: [PATCH 34/80] flatpak: update xrandr to 1.5.3 Signed-off-by: guihkx <626206+guihkx@users.noreply.github.com> --- flatpak/org.prismlauncher.PrismLauncher.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/flatpak/org.prismlauncher.PrismLauncher.yml b/flatpak/org.prismlauncher.PrismLauncher.yml index 7aaa4f379..e2c8a0b79 100644 --- a/flatpak/org.prismlauncher.PrismLauncher.yml +++ b/flatpak/org.prismlauncher.PrismLauncher.yml @@ -75,8 +75,8 @@ modules: buildsystem: autotools sources: - type: archive - url: https://xorg.freedesktop.org/archive/individual/app/xrandr-1.5.2.tar.xz - sha256: c8bee4790d9058bacc4b6246456c58021db58a87ddda1a9d0139bf5f18f1f240 + url: https://xorg.freedesktop.org/archive/individual/app/xrandr-1.5.3.tar.xz + sha256: f8dd7566adb74147fab9964680b6bbadee87cf406a7fcff51718a5e6949b841c x-checker-data: type: anitya project-id: 14957 From f6770a847a8419ef0b1acab30144077f745a48ee Mon Sep 17 00:00:00 2001 From: guihkx <626206+guihkx@users.noreply.github.com> Date: Tue, 26 Nov 2024 13:51:09 -0300 Subject: [PATCH 35/80] flatpak: update KDE runtime to 6.8 This also switches to the Docker image provided and maintained by Flathub collaborators through the 'flathub-infra' organization on GitHub, because it looks better maintained at the moment. Signed-off-by: guihkx <626206+guihkx@users.noreply.github.com> --- .github/workflows/build.yml | 2 +- flatpak/org.prismlauncher.PrismLauncher.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2cefa8100..d2db67054 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -633,7 +633,7 @@ jobs: flatpak: runs-on: ubuntu-latest container: - image: bilelmoussaoui/flatpak-github-actions:kde-6.7 + image: ghcr.io/flathub-infra/flatpak-github-actions:kde-6.8 options: --privileged steps: - name: Checkout diff --git a/flatpak/org.prismlauncher.PrismLauncher.yml b/flatpak/org.prismlauncher.PrismLauncher.yml index e2c8a0b79..136aef91a 100644 --- a/flatpak/org.prismlauncher.PrismLauncher.yml +++ b/flatpak/org.prismlauncher.PrismLauncher.yml @@ -1,6 +1,6 @@ id: org.prismlauncher.PrismLauncher runtime: org.kde.Platform -runtime-version: '6.7' +runtime-version: '6.8' sdk: org.kde.Sdk sdk-extensions: - org.freedesktop.Sdk.Extension.openjdk17 From e0faee7f262fda898ceb8ea5ab40249dbd6c52ea Mon Sep 17 00:00:00 2001 From: guihkx <626206+guihkx@users.noreply.github.com> Date: Tue, 26 Nov 2024 13:51:09 -0300 Subject: [PATCH 36/80] ci(flatpak): update build artifact name Just aligning the name of the Flatpak package with other build artifacts. Signed-off-by: guihkx <626206+guihkx@users.noreply.github.com> --- .github/workflows/build.yml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d2db67054..5e092b4e4 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -640,12 +640,17 @@ jobs: uses: actions/checkout@v4 if: inputs.build_type == 'Debug' with: - submodules: "true" + submodules: true + + - name: Set short version + shell: bash + run: echo "VERSION=${GITHUB_SHA::7}" >> $GITHUB_ENV + - name: Build Flatpak (Linux) if: inputs.build_type == 'Debug' uses: flatpak/flatpak-github-actions/flatpak-builder@v6 with: - bundle: "Prism Launcher.flatpak" + bundle: PrismLauncher-${{ runner.os }}-${{ env.VERSION }}-Flatpak.flatpak manifest-path: flatpak/org.prismlauncher.PrismLauncher.yml nix: From 884f15da1e4089690c56ea475b3860672c8baedd Mon Sep 17 00:00:00 2001 From: Kenneth Chew <79120643+kthchew@users.noreply.github.com> Date: Fri, 29 Nov 2024 20:40:37 -0500 Subject: [PATCH 37/80] Remove unnecessary hardened runtime exceptions These are cruft from an older time when the launcher was ad-hoc signed, and the OS couldn't tell the libraries and launcher were signed by the same party. Additionally, add a workaround to send the necessary library injection to the game if Steam overlay is used despite library validation being on for the launcher. Signed-off-by: Kenneth Chew <79120643+kthchew@users.noreply.github.com> --- launcher/minecraft/MinecraftInstance.cpp | 7 +++++++ program_info/App.entitlements | 4 ---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/launcher/minecraft/MinecraftInstance.cpp b/launcher/minecraft/MinecraftInstance.cpp index 007fb6cca..108cb6648 100644 --- a/launcher/minecraft/MinecraftInstance.cpp +++ b/launcher/minecraft/MinecraftInstance.cpp @@ -554,6 +554,13 @@ QMap MinecraftInstance::getVariables() out.insert("INST_JAVA", settings()->get("JavaPath").toString()); out.insert("INST_JAVA_ARGS", javaArguments().join(' ')); out.insert("NO_COLOR", "1"); +#ifdef Q_OS_MACOS + // get library for Steam overlay support + QString steamDyldInsertLibraries = qEnvironmentVariable("STEAM_DYLD_INSERT_LIBRARIES"); + if (!steamDyldInsertLibraries.isEmpty()) { + out.insert("DYLD_INSERT_LIBRARIES", steamDyldInsertLibraries); + } +#endif return out; } diff --git a/program_info/App.entitlements b/program_info/App.entitlements index b46e8ff2a..73bf832c7 100644 --- a/program_info/App.entitlements +++ b/program_info/App.entitlements @@ -2,10 +2,6 @@ - com.apple.security.cs.disable-library-validation - - com.apple.security.cs.allow-dyld-environment-variables - com.apple.security.device.audio-input com.apple.security.device.camera From 7e76638f2c5471b161b717f6feb1f3e37135fc13 Mon Sep 17 00:00:00 2001 From: Kenneth Chew <79120643+kthchew@users.noreply.github.com> Date: Fri, 29 Nov 2024 21:10:35 -0500 Subject: [PATCH 38/80] Only disable library validation if using ad-hoc signature While not needed for regular releases, it is needed for CI when an Apple Developer account isn't available and you can only perform an ad-hoc signature. Signed-off-by: Kenneth Chew <79120643+kthchew@users.noreply.github.com> --- .github/workflows/build.yml | 4 +++- program_info/AdhocSignedApp.entitlements | 12 ++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 program_info/AdhocSignedApp.entitlements diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2cefa8100..23b4edcd6 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -380,11 +380,13 @@ jobs: if [ -n '${{ secrets.APPLE_CODESIGN_ID }}' ]; then APPLE_CODESIGN_ID='${{ secrets.APPLE_CODESIGN_ID }}' + ENTITLEMENTS_FILE='../program_info/App.entitlements' else APPLE_CODESIGN_ID='-' + ENTITLEMENTS_FILE='../program_info/AdhocSignedApp.entitlements' fi - sudo codesign --sign "$APPLE_CODESIGN_ID" --deep --force --entitlements "../program_info/App.entitlements" --options runtime "PrismLauncher.app/Contents/MacOS/prismlauncher" + sudo codesign --sign "$APPLE_CODESIGN_ID" --deep --force --entitlements "$ENTITLEMENTS_FILE" --options runtime "PrismLauncher.app/Contents/MacOS/prismlauncher" mv "PrismLauncher.app" "Prism Launcher.app" - name: Notarize (macOS) diff --git a/program_info/AdhocSignedApp.entitlements b/program_info/AdhocSignedApp.entitlements new file mode 100644 index 000000000..032308a18 --- /dev/null +++ b/program_info/AdhocSignedApp.entitlements @@ -0,0 +1,12 @@ + + + + + com.apple.security.cs.disable-library-validation + + com.apple.security.device.audio-input + + com.apple.security.device.camera + + + From fd9c80db62436b1a364cb8342ba45a059c53f899 Mon Sep 17 00:00:00 2001 From: leia uwu Date: Sat, 30 Nov 2024 11:30:25 -0300 Subject: [PATCH 39/80] fix: fix system icons This sets the fallback icon theme to the current(system default) icon theme before launcher specific themes are applied And removes `Inherits` line of multimc/legacy icon theme because it can end up making it inherit a default theme set from /usr/share/icons/default/index.theme instead of the user configured theme (probably a qt bug?) Signed-off-by: leia uwu --- launcher/resources/multimc/index.theme | 1 - launcher/ui/themes/ThemeManager.cpp | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/resources/multimc/index.theme b/launcher/resources/multimc/index.theme index 4da8072d9..497106d6f 100644 --- a/launcher/resources/multimc/index.theme +++ b/launcher/resources/multimc/index.theme @@ -1,7 +1,6 @@ [Icon Theme] Name=Legacy Comment=Default Icons -Inherits=default Directories=8x8,16x16,22x22,24x24,32x32,32x32/instances,48x48,50x50/instances,64x64,128x128/instances,256x256,scalable,scalable/instances [8x8] diff --git a/launcher/ui/themes/ThemeManager.cpp b/launcher/ui/themes/ThemeManager.cpp index 691a51668..81afd0412 100644 --- a/launcher/ui/themes/ThemeManager.cpp +++ b/launcher/ui/themes/ThemeManager.cpp @@ -36,6 +36,7 @@ ThemeManager::ThemeManager() { + QIcon::setFallbackThemeName(QIcon::themeName()); themeDebugLog() << "Determining System Widget Theme..."; const auto& style = QApplication::style(); m_defaultStyle = style->objectName(); From 3f67ef968bb9be3b1cdfdfa68e2d38ddf8e1a3cf Mon Sep 17 00:00:00 2001 From: leia uwu Date: Sat, 30 Nov 2024 12:50:57 -0300 Subject: [PATCH 40/80] fix: icon search paths memory leak Signed-off-by: leia uwu --- launcher/ui/themes/ThemeManager.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/launcher/ui/themes/ThemeManager.cpp b/launcher/ui/themes/ThemeManager.cpp index 81afd0412..bbf614855 100644 --- a/launcher/ui/themes/ThemeManager.cpp +++ b/launcher/ui/themes/ThemeManager.cpp @@ -37,6 +37,7 @@ ThemeManager::ThemeManager() { QIcon::setFallbackThemeName(QIcon::themeName()); + QIcon::setFallbackSearchPaths(QIcon::themeSearchPaths()); themeDebugLog() << "Determining System Widget Theme..."; const auto& style = QApplication::style(); m_defaultStyle = style->objectName(); @@ -94,9 +95,7 @@ void ThemeManager::initializeIcons() // set icon theme search path! themeDebugLog() << "<> Initializing Icon Themes"; - auto searchPaths = QIcon::themeSearchPaths(); - searchPaths.append(m_iconThemeFolder.path()); - QIcon::setThemeSearchPaths(searchPaths); + QIcon::setThemeSearchPaths({ m_iconThemeFolder.path(), ":/icons" }); for (const QString& id : builtinIcons) { IconTheme theme(id, QString(":/icons/%1").arg(id)); From 2cfd1169473e8a7d5b1b436ff5a6b708c52a5b93 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 1 Dec 2024 00:30:03 +0000 Subject: [PATCH 41/80] chore(nix): update lockfile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Flake lock file updates: • Updated input 'flake-compat': 'github:edolstra/flake-compat/0f9255e01c2351cc7d116c072cb317785dd33b33?narHash=sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U%3D' (2023-10-04) → 'github:edolstra/flake-compat/9ed2ac151eada2306ca8c418ebd97807bb08f6ac?narHash=sha256-HRJ/18p%2BWoXpWJkcdsk9St5ZiukCqSDgbOGFa8Okehg%3D' (2024-11-27) • Updated input 'nixpkgs': 'github:NixOS/nixpkgs/23e89b7da85c3640bbc2173fe04f4bd114342367?narHash=sha256-y/MEyuJ5oBWrWAic/14LaIr/u5E0wRVzyYsouYY3W6w%3D' (2024-11-19) → 'github:NixOS/nixpkgs/970e93b9f82e2a0f3675757eb0bfc73297cc6370?narHash=sha256-jNRNr49UiuIwaarqijgdTR2qLPifxsVhlJrKzQ8XUIE%3D' (2024-11-28) --- flake.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/flake.lock b/flake.lock index ba9a56c33..49ca909a4 100644 --- a/flake.lock +++ b/flake.lock @@ -3,11 +3,11 @@ "flake-compat": { "flake": false, "locked": { - "lastModified": 1696426674, - "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", + "lastModified": 1732722421, + "narHash": "sha256-HRJ/18p+WoXpWJkcdsk9St5ZiukCqSDgbOGFa8Okehg=", "owner": "edolstra", "repo": "flake-compat", - "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", + "rev": "9ed2ac151eada2306ca8c418ebd97807bb08f6ac", "type": "github" }, "original": { @@ -49,11 +49,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1732014248, - "narHash": "sha256-y/MEyuJ5oBWrWAic/14LaIr/u5E0wRVzyYsouYY3W6w=", + "lastModified": 1732837521, + "narHash": "sha256-jNRNr49UiuIwaarqijgdTR2qLPifxsVhlJrKzQ8XUIE=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "23e89b7da85c3640bbc2173fe04f4bd114342367", + "rev": "970e93b9f82e2a0f3675757eb0bfc73297cc6370", "type": "github" }, "original": { From 94c893bd865ceba286dffc1d6392df07d47c11d9 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 5 Dec 2024 20:29:11 +0000 Subject: [PATCH 42/80] chore(deps): update actions/cache action to v4.2.0 --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5e092b4e4..991ddcd8c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -173,7 +173,7 @@ jobs: - name: Retrieve ccache cache (Windows MinGW-w64) if: runner.os == 'Windows' && matrix.msystem != '' && inputs.build_type == 'Debug' - uses: actions/cache@v4.1.2 + uses: actions/cache@v4.2.0 with: path: '${{ github.workspace }}\.ccache' key: ${{ matrix.os }}-mingw-w64-ccache-${{ github.run_id }} From 614574f15c507f884fc2ceff74db8c919674a0f1 Mon Sep 17 00:00:00 2001 From: leia uwu Date: Fri, 6 Dec 2024 16:40:07 -0300 Subject: [PATCH 43/80] fix icon theme search paths using fallback search paths breaks qadwaitadecorations Signed-off-by: leia uwu --- launcher/ui/themes/ThemeManager.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/launcher/ui/themes/ThemeManager.cpp b/launcher/ui/themes/ThemeManager.cpp index bbf614855..30a1fe7be 100644 --- a/launcher/ui/themes/ThemeManager.cpp +++ b/launcher/ui/themes/ThemeManager.cpp @@ -37,7 +37,8 @@ ThemeManager::ThemeManager() { QIcon::setFallbackThemeName(QIcon::themeName()); - QIcon::setFallbackSearchPaths(QIcon::themeSearchPaths()); + QIcon::setThemeSearchPaths(QIcon::themeSearchPaths() << m_iconThemeFolder.path()); + themeDebugLog() << "Determining System Widget Theme..."; const auto& style = QApplication::style(); m_defaultStyle = style->objectName(); @@ -95,8 +96,6 @@ void ThemeManager::initializeIcons() // set icon theme search path! themeDebugLog() << "<> Initializing Icon Themes"; - QIcon::setThemeSearchPaths({ m_iconThemeFolder.path(), ":/icons" }); - for (const QString& id : builtinIcons) { IconTheme theme(id, QString(":/icons/%1").arg(id)); if (!theme.load()) { @@ -348,4 +347,4 @@ void ThemeManager::refresh() initializeThemes(); initializeCatPacks(); -} \ No newline at end of file +} From dedb7a2343f7d433492dee5930802ed47294b722 Mon Sep 17 00:00:00 2001 From: sshcrack <34072808+sshcrack@users.noreply.github.com> Date: Sun, 8 Dec 2024 14:17:04 +0100 Subject: [PATCH 44/80] change order of steps Signed-off-by: sshcrack <34072808+sshcrack@users.noreply.github.com> --- launcher/minecraft/MinecraftInstance.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/launcher/minecraft/MinecraftInstance.cpp b/launcher/minecraft/MinecraftInstance.cpp index 98ac7647f..e35dd973e 100644 --- a/launcher/minecraft/MinecraftInstance.cpp +++ b/launcher/minecraft/MinecraftInstance.cpp @@ -1083,6 +1083,12 @@ shared_qobject_ptr MinecraftInstance::createLaunchTask(AuthSessionPt process->appendStep(step); } + // check java + { + process->appendStep(makeShared(pptr)); + process->appendStep(makeShared(pptr)); + } + // run pre-launch command if that's needed if (getPreLaunchCommand().size()) { auto step = makeShared(pptr); @@ -1096,12 +1102,6 @@ shared_qobject_ptr MinecraftInstance::createLaunchTask(AuthSessionPt process->appendStep(makeShared(pptr, makeShared(this, mode, pptr))); } - // check java - { - process->appendStep(makeShared(pptr)); - process->appendStep(makeShared(pptr)); - } - // if we aren't in offline mode,. if (session->status != AuthSession::PlayableOffline) { if (!session->demo) { From cf2dcbd431b0c4bb03ff527465f972d72f713b0c Mon Sep 17 00:00:00 2001 From: sshcrack <34072808+sshcrack@users.noreply.github.com> Date: Sun, 8 Dec 2024 18:27:57 +0100 Subject: [PATCH 45/80] load meta first Signed-off-by: sshcrack <34072808+sshcrack@users.noreply.github.com> --- launcher/minecraft/MinecraftInstance.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/launcher/minecraft/MinecraftInstance.cpp b/launcher/minecraft/MinecraftInstance.cpp index e35dd973e..995dd15d7 100644 --- a/launcher/minecraft/MinecraftInstance.cpp +++ b/launcher/minecraft/MinecraftInstance.cpp @@ -1083,6 +1083,12 @@ shared_qobject_ptr MinecraftInstance::createLaunchTask(AuthSessionPt process->appendStep(step); } + // load meta + { + auto mode = session->status != AuthSession::PlayableOffline ? Net::Mode::Online : Net::Mode::Offline; + process->appendStep(makeShared(pptr, makeShared(this, mode, pptr))); + } + // check java { process->appendStep(makeShared(pptr)); @@ -1096,12 +1102,6 @@ shared_qobject_ptr MinecraftInstance::createLaunchTask(AuthSessionPt process->appendStep(step); } - // load meta - { - auto mode = session->status != AuthSession::PlayableOffline ? Net::Mode::Online : Net::Mode::Offline; - process->appendStep(makeShared(pptr, makeShared(this, mode, pptr))); - } - // if we aren't in offline mode,. if (session->status != AuthSession::PlayableOffline) { if (!session->demo) { From 1dd0728a58159bc835b2e7724a707776ae0b93ce Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sun, 8 Dec 2024 22:04:16 +0200 Subject: [PATCH 46/80] fix crash with invalid mrpack format Signed-off-by: Trial97 --- .../modplatform/modrinth/ModrinthInstanceCreationTask.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp b/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp index bfececb8d..2cc8767a4 100644 --- a/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp +++ b/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp @@ -262,12 +262,14 @@ bool ModrinthCreationTask::createInstance() mod->setDetails(d); resources[file.hash.toHex()] = mod; } - + if (file.downloads.empty()) { + setError(tr("The file '%1' is missing a download link. This is invalid in the pack format.").arg(fileName)); + return false; + } qDebug() << "Will try to download" << file.downloads.front() << "to" << file_path; auto dl = Net::ApiDownload::makeFile(file.downloads.dequeue(), file_path); dl->addValidator(new Net::ChecksumValidator(file.hashAlgorithm, file.hash)); downloadMods->addNetAction(dl); - if (!file.downloads.empty()) { // FIXME: This really needs to be put into a ConcurrentTask of // MultipleOptionsTask's , once those exist :) From eb8c375ec5023bbc7c02e45d63da866058e56b26 Mon Sep 17 00:00:00 2001 From: Edgars Cirulis Date: Mon, 9 Dec 2024 00:40:05 +0200 Subject: [PATCH 47/80] chore: update Qt to 6.8.1 Signed-off-by: Edgars Cirulis --- .github/workflows/build.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a96278ba3..7bb6c0ad7 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -82,7 +82,7 @@ jobs: qt_ver: 6 qt_host: "windows" qt_arch: "win64_msvc2022_64" - qt_version: "6.8.0" + qt_version: "6.8.1" qt_modules: "qt5compat qtimageformats qtnetworkauth" nscurl_tag: "v24.9.26.122" nscurl_sha256: "AEE6C4BE3CB6455858E9C1EE4B3AFE0DB9960FA03FE99CCDEDC28390D57CCBB0" @@ -95,7 +95,7 @@ jobs: qt_ver: 6 qt_host: "windows" qt_arch: "win64_msvc2022_arm64_cross_compiled" - qt_version: "6.8.0" + qt_version: "6.8.1" qt_modules: "qt5compat qtimageformats qtnetworkauth" nscurl_tag: "v24.9.26.122" nscurl_sha256: "AEE6C4BE3CB6455858E9C1EE4B3AFE0DB9960FA03FE99CCDEDC28390D57CCBB0" @@ -106,7 +106,7 @@ jobs: qt_ver: 6 qt_host: mac qt_arch: "" - qt_version: "6.8.0" + qt_version: "6.8.1" qt_modules: "qt5compat qtimageformats qtnetworkauth" - os: macos-14 From a1c1c0b769d77eb8c44cef3dc0966e7184b2ce78 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 12 Dec 2024 17:29:46 +0200 Subject: [PATCH 48/80] Do not fail curseforge import if modrinth file check fails Signed-off-by: Trial97 --- launcher/modplatform/flame/FileResolvingTask.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/modplatform/flame/FileResolvingTask.cpp b/launcher/modplatform/flame/FileResolvingTask.cpp index 4c2f3d69e..d69bf12c0 100644 --- a/launcher/modplatform/flame/FileResolvingTask.cpp +++ b/launcher/modplatform/flame/FileResolvingTask.cpp @@ -144,7 +144,7 @@ void Flame::FileResolvingTask::netJobFinished() << " reason: " << parse_error.errorString(); qWarning() << *m_result; - failed(parse_error.errorString()); + getFlameProjects(); return; } From c3e44554abccfd16ff7f84740932848e59d28474 Mon Sep 17 00:00:00 2001 From: Kenneth Chew <79120643+kthchew@users.noreply.github.com> Date: Thu, 12 Dec 2024 14:43:28 -0500 Subject: [PATCH 49/80] Add local network usage description Signed-off-by: Kenneth Chew <79120643+kthchew@users.noreply.github.com> --- cmake/MacOSXBundleInfo.plist.in | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cmake/MacOSXBundleInfo.plist.in b/cmake/MacOSXBundleInfo.plist.in index 6d3845dfc..3a8c8fbfe 100644 --- a/cmake/MacOSXBundleInfo.plist.in +++ b/cmake/MacOSXBundleInfo.plist.in @@ -8,6 +8,8 @@ A Minecraft mod wants to access your microphone. NSDownloadsFolderUsageDescription Prism uses access to your Downloads folder to help you more quickly add mods that can't be automatically downloaded to your instance. You can change where Prism scans for downloaded mods in Settings or the prompt that appears. + NSLocalNetworkUsageDescription + Minecraft uses the local network to find and connect to LAN servers. NSPrincipalClass NSApplication NSHighResolutionCapable From c3712ba6483f6386e2930ec0ed059d8c94f671b6 Mon Sep 17 00:00:00 2001 From: Kenneth Chew <79120643+kthchew@users.noreply.github.com> Date: Thu, 12 Dec 2024 14:53:39 -0500 Subject: [PATCH 50/80] Fix tab order in launcher settings Signed-off-by: Kenneth Chew <79120643+kthchew@users.noreply.github.com> --- launcher/ui/pages/global/LauncherPage.ui | 32 ++++++++++++++++++------ 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/launcher/ui/pages/global/LauncherPage.ui b/launcher/ui/pages/global/LauncherPage.ui index 09e7bca5b..a46a6fd5d 100644 --- a/launcher/ui/pages/global/LauncherPage.ui +++ b/launcher/ui/pages/global/LauncherPage.ui @@ -35,7 +35,7 @@ - QTabWidget::Rounded + QTabWidget::TabShape::Rounded 0 @@ -48,7 +48,7 @@ - Qt::ScrollBarAlwaysOff + Qt::ScrollBarPolicy::ScrollBarAlwaysOff true @@ -365,7 +365,7 @@ - Qt::Vertical + Qt::Orientation::Vertical @@ -465,7 +465,7 @@ - Qt::Horizontal + Qt::Orientation::Horizontal @@ -506,7 +506,7 @@ - Qt::Vertical + Qt::Orientation::Vertical @@ -615,13 +615,13 @@ - Qt::ScrollBarAlwaysOff + Qt::ScrollBarPolicy::ScrollBarAlwaysOff false - Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + Qt::TextInteractionFlag::TextSelectableByKeyboard|Qt::TextInteractionFlag::TextSelectableByMouse @@ -667,15 +667,33 @@ tabWidget + scrollArea autoUpdateCheckBox + updateIntervalSpinBox instDirTextBox instDirBrowseBtn modsDirTextBox modsDirBrowseBtn iconsDirTextBox iconsDirBrowseBtn + javaDirTextBox + javaDirBrowseBtn + skinsDirTextBox + skinsDirBrowseBtn + downloadsDirTextBox + downloadsDirBrowseBtn + downloadsDirWatchRecursiveCheckBox + metadataDisableBtn + dependenciesDisableBtn + skipModpackUpdatePromptBtn + numberOfConcurrentTasksSpinBox + numberOfConcurrentDownloadsSpinBox + numberOfManualRetriesSpinBox + timeoutSecondsSpinBox sortLastLaunchedBtn sortByNameBtn + catOpacitySpinBox + preferMenuBarCheckBox showConsoleCheck autoCloseConsoleCheck showConsoleErrorCheck From b6cd46ad27e8046962dcb7b3b43a973ff08564eb Mon Sep 17 00:00:00 2001 From: Kenneth Chew <79120643+kthchew@users.noreply.github.com> Date: Sat, 14 Dec 2024 00:42:08 -0500 Subject: [PATCH 51/80] Update Sparkle to v2.6.4 Signed-off-by: Kenneth Chew <79120643+kthchew@users.noreply.github.com> --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4063ff503..dcf13c577 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -401,8 +401,8 @@ if(UNIX AND APPLE) set(MACOSX_SPARKLE_UPDATE_PUBLIC_KEY "v55ZWWD6QlPoXGV6VLzOTZxZUggWeE51X8cRQyQh6vA=" CACHE STRING "Public key for Sparkle update feed") set(MACOSX_SPARKLE_UPDATE_FEED_URL "https://prismlauncher.org/feed/appcast.xml" CACHE STRING "URL for Sparkle update feed") - set(MACOSX_SPARKLE_DOWNLOAD_URL "https://github.com/sparkle-project/Sparkle/releases/download/2.5.2/Sparkle-2.5.2.tar.xz" CACHE STRING "URL to Sparkle release archive") - set(MACOSX_SPARKLE_SHA256 "572dd67ae398a466f19f343a449e1890bac1ef74885b4739f68f979a8a89884b" CACHE STRING "SHA256 checksum for Sparkle release archive") + set(MACOSX_SPARKLE_DOWNLOAD_URL "https://github.com/sparkle-project/Sparkle/releases/download/2.6.4/Sparkle-2.6.4.tar.xz" CACHE STRING "URL to Sparkle release archive") + set(MACOSX_SPARKLE_SHA256 "50612a06038abc931f16011d7903b8326a362c1074dabccb718404ce8e585f0b" CACHE STRING "SHA256 checksum for Sparkle release archive") set(MACOSX_SPARKLE_DIR "${CMAKE_BINARY_DIR}/frameworks/Sparkle") # directories to look for dependencies From 706e2630508c40125d9442062e81c64ec4789cea Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 15 Dec 2024 00:27:47 +0000 Subject: [PATCH 52/80] chore(nix): update lockfile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Flake lock file updates: • Updated input 'flake-compat': 'github:edolstra/flake-compat/9ed2ac151eada2306ca8c418ebd97807bb08f6ac?narHash=sha256-HRJ/18p%2BWoXpWJkcdsk9St5ZiukCqSDgbOGFa8Okehg%3D' (2024-11-27) → 'github:edolstra/flake-compat/ff81ac966bb2cae68946d5ed5fc4994f96d0ffec?narHash=sha256-NeCCThCEP3eCl2l/%2B27kNNK7QrwZB1IJCrXfrbv5oqU%3D' (2024-12-04) • Updated input 'nixpkgs': 'github:NixOS/nixpkgs/970e93b9f82e2a0f3675757eb0bfc73297cc6370?narHash=sha256-jNRNr49UiuIwaarqijgdTR2qLPifxsVhlJrKzQ8XUIE%3D' (2024-11-28) → 'github:NixOS/nixpkgs/5d67ea6b4b63378b9c13be21e2ec9d1afc921713?narHash=sha256-Pj39hSoUA86ZePPF/UXiYHHM7hMIkios8TYG29kQT4g%3D' (2024-12-11) --- flake.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/flake.lock b/flake.lock index 49ca909a4..f01d7da12 100644 --- a/flake.lock +++ b/flake.lock @@ -3,11 +3,11 @@ "flake-compat": { "flake": false, "locked": { - "lastModified": 1732722421, - "narHash": "sha256-HRJ/18p+WoXpWJkcdsk9St5ZiukCqSDgbOGFa8Okehg=", + "lastModified": 1733328505, + "narHash": "sha256-NeCCThCEP3eCl2l/+27kNNK7QrwZB1IJCrXfrbv5oqU=", "owner": "edolstra", "repo": "flake-compat", - "rev": "9ed2ac151eada2306ca8c418ebd97807bb08f6ac", + "rev": "ff81ac966bb2cae68946d5ed5fc4994f96d0ffec", "type": "github" }, "original": { @@ -49,11 +49,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1732837521, - "narHash": "sha256-jNRNr49UiuIwaarqijgdTR2qLPifxsVhlJrKzQ8XUIE=", + "lastModified": 1733940404, + "narHash": "sha256-Pj39hSoUA86ZePPF/UXiYHHM7hMIkios8TYG29kQT4g=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "970e93b9f82e2a0f3675757eb0bfc73297cc6370", + "rev": "5d67ea6b4b63378b9c13be21e2ec9d1afc921713", "type": "github" }, "original": { From 8d53242952ceeed11bd1a57c9ac43344d854ac8c Mon Sep 17 00:00:00 2001 From: Kenneth Chew <79120643+kthchew@users.noreply.github.com> Date: Mon, 16 Dec 2024 02:27:26 -0500 Subject: [PATCH 53/80] Correct symbolic link destination on manifest Java download Signed-off-by: Kenneth Chew <79120643+kthchew@users.noreply.github.com> --- launcher/java/download/ManifestDownloadTask.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/launcher/java/download/ManifestDownloadTask.cpp b/launcher/java/download/ManifestDownloadTask.cpp index 836afeaac..20b39e751 100644 --- a/launcher/java/download/ManifestDownloadTask.cpp +++ b/launcher/java/download/ManifestDownloadTask.cpp @@ -86,11 +86,10 @@ void ManifestDownloadTask::downloadJava(const QJsonDocument& doc) if (type == "directory") { FS::ensureFolderPathExists(file); } else if (type == "link") { - // this is linux only ! + // this is *nix only ! auto path = Json::ensureString(meta, "target"); if (!path.isEmpty()) { - auto target = FS::PathCombine(file, "../" + path); - QFile(target).link(file); + QFile::link(path, file); } } else if (type == "file") { // TODO download compressed version if it exists ? From f4d93a08ba18f386dc8cb08e77c813dc56ac5f9f Mon Sep 17 00:00:00 2001 From: Trial97 Date: Mon, 16 Dec 2024 13:27:44 +0200 Subject: [PATCH 54/80] Fix curseforge/modrinth instance icons Signed-off-by: Trial97 --- launcher/icons/IconList.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/launcher/icons/IconList.cpp b/launcher/icons/IconList.cpp index faeb3f2c7..f4022e0fb 100644 --- a/launcher/icons/IconList.cpp +++ b/launcher/icons/IconList.cpp @@ -196,7 +196,8 @@ void IconList::directoryChanged(const QString& path) qDebug() << "Adding icon " << addedPath; QFileInfo addfile(addedPath); - QString key = m_dir.relativeFilePath(addfile.absoluteFilePath()); + QString relativePath = m_dir.relativeFilePath(addfile.absoluteFilePath()); + QString key = QFileInfo(relativePath).completeBaseName(); QString name = formatName(m_dir, addfile); if (addIcon(key, name, addfile.filePath(), IconType::FileBased)) { From 0412ed3f7807d28145c28270f12e1de20a923b89 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Mon, 16 Dec 2024 14:51:59 +0200 Subject: [PATCH 55/80] Fix automatically choose mod provider option Signed-off-by: Trial97 --- launcher/modplatform/EnsureMetadataTask.cpp | 17 +++++++++-------- launcher/modplatform/EnsureMetadataTask.h | 4 ++-- launcher/ui/dialogs/ResourceUpdateDialog.cpp | 11 +++++++++-- 3 files changed, 20 insertions(+), 12 deletions(-) diff --git a/launcher/modplatform/EnsureMetadataTask.cpp b/launcher/modplatform/EnsureMetadataTask.cpp index 9d8d75b09..8e910e984 100644 --- a/launcher/modplatform/EnsureMetadataTask.cpp +++ b/launcher/modplatform/EnsureMetadataTask.cpp @@ -19,27 +19,28 @@ static ModrinthAPI modrinth_api; static FlameAPI flame_api; EnsureMetadataTask::EnsureMetadataTask(Resource* resource, QDir dir, ModPlatform::ResourceProvider prov) - : Task(), m_index_dir(dir), m_provider(prov), m_hashing_task(nullptr), m_current_task(nullptr) + : Task(), m_index_dir(dir), m_provider(prov), m_hashingTask(nullptr), m_current_task(nullptr) { - auto hash_task = createNewHash(resource); - if (!hash_task) + auto hashTask = createNewHash(resource); + if (!hashTask) return; - connect(hash_task.get(), &Hashing::Hasher::resultsReady, [this, resource](QString hash) { m_resources.insert(hash, resource); }); - connect(hash_task.get(), &Task::failed, [this, resource] { emitFail(resource, "", RemoveFromList::No); }); - hash_task->start(); + connect(hashTask.get(), &Hashing::Hasher::resultsReady, [this, resource](QString hash) { m_resources.insert(hash, resource); }); + connect(hashTask.get(), &Task::failed, [this, resource] { emitFail(resource, "", RemoveFromList::No); }); + m_hashingTask = hashTask; } EnsureMetadataTask::EnsureMetadataTask(QList& resources, QDir dir, ModPlatform::ResourceProvider prov) : Task(), m_index_dir(dir), m_provider(prov), m_current_task(nullptr) { - m_hashing_task.reset(new ConcurrentTask("MakeHashesTask", APPLICATION->settings()->get("NumberOfConcurrentTasks").toInt())); + auto hashTask = makeShared("MakeHashesTask", APPLICATION->settings()->get("NumberOfConcurrentTasks").toInt()); + m_hashingTask = hashTask; for (auto* resource : resources) { auto hash_task = createNewHash(resource); if (!hash_task) continue; connect(hash_task.get(), &Hashing::Hasher::resultsReady, [this, resource](QString hash) { m_resources.insert(hash, resource); }); connect(hash_task.get(), &Task::failed, [this, resource] { emitFail(resource, "", RemoveFromList::No); }); - m_hashing_task->addTask(hash_task); + hashTask->addTask(hash_task); } } diff --git a/launcher/modplatform/EnsureMetadataTask.h b/launcher/modplatform/EnsureMetadataTask.h index a78ffc0c5..4e5787841 100644 --- a/launcher/modplatform/EnsureMetadataTask.h +++ b/launcher/modplatform/EnsureMetadataTask.h @@ -21,7 +21,7 @@ class EnsureMetadataTask : public Task { ~EnsureMetadataTask() = default; - Task::Ptr getHashingTask() { return m_hashing_task; } + Task::Ptr getHashingTask() { return m_hashingTask; } public slots: bool abort() override; @@ -59,6 +59,6 @@ class EnsureMetadataTask : public Task { ModPlatform::ResourceProvider m_provider; QHash m_temp_versions; - ConcurrentTask::Ptr m_hashing_task; + Task::Ptr m_hashingTask; Task::Ptr m_current_task; }; diff --git a/launcher/ui/dialogs/ResourceUpdateDialog.cpp b/launcher/ui/dialogs/ResourceUpdateDialog.cpp index 78cf0e44a..f5ab52590 100644 --- a/launcher/ui/dialogs/ResourceUpdateDialog.cpp +++ b/launcher/ui/dialogs/ResourceUpdateDialog.cpp @@ -7,6 +7,7 @@ #include "minecraft/mod/tasks/GetModDependenciesTask.h" #include "modplatform/ModIndex.h" #include "modplatform/flame/FlameAPI.h" +#include "tasks/SequentialTask.h" #include "ui_ReviewMessageBox.h" #include "Markdown.h" @@ -411,8 +412,14 @@ void ResourceUpdateDialog::onMetadataFailed(Resource* resource, bool try_others, connect(task.get(), &EnsureMetadataTask::metadataFailed, [this](Resource* candidate) { onMetadataFailed(candidate, false); }); connect(task.get(), &EnsureMetadataTask::failed, [this](const QString& reason) { CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->exec(); }); - - m_second_try_metadata->addTask(task); + if (task->getHashingTask()) { + auto seq = makeShared(); + seq->addTask(task->getHashingTask()); + seq->addTask(task); + m_second_try_metadata->addTask(seq); + } else { + m_second_try_metadata->addTask(task); + } } else { QString reason{ tr("Couldn't find a valid version on the selected mod provider(s)") }; From 7dde35fef2108b8f870c7ed70b42f7e2358396d5 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 20 Dec 2024 19:57:09 +0200 Subject: [PATCH 56/80] Add settings to control the if prism should move the downloaded mods Signed-off-by: Trial97 --- launcher/Application.cpp | 1 + .../flame/FlameInstanceCreationTask.cpp | 10 ++++- launcher/ui/dialogs/BlockedModsDialog.cpp | 10 +++++ launcher/ui/dialogs/BlockedModsDialog.h | 1 + launcher/ui/pages/global/LauncherPage.cpp | 2 + launcher/ui/pages/global/LauncherPage.ui | 44 ++++++++++++------- 6 files changed, 51 insertions(+), 17 deletions(-) diff --git a/launcher/Application.cpp b/launcher/Application.cpp index 72f847d88..b0ff14a6b 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -616,6 +616,7 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) m_settings->registerSetting("IconsDir", "icons"); m_settings->registerSetting("DownloadsDir", QStandardPaths::writableLocation(QStandardPaths::DownloadLocation)); m_settings->registerSetting("DownloadsDirWatchRecursive", false); + m_settings->registerSetting("MoveModsFromDownloadsDir", false); m_settings->registerSetting("SkinsDir", "skins"); m_settings->registerSetting("JavaDir", "java"); diff --git a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp index 3fbe1aced..e60d32cc0 100644 --- a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp +++ b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp @@ -597,8 +597,14 @@ void FlameCreationTask::copyBlockedMods(QList const& blocked_mods) qDebug() << "Will try to copy" << mod.localPath << "to" << destPath; - if (!FS::copy(mod.localPath, destPath)()) { - qDebug() << "Copy of" << mod.localPath << "to" << destPath << "Failed"; + if (mod.move) { + if (!FS::move(mod.localPath, destPath)) { + qDebug() << "Move of" << mod.localPath << "to" << destPath << "Failed"; + } + } else { + if (!FS::copy(mod.localPath, destPath)()) { + qDebug() << "Copy of" << mod.localPath << "to" << destPath << "Failed"; + } } i++; diff --git a/launcher/ui/dialogs/BlockedModsDialog.cpp b/launcher/ui/dialogs/BlockedModsDialog.cpp index b3b6d2bcc..0095f7af9 100644 --- a/launcher/ui/dialogs/BlockedModsDialog.cpp +++ b/launcher/ui/dialogs/BlockedModsDialog.cpp @@ -288,6 +288,8 @@ void BlockedModsDialog::checkMatchHash(QString hash, QString path) qDebug() << "[Blocked Mods Dialog] Checking for match on hash: " << hash << "| From path:" << path; + auto downloadDir = QFileInfo(APPLICATION->settings()->get("DownloadsDir").toString()).absoluteFilePath(); + auto moveFiles = APPLICATION->settings()->get("MoveModsFromDownloadsDir").toBool(); for (auto& mod : m_mods) { if (mod.matched) { continue; @@ -295,6 +297,9 @@ void BlockedModsDialog::checkMatchHash(QString hash, QString path) if (mod.hash.compare(hash, Qt::CaseInsensitive) == 0) { mod.matched = true; mod.localPath = path; + if (moveFiles) { + mod.move = QFileInfo(path).absoluteFilePath().startsWith(downloadDir); + } match = true; qDebug() << "[Blocked Mods Dialog] Hash match found:" << mod.name << hash << "| From path:" << path; @@ -346,6 +351,8 @@ bool BlockedModsDialog::checkValidPath(QString path) return fsName.compare(metaName) == 0; }; + auto downloadDir = QFileInfo(APPLICATION->settings()->get("DownloadsDir").toString()).absoluteFilePath(); + auto moveFiles = APPLICATION->settings()->get("MoveModsFromDownloadsDir").toBool(); for (auto& mod : m_mods) { if (compare(filename, mod.name)) { // if the mod is not yet matched and doesn't have a hash then @@ -353,6 +360,9 @@ bool BlockedModsDialog::checkValidPath(QString path) if (!mod.matched && mod.hash.isEmpty()) { mod.matched = true; mod.localPath = path; + if (moveFiles) { + mod.move = QFileInfo(path).absoluteFilePath().startsWith(downloadDir); + } return false; } qDebug() << "[Blocked Mods Dialog] Name match found:" << mod.name << "| From path:" << path; diff --git a/launcher/ui/dialogs/BlockedModsDialog.h b/launcher/ui/dialogs/BlockedModsDialog.h index 09722bce9..b2d2c0374 100644 --- a/launcher/ui/dialogs/BlockedModsDialog.h +++ b/launcher/ui/dialogs/BlockedModsDialog.h @@ -42,6 +42,7 @@ struct BlockedMod { bool matched; QString localPath; QString targetFolder; + bool move = false; }; QT_BEGIN_NAMESPACE diff --git a/launcher/ui/pages/global/LauncherPage.cpp b/launcher/ui/pages/global/LauncherPage.cpp index 8bbed9643..831b40231 100644 --- a/launcher/ui/pages/global/LauncherPage.cpp +++ b/launcher/ui/pages/global/LauncherPage.cpp @@ -235,6 +235,7 @@ void LauncherPage::applySettings() s->set("SkinsDir", ui->skinsDirTextBox->text()); s->set("JavaDir", ui->javaDirTextBox->text()); s->set("DownloadsDirWatchRecursive", ui->downloadsDirWatchRecursiveCheckBox->isChecked()); + s->set("MoveModsFromDownloadsDir", ui->downloadsDirMoveCheckBox->isChecked()); auto sortMode = (InstSortMode)ui->sortingModeGroup->checkedId(); switch (sortMode) { @@ -302,6 +303,7 @@ void LauncherPage::loadSettings() ui->skinsDirTextBox->setText(s->get("SkinsDir").toString()); ui->javaDirTextBox->setText(s->get("JavaDir").toString()); ui->downloadsDirWatchRecursiveCheckBox->setChecked(s->get("DownloadsDirWatchRecursive").toBool()); + ui->downloadsDirMoveCheckBox->setChecked(s->get("MoveModsFromDownloadsDir").toBool()); QString sortMode = s->get("InstSortMode").toString(); diff --git a/launcher/ui/pages/global/LauncherPage.ui b/launcher/ui/pages/global/LauncherPage.ui index a46a6fd5d..7e374662b 100644 --- a/launcher/ui/pages/global/LauncherPage.ui +++ b/launcher/ui/pages/global/LauncherPage.ui @@ -35,7 +35,7 @@ - QTabWidget::TabShape::Rounded + QTabWidget::Rounded 0 @@ -48,7 +48,7 @@ - Qt::ScrollBarPolicy::ScrollBarAlwaysOff + Qt::ScrollBarAsNeeded true @@ -156,14 +156,28 @@ - - - When enabled, in addition to the downloads folder, its sub folders will also be searched when looking for resources (e.g. when looking for blocked mods on CurseForge). - - - Check downloads folder recursively - - + + + + + When enabled, in addition to the downloads folder, its sub folders will also be searched when looking for resources (e.g. when looking for blocked mods on CurseForge). + + + Check downloads folder recursively + + + + + + + When enabled, it will move blocked resources instead of copying them. + + + Move blocked resources + + + + @@ -365,7 +379,7 @@ - Qt::Orientation::Vertical + Qt::Vertical @@ -465,7 +479,7 @@ - Qt::Orientation::Horizontal + Qt::Horizontal @@ -506,7 +520,7 @@ - Qt::Orientation::Vertical + Qt::Vertical @@ -615,13 +629,13 @@ - Qt::ScrollBarPolicy::ScrollBarAlwaysOff + Qt::ScrollBarAsNeeded false - Qt::TextInteractionFlag::TextSelectableByKeyboard|Qt::TextInteractionFlag::TextSelectableByMouse + Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse From e01df73debc8cb578e3e1b1e557388a8d0a7a052 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Tue, 31 Dec 2024 11:13:01 +0200 Subject: [PATCH 57/80] remove EditAccountDialog Signed-off-by: Trial97 --- launcher/CMakeLists.txt | 3 - launcher/ui/dialogs/EditAccountDialog.cpp | 64 --------------- launcher/ui/dialogs/EditAccountDialog.h | 52 ------------- launcher/ui/dialogs/EditAccountDialog.ui | 94 ----------------------- 4 files changed, 213 deletions(-) delete mode 100644 launcher/ui/dialogs/EditAccountDialog.cpp delete mode 100644 launcher/ui/dialogs/EditAccountDialog.h delete mode 100644 launcher/ui/dialogs/EditAccountDialog.ui diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index 991f610dd..00a7274ea 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -1030,8 +1030,6 @@ SET(LAUNCHER_SOURCES ui/dialogs/CopyInstanceDialog.h ui/dialogs/CustomMessageBox.cpp ui/dialogs/CustomMessageBox.h - ui/dialogs/EditAccountDialog.cpp - ui/dialogs/EditAccountDialog.h ui/dialogs/ExportInstanceDialog.cpp ui/dialogs/ExportInstanceDialog.h ui/dialogs/ExportPackDialog.cpp @@ -1217,7 +1215,6 @@ qt_wrap_ui(LAUNCHER_UI ui/dialogs/MSALoginDialog.ui ui/dialogs/OfflineLoginDialog.ui ui/dialogs/AboutDialog.ui - ui/dialogs/EditAccountDialog.ui ui/dialogs/ReviewMessageBox.ui ui/dialogs/ScrollMessageBox.ui ui/dialogs/BlockedModsDialog.ui diff --git a/launcher/ui/dialogs/EditAccountDialog.cpp b/launcher/ui/dialogs/EditAccountDialog.cpp deleted file mode 100644 index 9d0175bbc..000000000 --- a/launcher/ui/dialogs/EditAccountDialog.cpp +++ /dev/null @@ -1,64 +0,0 @@ -/* Copyright 2013-2021 MultiMC Contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "EditAccountDialog.h" -#include -#include -#include -#include "ui_EditAccountDialog.h" - -EditAccountDialog::EditAccountDialog(const QString& text, QWidget* parent, int flags) : QDialog(parent), ui(new Ui::EditAccountDialog) -{ - ui->setupUi(this); - - ui->label->setText(text); - ui->label->setVisible(!text.isEmpty()); - - ui->userTextBox->setEnabled(flags & UsernameField); - ui->passTextBox->setEnabled(flags & PasswordField); - - ui->buttonBox->button(QDialogButtonBox::Cancel)->setText(tr("Cancel")); - ui->buttonBox->button(QDialogButtonBox::Ok)->setText(tr("OK")); -} - -EditAccountDialog::~EditAccountDialog() -{ - delete ui; -} - -void EditAccountDialog::on_label_linkActivated(const QString& link) -{ - DesktopServices::openUrl(QUrl(link)); -} - -void EditAccountDialog::setUsername(const QString& user) const -{ - ui->userTextBox->setText(user); -} - -QString EditAccountDialog::username() const -{ - return ui->userTextBox->text(); -} - -void EditAccountDialog::setPassword(const QString& pass) const -{ - ui->passTextBox->setText(pass); -} - -QString EditAccountDialog::password() const -{ - return ui->passTextBox->text(); -} diff --git a/launcher/ui/dialogs/EditAccountDialog.h b/launcher/ui/dialogs/EditAccountDialog.h deleted file mode 100644 index 7a9ccba79..000000000 --- a/launcher/ui/dialogs/EditAccountDialog.h +++ /dev/null @@ -1,52 +0,0 @@ -/* Copyright 2013-2021 MultiMC Contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once - -#include - -namespace Ui { -class EditAccountDialog; -} - -class EditAccountDialog : public QDialog { - Q_OBJECT - - public: - explicit EditAccountDialog(const QString& text = "", QWidget* parent = 0, int flags = UsernameField | PasswordField); - ~EditAccountDialog(); - - void setUsername(const QString& user) const; - void setPassword(const QString& pass) const; - - QString username() const; - QString password() const; - - enum Flags { - NoFlags = 0, - - //! Specifies that the dialog should have a username field. - UsernameField, - - //! Specifies that the dialog should have a password field. - PasswordField, - }; - - private slots: - void on_label_linkActivated(const QString& link); - - private: - Ui::EditAccountDialog* ui; -}; diff --git a/launcher/ui/dialogs/EditAccountDialog.ui b/launcher/ui/dialogs/EditAccountDialog.ui deleted file mode 100644 index e87509bcb..000000000 --- a/launcher/ui/dialogs/EditAccountDialog.ui +++ /dev/null @@ -1,94 +0,0 @@ - - - EditAccountDialog - - - - 0 - 0 - 400 - 148 - - - - Login - - - - - - Message label placeholder. - - - Qt::RichText - - - Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse - - - - - - - Email - - - - - - - QLineEdit::Password - - - Password - - - - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - - buttonBox - accepted() - EditAccountDialog - accept() - - - 248 - 254 - - - 157 - 274 - - - - - buttonBox - rejected() - EditAccountDialog - reject() - - - 316 - 260 - - - 286 - 274 - - - - - From 6ebfcb91cf954048061ff39719629e7f581f1997 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Tue, 31 Dec 2024 13:44:22 +0200 Subject: [PATCH 58/80] propagate load component error Signed-off-by: Trial97 --- launcher/minecraft/MinecraftLoadAndCheck.cpp | 5 +- launcher/minecraft/PackProfile.cpp | 88 +++++++++++--------- launcher/minecraft/PackProfile.h | 17 +++- launcher/ui/pages/instance/VersionPage.cpp | 7 +- 4 files changed, 71 insertions(+), 46 deletions(-) diff --git a/launcher/minecraft/MinecraftLoadAndCheck.cpp b/launcher/minecraft/MinecraftLoadAndCheck.cpp index b9fb7eb0c..c0a82e61e 100644 --- a/launcher/minecraft/MinecraftLoadAndCheck.cpp +++ b/launcher/minecraft/MinecraftLoadAndCheck.cpp @@ -8,7 +8,10 @@ void MinecraftLoadAndCheck::executeTask() { // add offline metadata load task auto components = m_inst->getPackProfile(); - components->reload(m_netmode); + if (auto result = components->reload(m_netmode); !result) { + emitFailed(result.error); + return; + } m_task = components->getCurrentTask(); if (!m_task) { diff --git a/launcher/minecraft/PackProfile.cpp b/launcher/minecraft/PackProfile.cpp index 1acc87166..d6534b910 100644 --- a/launcher/minecraft/PackProfile.cpp +++ b/launcher/minecraft/PackProfile.cpp @@ -173,29 +173,32 @@ static bool savePackProfile(const QString& filename, const ComponentContainer& c } // Read the given file into component containers -static bool loadPackProfile(PackProfile* parent, - const QString& filename, - const QString& componentJsonPattern, - ComponentContainer& container) +static PackProfile::Result loadPackProfile(PackProfile* parent, + const QString& filename, + const QString& componentJsonPattern, + ComponentContainer& container) { QFile componentsFile(filename); if (!componentsFile.exists()) { - qCWarning(instanceProfileC) << "Components file" << filename << "doesn't exist. This should never happen."; - return false; + auto message = QObject::tr("Components file %1 doesn't exist. This should never happen.").arg(filename); + qCWarning(instanceProfileC) << message; + return PackProfile::Result::Error(message); } if (!componentsFile.open(QFile::ReadOnly)) { - qCCritical(instanceProfileC) << "Couldn't open" << componentsFile.fileName() << " for reading:" << componentsFile.errorString(); + auto message = QObject::tr("Couldn't open %1 for reading: %2").arg(componentsFile.fileName(), componentsFile.errorString()); + qCCritical(instanceProfileC) << message; qCWarning(instanceProfileC) << "Ignoring overridden order"; - return false; + return PackProfile::Result::Error(message); } // and it's valid JSON QJsonParseError error; QJsonDocument doc = QJsonDocument::fromJson(componentsFile.readAll(), &error); if (error.error != QJsonParseError::NoError) { - qCCritical(instanceProfileC) << "Couldn't parse" << componentsFile.fileName() << ":" << error.errorString(); + auto message = QObject::tr("Couldn't parse %1 as json: %2").arg(componentsFile.fileName(), error.errorString()); + qCCritical(instanceProfileC) << message; qCWarning(instanceProfileC) << "Ignoring overridden order"; - return false; + return PackProfile::Result::Error(message); } // and then read it and process it if all above is true. @@ -212,11 +215,13 @@ static bool loadPackProfile(PackProfile* parent, container.append(componentFromJsonV1(parent, componentJsonPattern, comp_obj)); } } catch ([[maybe_unused]] const JSONValidationError& err) { - qCCritical(instanceProfileC) << "Couldn't parse" << componentsFile.fileName() << ": bad file format"; + auto message = QObject::tr("Couldn't parse %1 : bad file format").arg(componentsFile.fileName()); + qCCritical(instanceProfileC) << message; + qCWarning(instanceProfileC) << "error:" << err.what(); container.clear(); - return false; + return PackProfile::Result::Error(message); } - return true; + return PackProfile::Result::Success(); } // END: component file format @@ -283,44 +288,43 @@ void PackProfile::save_internal() d->dirty = false; } -bool PackProfile::load() +PackProfile::Result PackProfile::load() { auto filename = componentsFilePath(); // load the new component list and swap it with the current one... ComponentContainer newComponents; - if (!loadPackProfile(this, filename, patchesPattern(), newComponents)) { + if (auto result = loadPackProfile(this, filename, patchesPattern(), newComponents); !result) { qCritical() << d->m_instance->name() << "|" << "Failed to load the component config"; - return false; - } else { - // FIXME: actually use fine-grained updates, not this... - beginResetModel(); - // disconnect all the old components - for (auto component : d->components) { - disconnect(component.get(), &Component::dataChanged, this, &PackProfile::componentDataChanged); - } - d->components.clear(); - d->componentIndex.clear(); - for (auto component : newComponents) { - if (d->componentIndex.contains(component->m_uid)) { - qWarning() << d->m_instance->name() << "|" << "Ignoring duplicate component entry" << component->m_uid; - continue; - } - connect(component.get(), &Component::dataChanged, this, &PackProfile::componentDataChanged); - d->components.append(component); - d->componentIndex[component->m_uid] = component; - } - endResetModel(); - d->loaded = true; - return true; + return result; } + // FIXME: actually use fine-grained updates, not this... + beginResetModel(); + // disconnect all the old components + for (auto component : d->components) { + disconnect(component.get(), &Component::dataChanged, this, &PackProfile::componentDataChanged); + } + d->components.clear(); + d->componentIndex.clear(); + for (auto component : newComponents) { + if (d->componentIndex.contains(component->m_uid)) { + qWarning() << d->m_instance->name() << "|" << "Ignoring duplicate component entry" << component->m_uid; + continue; + } + connect(component.get(), &Component::dataChanged, this, &PackProfile::componentDataChanged); + d->components.append(component); + d->componentIndex[component->m_uid] = component; + } + endResetModel(); + d->loaded = true; + return Result::Success(); } -void PackProfile::reload(Net::Mode netmode) +PackProfile::Result PackProfile::reload(Net::Mode netmode) { // Do not reload when the update/resolve task is running. It is in control. if (d->m_updateTask) { - return; + return Result::Success(); } // flush any scheduled saves to not lose state @@ -329,9 +333,11 @@ void PackProfile::reload(Net::Mode netmode) // FIXME: differentiate when a reapply is required by propagating state from components invalidateLaunchProfile(); - if (load()) { - resolve(netmode); + if (auto result = load(); !result) { + return result; } + resolve(netmode); + return Result::Success(); } Task::Ptr PackProfile::getCurrentTask() diff --git a/launcher/minecraft/PackProfile.h b/launcher/minecraft/PackProfile.h index b2de26ea0..d812dfa48 100644 --- a/launcher/minecraft/PackProfile.h +++ b/launcher/minecraft/PackProfile.h @@ -62,6 +62,19 @@ class PackProfile : public QAbstractListModel { public: enum Columns { NameColumn = 0, VersionColumn, NUM_COLUMNS }; + struct Result { + bool success; + QString error; + + // Implicit conversion to bool + operator bool() const { return success; } + + // Factory methods for convenience + static Result Success() { return { true, "" }; } + + static Result Error(const QString& errorMessage) { return { false, errorMessage }; } + }; + explicit PackProfile(MinecraftInstance* instance); virtual ~PackProfile(); @@ -102,7 +115,7 @@ class PackProfile : public QAbstractListModel { bool revertToBase(int index); /// reload the list, reload all components, resolve dependencies - void reload(Net::Mode netmode); + Result reload(Net::Mode netmode); // reload all components, resolve dependencies void resolve(Net::Mode netmode); @@ -169,7 +182,7 @@ class PackProfile : public QAbstractListModel { void disableInteraction(bool disable); private: - bool load(); + Result load(); bool installJarMods_internal(QStringList filepaths); bool installCustomJar_internal(QString filepath); bool installAgents_internal(QStringList filepaths); diff --git a/launcher/ui/pages/instance/VersionPage.cpp b/launcher/ui/pages/instance/VersionPage.cpp index ab1c48ed4..975c44de2 100644 --- a/launcher/ui/pages/instance/VersionPage.cpp +++ b/launcher/ui/pages/instance/VersionPage.cpp @@ -252,8 +252,11 @@ void VersionPage::updateButtons(int row) bool VersionPage::reloadPackProfile() { try { - m_profile->reload(Net::Mode::Online); - return true; + auto result = m_profile->reload(Net::Mode::Online); + if (!result) { + QMessageBox::critical(this, tr("Error"), result.error); + } + return result; } catch (const Exception& e) { QMessageBox::critical(this, tr("Error"), e.cause()); return false; From 82a500f4e8828b22431df1acdc06818bf8bb5cc9 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 5 Jan 2025 00:25:34 +0000 Subject: [PATCH 59/80] chore(nix): update lockfile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Flake lock file updates: • Updated input 'nixpkgs': 'github:NixOS/nixpkgs/5d67ea6b4b63378b9c13be21e2ec9d1afc921713?narHash=sha256-Pj39hSoUA86ZePPF/UXiYHHM7hMIkios8TYG29kQT4g%3D' (2024-12-11) → 'github:NixOS/nixpkgs/6df24922a1400241dae323af55f30e4318a6ca65?narHash=sha256-dklw3AXr3OGO4/XT1Tu3Xz9n/we8GctZZ75ZWVqAVhk%3D' (2025-01-02) --- flake.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index f01d7da12..c2f37cf0d 100644 --- a/flake.lock +++ b/flake.lock @@ -49,11 +49,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1733940404, - "narHash": "sha256-Pj39hSoUA86ZePPF/UXiYHHM7hMIkios8TYG29kQT4g=", + "lastModified": 1735834308, + "narHash": "sha256-dklw3AXr3OGO4/XT1Tu3Xz9n/we8GctZZ75ZWVqAVhk=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "5d67ea6b4b63378b9c13be21e2ec9d1afc921713", + "rev": "6df24922a1400241dae323af55f30e4318a6ca65", "type": "github" }, "original": { From d40c8b704ce1e1d755c99c6b44e747eec48442e3 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Wed, 8 Jan 2025 01:52:11 +0200 Subject: [PATCH 60/80] fix drop file on resource page Signed-off-by: Trial97 --- launcher/ui/pages/instance/ExternalResourcesPage.ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/ui/pages/instance/ExternalResourcesPage.ui b/launcher/ui/pages/instance/ExternalResourcesPage.ui index 9c41f3a71..5df8aafa2 100644 --- a/launcher/ui/pages/instance/ExternalResourcesPage.ui +++ b/launcher/ui/pages/instance/ExternalResourcesPage.ui @@ -60,7 +60,7 @@ true - QAbstractItemView::NoDragDrop + QAbstractItemView::DropOnly true From 0f9ea5c9498fcfe024034cad465b6be9908041b7 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Wed, 8 Jan 2025 01:55:45 +0200 Subject: [PATCH 61/80] remove drop label Signed-off-by: Trial97 --- launcher/CMakeLists.txt | 2 -- launcher/ui/widgets/DropLabel.cpp | 40 ------------------------------- launcher/ui/widgets/DropLabel.h | 19 --------------- 3 files changed, 61 deletions(-) delete mode 100644 launcher/ui/widgets/DropLabel.cpp delete mode 100644 launcher/ui/widgets/DropLabel.h diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index 991f610dd..7a569caca 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -1085,8 +1085,6 @@ SET(LAUNCHER_SOURCES ui/widgets/CustomCommands.h ui/widgets/EnvironmentVariables.cpp ui/widgets/EnvironmentVariables.h - ui/widgets/DropLabel.cpp - ui/widgets/DropLabel.h ui/widgets/FocusLineEdit.cpp ui/widgets/FocusLineEdit.h ui/widgets/IconLabel.cpp diff --git a/launcher/ui/widgets/DropLabel.cpp b/launcher/ui/widgets/DropLabel.cpp deleted file mode 100644 index b1473b358..000000000 --- a/launcher/ui/widgets/DropLabel.cpp +++ /dev/null @@ -1,40 +0,0 @@ -#include "DropLabel.h" - -#include -#include - -DropLabel::DropLabel(QWidget* parent) : QLabel(parent) -{ - setAcceptDrops(true); -} - -void DropLabel::dragEnterEvent(QDragEnterEvent* event) -{ - event->acceptProposedAction(); -} - -void DropLabel::dragMoveEvent(QDragMoveEvent* event) -{ - event->acceptProposedAction(); -} - -void DropLabel::dragLeaveEvent(QDragLeaveEvent* event) -{ - event->accept(); -} - -void DropLabel::dropEvent(QDropEvent* event) -{ - const QMimeData* mimeData = event->mimeData(); - - if (!mimeData) { - return; - } - - if (mimeData->hasUrls()) { - auto urls = mimeData->urls(); - emit droppedURLs(urls); - } - - event->acceptProposedAction(); -} diff --git a/launcher/ui/widgets/DropLabel.h b/launcher/ui/widgets/DropLabel.h deleted file mode 100644 index 0027f48b1..000000000 --- a/launcher/ui/widgets/DropLabel.h +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once - -#include - -class DropLabel : public QLabel { - Q_OBJECT - - public: - explicit DropLabel(QWidget* parent = nullptr); - - signals: - void droppedURLs(QList urls); - - protected: - void dropEvent(QDropEvent* event) override; - void dragEnterEvent(QDragEnterEvent* event) override; - void dragMoveEvent(QDragMoveEvent* event) override; - void dragLeaveEvent(QDragLeaveEvent* event) override; -}; From 54da41c6253ddd8af20ff30044a208c9b529db7c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 11 Jan 2025 22:11:18 +0000 Subject: [PATCH 62/80] chore(deps): update hendrikmuhs/ccache-action action to v1.2.16 --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0770b66dd..f9469be2e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -167,7 +167,7 @@ jobs: - name: Setup ccache if: (runner.os != 'Windows' || matrix.msystem == '') && inputs.build_type == 'Debug' - uses: hendrikmuhs/ccache-action@v1.2.14 + uses: hendrikmuhs/ccache-action@v1.2.16 with: key: ${{ matrix.os }}-qt${{ matrix.qt_ver }}-${{ matrix.architecture }} From 03834e14558475bafd542ad1365f35cce243682f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 12 Jan 2025 00:26:01 +0000 Subject: [PATCH 63/80] chore(nix): update lockfile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Flake lock file updates: • Updated input 'nixpkgs': 'github:NixOS/nixpkgs/6df24922a1400241dae323af55f30e4318a6ca65?narHash=sha256-dklw3AXr3OGO4/XT1Tu3Xz9n/we8GctZZ75ZWVqAVhk%3D' (2025-01-02) → 'github:NixOS/nixpkgs/bffc22eb12172e6db3c5dde9e3e5628f8e3e7912?narHash=sha256-8YVQ9ZbSfuUk2bUf2KRj60NRraLPKPS0Q4QFTbc%2Bc2c%3D' (2025-01-08) --- flake.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index c2f37cf0d..3ab2fcd67 100644 --- a/flake.lock +++ b/flake.lock @@ -49,11 +49,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1735834308, - "narHash": "sha256-dklw3AXr3OGO4/XT1Tu3Xz9n/we8GctZZ75ZWVqAVhk=", + "lastModified": 1736344531, + "narHash": "sha256-8YVQ9ZbSfuUk2bUf2KRj60NRraLPKPS0Q4QFTbc+c2c=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "6df24922a1400241dae323af55f30e4318a6ca65", + "rev": "bffc22eb12172e6db3c5dde9e3e5628f8e3e7912", "type": "github" }, "original": { From 3ee73916ca31666abc48f45e8b0bfcf8d678e6cf Mon Sep 17 00:00:00 2001 From: Trial97 Date: Mon, 13 Jan 2025 08:16:12 +0200 Subject: [PATCH 64/80] fix modrinth link Signed-off-by: Trial97 --- launcher/ui/pages/global/APIPage.ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/ui/pages/global/APIPage.ui b/launcher/ui/pages/global/APIPage.ui index 9c713aa79..05c256bb2 100644 --- a/launcher/ui/pages/global/APIPage.ui +++ b/launcher/ui/pages/global/APIPage.ui @@ -207,7 +207,7 @@ - <html><head/><body><p>Note: you only need to set this to access private data. Read the <a href="https://docs.modrinth.com/#section/Authentication">documentation</a> for more information.</p></body></html> + <html><head/><body><p>Note: you only need to set this to access private data. Read the <a href="https://docs.modrinth.com/api/#authentication">documentation</a> for more information.</p></body></html> true From e4ad4051c8b87bd5102a76a860408de2b447d74d Mon Sep 17 00:00:00 2001 From: Trial97 Date: Mon, 13 Jan 2025 13:56:55 +0200 Subject: [PATCH 65/80] fix curseforge with empty loader as newest version Signed-off-by: Trial97 --- launcher/modplatform/flame/FlameAPI.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/launcher/modplatform/flame/FlameAPI.cpp b/launcher/modplatform/flame/FlameAPI.cpp index 53eadcf02..699eb792a 100644 --- a/launcher/modplatform/flame/FlameAPI.cpp +++ b/launcher/modplatform/flame/FlameAPI.cpp @@ -270,6 +270,7 @@ std::optional FlameAPI::getLatestVersion(QList instanceLoaders, ModPlatform::ModLoaderTypes modLoaders) { + static const auto noLoader = ModPlatform::ModLoaderType(0); QHash bestMatch; auto checkVersion = [&bestMatch](const ModPlatform::IndexedVersion& version, const ModPlatform::ModLoaderType& loader) { if (bestMatch.contains(loader)) { @@ -284,7 +285,7 @@ std::optional FlameAPI::getLatestVersion(QList FlameAPI::getLatestVersion(QList fabric version will be prioritizated on update auto currentLoaders = instanceLoaders + ModPlatform::modLoaderTypesToList(modLoaders); - currentLoaders.append(ModPlatform::ModLoaderType(0)); // add a fallback in case the versions do not define a loader + currentLoaders.append(noLoader); // add a fallback in case the versions do not define a loader for (auto loader : currentLoaders) { if (bestMatch.contains(loader)) { - return bestMatch.value(loader); + auto bestForLoader = bestMatch.value(loader); + // awkward case where the mod has only two loaders and one of them is not specified + if (loader != noLoader && bestMatch.contains(noLoader) && bestMatch.size() == 2) { + auto bestForNoLoader = bestMatch.value(noLoader); + if (bestForNoLoader.date > bestForLoader.date) { + return bestForNoLoader; + } + } + return bestForLoader; } } return {}; From bca517b8d3cd685540beebf69fbc1f80fe0a6ce4 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 16 Jan 2025 12:10:19 +0200 Subject: [PATCH 66/80] fix appimage Signed-off-by: Trial97 --- .github/workflows/build.yml | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0770b66dd..12dea1715 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -62,7 +62,7 @@ jobs: qt_version: "5.15.2" qt_modules: "qtnetworkauth" - - os: ubuntu-20.04 + - os: ubuntu-22.04 qt_ver: 6 qt_host: linux qt_arch: "" @@ -259,7 +259,7 @@ jobs: wget "https://github.com/AppImageCommunity/AppImageUpdate/releases/download/continuous/AppImageUpdate-x86_64.AppImage" - sudo apt install libopengl0 + sudo apt install libopengl0 libfuse2 - name: Add QT_HOST_PATH var (Windows MSVC arm64) if: runner.os == 'Windows' && matrix.architecture == 'arm64' @@ -521,8 +521,8 @@ jobs: cp -r ${{ runner.workspace }}/Qt/${{ matrix.qt_version }}/gcc_64/plugins/iconengines/* ${{ env.INSTALL_APPIMAGE_DIR }}/usr/plugins/iconengines - cp /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1 ${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib/ - cp /usr/lib/x86_64-linux-gnu/libssl.so.1.1 ${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib/ + cp /usr/lib/x86_64-linux-gnu/libcrypto.so.3 ${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib/ + cp /usr/lib/x86_64-linux-gnu/libssl.so.3 ${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib/ cp /usr/lib/x86_64-linux-gnu/libOpenGL.so.0* ${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib/ LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib" @@ -547,8 +547,27 @@ jobs: mv "PrismLauncher-Linux-x86_64.AppImage" "PrismLauncher-Linux-${{ env.VERSION }}-${{ inputs.build_type }}-x86_64.AppImage" - - name: Package (Linux, portable) - if: runner.os == 'Linux' + - name: Package (Linux, qt6, portable) + if: runner.os == 'Linux' && matrix.qt_ver != 5 + run: | + cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_PORTABLE_DIR }} -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DLauncher_BUILD_PLATFORM=official -DCMAKE_C_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DCMAKE_CXX_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DLauncher_QT_VERSION_MAJOR=${{ matrix.qt_ver }} -DLauncher_BUILD_ARTIFACT=Linux-Qt${{ matrix.qt_ver }} -DINSTALL_BUNDLE=full -G Ninja + cmake --install ${{ env.BUILD_DIR }} + cmake --install ${{ env.BUILD_DIR }} --component portable + + mkdir ${{ env.INSTALL_PORTABLE_DIR }}/lib + cp /lib/x86_64-linux-gnu/libbz2.so.1.0 ${{ env.INSTALL_PORTABLE_DIR }}/lib + cp /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0 ${{ env.INSTALL_PORTABLE_DIR }}/lib + cp /usr/lib/x86_64-linux-gnu/libcrypto.so.3 ${{ env.INSTALL_PORTABLE_DIR }}/lib + cp /usr/lib/x86_64-linux-gnu/libssl.so.3 ${{ env.INSTALL_PORTABLE_DIR }}/lib + cp /usr/lib/x86_64-linux-gnu/libffi.so.8 ${{ env.INSTALL_PORTABLE_DIR }}/lib + mv ${{ env.INSTALL_PORTABLE_DIR }}/bin/*.so* ${{ env.INSTALL_PORTABLE_DIR }}/lib + + for l in $(find ${{ env.INSTALL_PORTABLE_DIR }} -type f); do l=${l#$(pwd)/}; l=${l#${{ env.INSTALL_PORTABLE_DIR }}/}; l=${l#./}; echo $l; done > ${{ env.INSTALL_PORTABLE_DIR }}/manifest.txt + cd ${{ env.INSTALL_PORTABLE_DIR }} + tar -czf ../PrismLauncher-portable.tar.gz * + + - name: Package (Linux, qt5, portable) + if: runner.os == 'Linux' && matrix.qt_ver == 5 run: | cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_PORTABLE_DIR }} -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DLauncher_BUILD_PLATFORM=official -DCMAKE_C_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DCMAKE_CXX_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DLauncher_QT_VERSION_MAJOR=${{ matrix.qt_ver }} -DLauncher_BUILD_ARTIFACT=Linux-Qt${{ matrix.qt_ver }} -DINSTALL_BUNDLE=full -G Ninja cmake --install ${{ env.BUILD_DIR }} From 7cb8deeb9072d0635728d72835645102ff241da3 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 20 Jul 2023 19:59:58 +0300 Subject: [PATCH 67/80] feat: updated flame mod resolution Signed-off-by: Trial97 --- .../modplatform/flame/FileResolvingTask.cpp | 28 +++++++++++++++++++ .../flame/FlameInstanceCreationTask.cpp | 3 +- launcher/modplatform/flame/PackManifest.h | 3 ++ 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/launcher/modplatform/flame/FileResolvingTask.cpp b/launcher/modplatform/flame/FileResolvingTask.cpp index d69bf12c0..7ff38d57e 100644 --- a/launcher/modplatform/flame/FileResolvingTask.cpp +++ b/launcher/modplatform/flame/FileResolvingTask.cpp @@ -87,6 +87,30 @@ void Flame::FileResolvingTask::executeTask() m_task->start(); } +PackedResourceType getResourceType(int classId) +{ + switch (classId) { + case 17: // Worlds + return PackedResourceType::WorldSave; + case 6: // Mods + return PackedResourceType::Mod; + case 12: // Resource Packs + // return PackedResourceType::ResourcePack; // not really a resourcepack + /* fallthrough */ + case 4546: // Customization + // return PackedResourceType::ShaderPack; // not really a shaderPack + /* fallthrough */ + case 4471: // Modpacks + /* fallthrough */ + case 5: // Bukkit Plugins + /* fallthrough */ + case 4559: // Addons + /* fallthrough */ + default: + return PackedResourceType::UNKNOWN; + } +} + void Flame::FileResolvingTask::netJobFinished() { setProgress(1, 3); @@ -232,6 +256,10 @@ void Flame::FileResolvingTask::getFlameProjects() setStatus(tr("Parsing API response from CurseForge for '%1'...").arg(file->version.fileName)); FlameMod::loadIndexedPack(file->pack, entry_obj); + file->resourceType = getResourceType(Json::requireInteger(entry_obj, "classId", "modClassId")); + if (file->resourceType == PackedResourceType::WorldSave) { + file->targetFolder = "saves"; + } } } catch (Json::JsonException& e) { qDebug() << e.cause(); diff --git a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp index e60d32cc0..b16277b48 100644 --- a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp +++ b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp @@ -474,7 +474,7 @@ void FlameCreationTask::idResolverSucceeded(QEventLoop& loop) QList blocked_mods; auto anyBlocked = false; for (const auto& result : results.files.values()) { - if (result.version.fileName.endsWith(".zip")) { + if (result.resourceType != PackedResourceType::Mod) { m_ZIP_resources.append(std::make_pair(result.version.fileName, result.targetFolder)); } @@ -678,6 +678,7 @@ void FlameCreationTask::validateZIPResources(QEventLoop& loop) installWorld(worldPath); break; case PackedResourceType::UNKNOWN: + /* fallthrough */ default: qDebug() << "Can't Identify" << fileName << "at" << localPath << ", leaving it where it is."; break; diff --git a/launcher/modplatform/flame/PackManifest.h b/launcher/modplatform/flame/PackManifest.h index 49a0b2d68..7d3693756 100644 --- a/launcher/modplatform/flame/PackManifest.h +++ b/launcher/modplatform/flame/PackManifest.h @@ -40,6 +40,7 @@ #include #include #include +#include "minecraft/mod/tasks/LocalResourceParse.h" #include "modplatform/ModIndex.h" namespace Flame { @@ -54,6 +55,8 @@ struct File { // our QString targetFolder = QStringLiteral("mods"); + enum class Type { Unknown, Folder, Ctoc, SingleFile, Cmod2, Modpack, Mod } type = Type::Mod; + PackedResourceType resourceType; }; struct Modloader { From 9317a675eddd5cb6f4845ca74f57f09b27453a2e Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 16 Jan 2025 17:07:44 +0200 Subject: [PATCH 68/80] removed unused type Signed-off-by: Trial97 --- launcher/modplatform/flame/PackManifest.h | 1 - 1 file changed, 1 deletion(-) diff --git a/launcher/modplatform/flame/PackManifest.h b/launcher/modplatform/flame/PackManifest.h index 7d3693756..7af3b9d6b 100644 --- a/launcher/modplatform/flame/PackManifest.h +++ b/launcher/modplatform/flame/PackManifest.h @@ -55,7 +55,6 @@ struct File { // our QString targetFolder = QStringLiteral("mods"); - enum class Type { Unknown, Folder, Ctoc, SingleFile, Cmod2, Modpack, Mod } type = Type::Mod; PackedResourceType resourceType; }; From 7d3238d234ca514436f608384ce7ceb94d0630eb Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 17 Jan 2025 21:09:44 +0200 Subject: [PATCH 69/80] rename variables Signed-off-by: Trial97 --- .../flame/FlameInstanceCreationTask.cpp | 78 +++++++++---------- .../flame/FlameInstanceCreationTask.h | 14 ++-- 2 files changed, 46 insertions(+), 46 deletions(-) diff --git a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp index b16277b48..6073e90a2 100644 --- a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp +++ b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp @@ -75,12 +75,12 @@ bool FlameCreationTask::abort() return false; m_abort = true; - if (m_process_update_file_info_job) - m_process_update_file_info_job->abort(); - if (m_files_job) - m_files_job->abort(); - if (m_mod_id_resolver) - m_mod_id_resolver->abort(); + if (m_processUpdateFileInfoJob) + m_processUpdateFileInfoJob->abort(); + if (m_filesJob) + m_filesJob->abort(); + if (m_modIdResolver) + m_modIdResolver->abort(); return Task::abort(); } @@ -232,12 +232,12 @@ bool FlameCreationTask::updateInstance() connect(job.get(), &Task::failed, this, [](QString reason) { qCritical() << "Failed to get files: " << reason; }); connect(job.get(), &Task::finished, &loop, &QEventLoop::quit); - m_process_update_file_info_job = job; + m_processUpdateFileInfoJob = job; job->start(); loop.exec(); - m_process_update_file_info_job = nullptr; + m_processUpdateFileInfoJob = nullptr; } else { // We don't have an old index file, so we may duplicate stuff! auto dialog = CustomMessageBox::selectable(m_parent, tr("No index file."), @@ -430,26 +430,26 @@ bool FlameCreationTask::createInstance() } // Don't add managed info to packs without an ID (most likely imported from ZIP) - if (!m_managed_id.isEmpty()) - instance.setManagedPack("flame", m_managed_id, m_pack.name, m_managed_version_id, m_pack.version); + if (!m_managedId.isEmpty()) + instance.setManagedPack("flame", m_managedId, m_pack.name, m_managedVersionId, m_pack.version); else instance.setManagedPack("flame", "", name(), "", ""); instance.setName(name()); - m_mod_id_resolver.reset(new Flame::FileResolvingTask(APPLICATION->network(), m_pack)); - connect(m_mod_id_resolver.get(), &Flame::FileResolvingTask::succeeded, this, [this, &loop] { idResolverSucceeded(loop); }); - connect(m_mod_id_resolver.get(), &Flame::FileResolvingTask::failed, [this, &loop](QString reason) { - m_mod_id_resolver.reset(); + m_modIdResolver.reset(new Flame::FileResolvingTask(APPLICATION->network(), m_pack)); + connect(m_modIdResolver.get(), &Flame::FileResolvingTask::succeeded, this, [this, &loop] { idResolverSucceeded(loop); }); + connect(m_modIdResolver.get(), &Flame::FileResolvingTask::failed, [this, &loop](QString reason) { + m_modIdResolver.reset(); setError(tr("Unable to resolve mod IDs:\n") + reason); loop.quit(); }); - connect(m_mod_id_resolver.get(), &Flame::FileResolvingTask::aborted, &loop, &QEventLoop::quit); - connect(m_mod_id_resolver.get(), &Flame::FileResolvingTask::progress, this, &FlameCreationTask::setProgress); - connect(m_mod_id_resolver.get(), &Flame::FileResolvingTask::status, this, &FlameCreationTask::setStatus); - connect(m_mod_id_resolver.get(), &Flame::FileResolvingTask::stepProgress, this, &FlameCreationTask::propagateStepProgress); - connect(m_mod_id_resolver.get(), &Flame::FileResolvingTask::details, this, &FlameCreationTask::setDetails); - m_mod_id_resolver->start(); + connect(m_modIdResolver.get(), &Flame::FileResolvingTask::aborted, &loop, &QEventLoop::quit); + connect(m_modIdResolver.get(), &Flame::FileResolvingTask::progress, this, &FlameCreationTask::setProgress); + connect(m_modIdResolver.get(), &Flame::FileResolvingTask::status, this, &FlameCreationTask::setStatus); + connect(m_modIdResolver.get(), &Flame::FileResolvingTask::stepProgress, this, &FlameCreationTask::propagateStepProgress); + connect(m_modIdResolver.get(), &Flame::FileResolvingTask::details, this, &FlameCreationTask::setDetails); + m_modIdResolver->start(); loop.exec(); @@ -468,14 +468,14 @@ bool FlameCreationTask::createInstance() void FlameCreationTask::idResolverSucceeded(QEventLoop& loop) { - auto results = m_mod_id_resolver->getResults(); + auto results = m_modIdResolver->getResults(); // first check for blocked mods QList blocked_mods; auto anyBlocked = false; for (const auto& result : results.files.values()) { if (result.resourceType != PackedResourceType::Mod) { - m_ZIP_resources.append(std::make_pair(result.version.fileName, result.targetFolder)); + m_otherResources.append(std::make_pair(result.version.fileName, result.targetFolder)); } if (result.version.downloadUrl.isEmpty()) { @@ -507,7 +507,7 @@ void FlameCreationTask::idResolverSucceeded(QEventLoop& loop) copyBlockedMods(blocked_mods); setupDownloadJob(loop); } else { - m_mod_id_resolver.reset(); + m_modIdResolver.reset(); setError("Canceled"); loop.quit(); } @@ -518,8 +518,8 @@ void FlameCreationTask::idResolverSucceeded(QEventLoop& loop) void FlameCreationTask::setupDownloadJob(QEventLoop& loop) { - m_files_job.reset(new NetJob(tr("Mod Download Flame"), APPLICATION->network())); - auto results = m_mod_id_resolver->getResults().files; + m_filesJob.reset(new NetJob(tr("Mod Download Flame"), APPLICATION->network())); + auto results = m_modIdResolver->getResults().files; QStringList optionalFiles; for (auto& result : results) { @@ -554,26 +554,26 @@ void FlameCreationTask::setupDownloadJob(QEventLoop& loop) if (!result.version.downloadUrl.isEmpty()) { qDebug() << "Will download" << result.version.downloadUrl << "to" << path; auto dl = Net::ApiDownload::makeFile(result.version.downloadUrl, path); - m_files_job->addNetAction(dl); + m_filesJob->addNetAction(dl); } } - connect(m_files_job.get(), &NetJob::finished, this, [this, &loop]() { - m_files_job.reset(); - validateZIPResources(loop); + connect(m_filesJob.get(), &NetJob::finished, this, [this, &loop]() { + m_filesJob.reset(); + validateOtherResources(loop); }); - connect(m_files_job.get(), &NetJob::failed, [this](QString reason) { - m_files_job.reset(); + connect(m_filesJob.get(), &NetJob::failed, [this](QString reason) { + m_filesJob.reset(); setError(reason); }); - connect(m_files_job.get(), &NetJob::progress, this, [this](qint64 current, qint64 total) { + connect(m_filesJob.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::propagateStepProgress); + connect(m_filesJob.get(), &NetJob::stepProgress, this, &FlameCreationTask::propagateStepProgress); setStatus(tr("Downloading mods...")); - m_files_job->start(); + m_filesJob->start(); } /// @brief copy the matched blocked mods to the instance staging area @@ -614,11 +614,11 @@ void FlameCreationTask::copyBlockedMods(QList const& blocked_mods) setAbortable(true); } -void FlameCreationTask::validateZIPResources(QEventLoop& loop) +void FlameCreationTask::validateOtherResources(QEventLoop& loop) { - qDebug() << "Validating whether resources stored as .zip are in the right place"; + qDebug() << "Validating whether other resources are in the right place"; QStringList zipMods; - for (auto [fileName, targetFolder] : m_ZIP_resources) { + for (auto [fileName, targetFolder] : m_otherResources) { qDebug() << "Checking" << fileName << "..."; auto localPath = FS::PathCombine(m_stagingPath, "minecraft", targetFolder, fileName); @@ -686,7 +686,7 @@ void FlameCreationTask::validateZIPResources(QEventLoop& loop) } // TODO make this work with other sorts of resource auto task = makeShared("CreateModMetadata", APPLICATION->settings()->get("NumberOfConcurrentTasks").toInt()); - auto results = m_mod_id_resolver->getResults().files; + auto results = m_modIdResolver->getResults().files; auto folder = FS::PathCombine(m_stagingPath, "minecraft", "mods", ".index"); for (auto file : results) { if (file.targetFolder != "mods" || (file.version.fileName.endsWith(".zip") && !zipMods.contains(file.version.fileName))) { @@ -695,6 +695,6 @@ void FlameCreationTask::validateZIPResources(QEventLoop& loop) task->addTask(makeShared(folder, file.pack, file.version)); } connect(task.get(), &Task::finished, &loop, &QEventLoop::quit); - m_process_update_file_info_job = task; + m_processUpdateFileInfoJob = task; task->start(); } diff --git a/launcher/modplatform/flame/FlameInstanceCreationTask.h b/launcher/modplatform/flame/FlameInstanceCreationTask.h index 28ab176c2..3e586a416 100644 --- a/launcher/modplatform/flame/FlameInstanceCreationTask.h +++ b/launcher/modplatform/flame/FlameInstanceCreationTask.h @@ -57,7 +57,7 @@ class FlameCreationTask final : public InstanceCreationTask { QString id, QString version_id, QString original_instance_id = {}) - : InstanceCreationTask(), m_parent(parent), m_managed_id(std::move(id)), m_managed_version_id(std::move(version_id)) + : InstanceCreationTask(), m_parent(parent), m_managedId(std::move(id)), m_managedVersionId(std::move(version_id)) { setStagingPath(staging_path); setParentSettings(global_settings); @@ -74,22 +74,22 @@ class FlameCreationTask final : public InstanceCreationTask { void idResolverSucceeded(QEventLoop&); void setupDownloadJob(QEventLoop&); void copyBlockedMods(QList const& blocked_mods); - void validateZIPResources(QEventLoop& loop); + void validateOtherResources(QEventLoop& loop); QString getVersionForLoader(QString uid, QString loaderType, QString version, QString mcVersion); private: QWidget* m_parent = nullptr; - shared_qobject_ptr m_mod_id_resolver; + shared_qobject_ptr m_modIdResolver; Flame::Manifest m_pack; // Handle to allow aborting - Task::Ptr m_process_update_file_info_job = nullptr; - NetJob::Ptr m_files_job = nullptr; + Task::Ptr m_processUpdateFileInfoJob = nullptr; + NetJob::Ptr m_filesJob = nullptr; - QString m_managed_id, m_managed_version_id; + QString m_managedId, m_managedVersionId; - QList> m_ZIP_resources; + QList> m_otherResources; std::optional m_instance; }; From 8e8538b506b5f3ae2b2424599078966600bb764c Mon Sep 17 00:00:00 2001 From: seth Date: Sat, 18 Jan 2025 16:55:25 -0500 Subject: [PATCH 70/80] ci: build nix packages for aarch64-linux Signed-off-by: seth --- .github/workflows/build.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f9469be2e..5cc71d88d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -665,6 +665,9 @@ jobs: - os: ubuntu-22.04 system: x86_64-linux + - os: ubuntu-22.04-arm + system: aarch64-linux + - os: macos-13 system: x86_64-darwin From 66f0397087d9b88c93e69c5e26a138d235344546 Mon Sep 17 00:00:00 2001 From: seth Date: Sat, 18 Jan 2025 17:05:17 -0500 Subject: [PATCH 71/80] ci: build flatpaks for arm Signed-off-by: seth --- .github/workflows/build.yml | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f9469be2e..338c7219e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -633,10 +633,24 @@ jobs: ccache -s flatpak: - runs-on: ubuntu-latest + name: Flatpak (${{ matrix.arch }}) + + strategy: + fail-fast: false + matrix: + include: + - os: ubuntu-22.04 + arch: x86_64 + + - os: ubuntu-22.04-arm + arch: aarch64 + + runs-on: ${{ matrix.os }} + container: image: ghcr.io/flathub-infra/flatpak-github-actions:kde-6.8 options: --privileged + steps: - name: Checkout uses: actions/checkout@v4 @@ -654,6 +668,7 @@ jobs: with: bundle: PrismLauncher-${{ runner.os }}-${{ env.VERSION }}-Flatpak.flatpak manifest-path: flatpak/org.prismlauncher.PrismLauncher.yml + arch: ${{ matrix.arch }} nix: name: Nix (${{ matrix.system }}) From be3eca8c97fdbb8daede84cab20fbd7695334242 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sun, 19 Jan 2025 01:05:06 +0200 Subject: [PATCH 72/80] remove specific step for qt6 Signed-off-by: Trial97 --- .github/workflows/build.yml | 29 +++++------------------------ 1 file changed, 5 insertions(+), 24 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 12dea1715..bbe2adee4 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -547,8 +547,8 @@ jobs: mv "PrismLauncher-Linux-x86_64.AppImage" "PrismLauncher-Linux-${{ env.VERSION }}-${{ inputs.build_type }}-x86_64.AppImage" - - name: Package (Linux, qt6, portable) - if: runner.os == 'Linux' && matrix.qt_ver != 5 + - name: Package (Linux, portable) + if: runner.os == 'Linux' run: | cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_PORTABLE_DIR }} -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DLauncher_BUILD_PLATFORM=official -DCMAKE_C_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DCMAKE_CXX_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DLauncher_QT_VERSION_MAJOR=${{ matrix.qt_ver }} -DLauncher_BUILD_ARTIFACT=Linux-Qt${{ matrix.qt_ver }} -DINSTALL_BUNDLE=full -G Ninja cmake --install ${{ env.BUILD_DIR }} @@ -557,28 +557,9 @@ jobs: mkdir ${{ env.INSTALL_PORTABLE_DIR }}/lib cp /lib/x86_64-linux-gnu/libbz2.so.1.0 ${{ env.INSTALL_PORTABLE_DIR }}/lib cp /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0 ${{ env.INSTALL_PORTABLE_DIR }}/lib - cp /usr/lib/x86_64-linux-gnu/libcrypto.so.3 ${{ env.INSTALL_PORTABLE_DIR }}/lib - cp /usr/lib/x86_64-linux-gnu/libssl.so.3 ${{ env.INSTALL_PORTABLE_DIR }}/lib - cp /usr/lib/x86_64-linux-gnu/libffi.so.8 ${{ env.INSTALL_PORTABLE_DIR }}/lib - mv ${{ env.INSTALL_PORTABLE_DIR }}/bin/*.so* ${{ env.INSTALL_PORTABLE_DIR }}/lib - - for l in $(find ${{ env.INSTALL_PORTABLE_DIR }} -type f); do l=${l#$(pwd)/}; l=${l#${{ env.INSTALL_PORTABLE_DIR }}/}; l=${l#./}; echo $l; done > ${{ env.INSTALL_PORTABLE_DIR }}/manifest.txt - cd ${{ env.INSTALL_PORTABLE_DIR }} - tar -czf ../PrismLauncher-portable.tar.gz * - - - name: Package (Linux, qt5, portable) - if: runner.os == 'Linux' && matrix.qt_ver == 5 - run: | - cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_PORTABLE_DIR }} -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DLauncher_BUILD_PLATFORM=official -DCMAKE_C_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DCMAKE_CXX_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DLauncher_QT_VERSION_MAJOR=${{ matrix.qt_ver }} -DLauncher_BUILD_ARTIFACT=Linux-Qt${{ matrix.qt_ver }} -DINSTALL_BUNDLE=full -G Ninja - cmake --install ${{ env.BUILD_DIR }} - cmake --install ${{ env.BUILD_DIR }} --component portable - - mkdir ${{ env.INSTALL_PORTABLE_DIR }}/lib - cp /lib/x86_64-linux-gnu/libbz2.so.1.0 ${{ env.INSTALL_PORTABLE_DIR }}/lib - cp /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0 ${{ env.INSTALL_PORTABLE_DIR }}/lib - cp /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1 ${{ env.INSTALL_PORTABLE_DIR }}/lib - cp /usr/lib/x86_64-linux-gnu/libssl.so.1.1 ${{ env.INSTALL_PORTABLE_DIR }}/lib - cp /usr/lib/x86_64-linux-gnu/libffi.so.7 ${{ env.INSTALL_PORTABLE_DIR }}/lib + cp /usr/lib/x86_64-linux-gnu/libcrypto.so.* ${{ env.INSTALL_PORTABLE_DIR }}/lib + cp /usr/lib/x86_64-linux-gnu/libssl.so.* ${{ env.INSTALL_PORTABLE_DIR }}/lib + cp /usr/lib/x86_64-linux-gnu/libffi.so.* ${{ env.INSTALL_PORTABLE_DIR }}/lib mv ${{ env.INSTALL_PORTABLE_DIR }}/bin/*.so* ${{ env.INSTALL_PORTABLE_DIR }}/lib for l in $(find ${{ env.INSTALL_PORTABLE_DIR }} -type f); do l=${l#$(pwd)/}; l=${l#${{ env.INSTALL_PORTABLE_DIR }}/}; l=${l#./}; echo $l; done > ${{ env.INSTALL_PORTABLE_DIR }}/manifest.txt From 1b5d3c2bf903bbcade7b38c22c0b103a0c6999f8 Mon Sep 17 00:00:00 2001 From: Alexandru Ionut Tripon Date: Sun, 19 Jan 2025 02:03:21 +0200 Subject: [PATCH 73/80] Update .github/workflows/build.yml Co-authored-by: seth Signed-off-by: Alexandru Ionut Tripon --- .github/workflows/build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index bbe2adee4..169d63176 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -521,8 +521,8 @@ jobs: cp -r ${{ runner.workspace }}/Qt/${{ matrix.qt_version }}/gcc_64/plugins/iconengines/* ${{ env.INSTALL_APPIMAGE_DIR }}/usr/plugins/iconengines - cp /usr/lib/x86_64-linux-gnu/libcrypto.so.3 ${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib/ - cp /usr/lib/x86_64-linux-gnu/libssl.so.3 ${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib/ + cp /usr/lib/x86_64-linux-gnu/libcrypto.so.* ${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib/ + cp /usr/lib/x86_64-linux-gnu/libssl.so.* ${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib/ cp /usr/lib/x86_64-linux-gnu/libOpenGL.so.0* ${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib/ LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib" From 8d4f27953978d1f308ac152fa5cfb9e860bf7cef Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 19 Jan 2025 00:24:56 +0000 Subject: [PATCH 74/80] chore(nix): update lockfile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Flake lock file updates: • Updated input 'nixpkgs': 'github:NixOS/nixpkgs/bffc22eb12172e6db3c5dde9e3e5628f8e3e7912?narHash=sha256-8YVQ9ZbSfuUk2bUf2KRj60NRraLPKPS0Q4QFTbc%2Bc2c%3D' (2025-01-08) → 'github:NixOS/nixpkgs/5df43628fdf08d642be8ba5b3625a6c70731c19c?narHash=sha256-Tbk1MZbtV2s5aG%2BiM99U8FqwxU/YNArMcWAv6clcsBc%3D' (2025-01-16) --- flake.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index 3ab2fcd67..01f66b974 100644 --- a/flake.lock +++ b/flake.lock @@ -49,11 +49,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1736344531, - "narHash": "sha256-8YVQ9ZbSfuUk2bUf2KRj60NRraLPKPS0Q4QFTbc+c2c=", + "lastModified": 1737062831, + "narHash": "sha256-Tbk1MZbtV2s5aG+iM99U8FqwxU/YNArMcWAv6clcsBc=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "bffc22eb12172e6db3c5dde9e3e5628f8e3e7912", + "rev": "5df43628fdf08d642be8ba5b3625a6c70731c19c", "type": "github" }, "original": { From db766574a42a4b7db6b320b6d469b233ce5f3100 Mon Sep 17 00:00:00 2001 From: Alexandru Ionut Tripon Date: Tue, 21 Jan 2025 01:38:13 +0200 Subject: [PATCH 75/80] Update .github/workflows/build.yml Co-authored-by: Seth Flynn Signed-off-by: Alexandru Ionut Tripon --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 169d63176..680a39a4f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -559,7 +559,7 @@ jobs: cp /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0 ${{ env.INSTALL_PORTABLE_DIR }}/lib cp /usr/lib/x86_64-linux-gnu/libcrypto.so.* ${{ env.INSTALL_PORTABLE_DIR }}/lib cp /usr/lib/x86_64-linux-gnu/libssl.so.* ${{ env.INSTALL_PORTABLE_DIR }}/lib - cp /usr/lib/x86_64-linux-gnu/libffi.so.* ${{ env.INSTALL_PORTABLE_DIR }}/lib + cp /usr/lib/x86_64-linux-gnu/libffi.so.*.* ${{ env.INSTALL_PORTABLE_DIR }}/lib mv ${{ env.INSTALL_PORTABLE_DIR }}/bin/*.so* ${{ env.INSTALL_PORTABLE_DIR }}/lib for l in $(find ${{ env.INSTALL_PORTABLE_DIR }} -type f); do l=${l#$(pwd)/}; l=${l#${{ env.INSTALL_PORTABLE_DIR }}/}; l=${l#./}; echo $l; done > ${{ env.INSTALL_PORTABLE_DIR }}/manifest.txt From e66f447ce5bca996b0a12fac02216b2b6ab8ccb6 Mon Sep 17 00:00:00 2001 From: Seth Flynn Date: Mon, 20 Jan 2025 20:35:37 -0500 Subject: [PATCH 76/80] feat: use better compile flags for mingw Signed-off-by: Seth Flynn --- CMakeLists.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index dcf13c577..d61817ecf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -78,6 +78,13 @@ else() # ATL's pack list needs more than the default 1 Mib stack on windows if(WIN32) set(CMAKE_EXE_LINKER_FLAGS "-Wl,--stack,8388608 ${CMAKE_EXE_LINKER_FLAGS}") + + # -ffunction-sections and -fdata-sections help reduce binary size + # -mguard=cf enables Control Flow Guard + # TODO: Look into -gc-sections to further reduce binary size + foreach(lang C CXX) + set("CMAKE_${lang}_FLAGS_RELEASE" "-ffunction-sections -fdata-sections -mguard=cf") + endforeach() endif() endif() From 2a403b3bfe9f4c79c38c33e80515a232576f6018 Mon Sep 17 00:00:00 2001 From: eff3ry Date: Wed, 22 Jan 2025 01:39:28 +1300 Subject: [PATCH 77/80] Edit Modrinth search faucets Edit Modrinth search faucets to alter the client and server filters to be more in-line with the Modrinth website and Launcher, making it easier to find client-side only mods etc. Signed-off-by: Jeffery Tolmie Jeffery.tolmie@gmail.com --- launcher/modplatform/modrinth/ModrinthAPI.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/launcher/modplatform/modrinth/ModrinthAPI.h b/launcher/modplatform/modrinth/ModrinthAPI.h index 3a5c21ed1..ae74545e2 100644 --- a/launcher/modplatform/modrinth/ModrinthAPI.h +++ b/launcher/modplatform/modrinth/ModrinthAPI.h @@ -71,13 +71,15 @@ class ModrinthAPI : public NetworkResourceAPI { static auto getSideFilters(QString side) -> const QString { - if (side.isEmpty() || side == "both") { + if (side.isEmpty()) { return {}; } + if (side == "both") + return QString("\"client_side:required\"],[\"server_side:required\""); if (side == "client") - return QString("\"client_side:required\",\"client_side:optional\""); + return QString("\"client_side:required\",\"client_side:optional\"],[\"server_side:optional\",\"server_side:unsupported\""); if (side == "server") - return QString("\"server_side:required\",\"server_side:optional\""); + return QString("\"server_side:required\",\"server_side:optional\"],[\"client_side:optional\",\"client_side:unsupported\""); return {}; } From 4ba3fd559d2664099524848825adb6f5a60650ab Mon Sep 17 00:00:00 2001 From: eff3ry Date: Wed, 22 Jan 2025 01:40:59 +1300 Subject: [PATCH 78/80] Update Filter Checks Updates the filter checks so that options both and none can be differentiated. Signed-off-by: Jeffery Tolmie Jeffery.tolmie@gmail.com --- launcher/ui/widgets/ModFilterWidget.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/launcher/ui/widgets/ModFilterWidget.cpp b/launcher/ui/widgets/ModFilterWidget.cpp index 5ae49d3a5..36afbcd87 100644 --- a/launcher/ui/widgets/ModFilterWidget.cpp +++ b/launcher/ui/widgets/ModFilterWidget.cpp @@ -279,14 +279,14 @@ void ModFilterWidget::onSideFilterChanged() { QString side; - if (ui->clientSide->isChecked() != ui->serverSide->isChecked()) { - if (ui->clientSide->isChecked()) - side = "client"; - else - side = "server"; + if (ui->clientSide->isChecked() && !ui->serverSide->isChecked()) { + side = "client"; + } else if (!ui->clientSide->isChecked() && ui->serverSide->isChecked()) { + side = "server"; + } else if (ui->clientSide->isChecked() && ui->serverSide->isChecked()) { + side = "both"; } else { - // both are checked or none are checked; in either case no filtering will happen - side = ""; + side = "none"; } m_filter_changed = side != m_filter->side; From 532fec77480fd6de608f6bb4966cf234427cc777 Mon Sep 17 00:00:00 2001 From: eff3ry Date: Wed, 22 Jan 2025 01:48:04 +1300 Subject: [PATCH 79/80] DCO Remediation Commit DCO Remediation Commit for eff3ry I, eff3ry , hereby add my Signed-off-by to this commit: 2a403b3bfe9f4c79c38c33e80515a232576f6018 I, eff3ry , hereby add my Signed-off-by to this commit: 4ba3fd559d2664099524848825adb6f5a60650ab Signed-off-by: eff3ry --- launcher/ui/widgets/ModFilterWidget.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/launcher/ui/widgets/ModFilterWidget.cpp b/launcher/ui/widgets/ModFilterWidget.cpp index 36afbcd87..d39b7a81a 100644 --- a/launcher/ui/widgets/ModFilterWidget.cpp +++ b/launcher/ui/widgets/ModFilterWidget.cpp @@ -289,6 +289,7 @@ void ModFilterWidget::onSideFilterChanged() side = "none"; } + m_filter_changed = side != m_filter->side; m_filter->side = side; if (m_filter_changed) From caccaefb3954bbe168a032b61f2590e9e796ad8e Mon Sep 17 00:00:00 2001 From: Jeffery Tolmie Date: Wed, 22 Jan 2025 02:06:49 +1300 Subject: [PATCH 80/80] Change "none" to "" Co-authored-by: Alexandru Ionut Tripon Signed-off-by: Jeffery Tolmie --- launcher/ui/widgets/ModFilterWidget.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/ui/widgets/ModFilterWidget.cpp b/launcher/ui/widgets/ModFilterWidget.cpp index d39b7a81a..37211693f 100644 --- a/launcher/ui/widgets/ModFilterWidget.cpp +++ b/launcher/ui/widgets/ModFilterWidget.cpp @@ -286,7 +286,7 @@ void ModFilterWidget::onSideFilterChanged() } else if (ui->clientSide->isChecked() && ui->serverSide->isChecked()) { side = "both"; } else { - side = "none"; + side = ""; }