From 87db723008727b32681f5a2a39b20497bc5fb34e Mon Sep 17 00:00:00 2001 From: Tayou Date: Tue, 18 Apr 2023 20:25:45 +0200 Subject: [PATCH 001/216] add global .editorconfig for doxygen comment style Signed-off-by: Tayou --- .editorconfig | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 000000000..a6521c873 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,8 @@ +# Visual Studio generated .editorconfig file with C++ settings. +root = true + +[*.{c++,cc,cpp,cppm,cxx,h,h++,hh,hpp,hxx,inl,ipp,ixx,tlh,tli}] + +# Visual C++ Code Style settings + +cpp_generate_documentation_comments = doxygen_triple_slash From c0f9ccc5b5fc943c033fd52af5eca1ddadcc1be0 Mon Sep 17 00:00:00 2001 From: Tayou <31988415+TayouVR@users.noreply.github.com> Date: Sun, 28 May 2023 19:57:08 +0200 Subject: [PATCH 002/216] Use slash_star comment style in .editorconfig Signed-off-by: Tayou <31988415+TayouVR@users.noreply.github.com> --- .editorconfig | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.editorconfig b/.editorconfig index a6521c873..56166b207 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,8 +1,8 @@ -# Visual Studio generated .editorconfig file with C++ settings. +# EditorConfig specs and documentation: https://EditorConfig.org + +# top-most EditorConfig file root = true +# C++ Code Style settings [*.{c++,cc,cpp,cppm,cxx,h,h++,hh,hpp,hxx,inl,ipp,ixx,tlh,tli}] - -# Visual C++ Code Style settings - -cpp_generate_documentation_comments = doxygen_triple_slash +cpp_generate_documentation_comments = doxygen_slash_star From f724059b883d584b9f1d9ecd5fe21c7e4d214889 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Wed, 7 Jun 2023 01:23:53 +0300 Subject: [PATCH 003/216] Added visit mod's page Signed-off-by: Trial97 --- .../pages/instance/ExternalResourcesPage.ui | 11 +++++ launcher/ui/pages/instance/ModFolderPage.cpp | 48 ++++++++++++++----- launcher/ui/pages/instance/ModFolderPage.h | 1 + 3 files changed, 49 insertions(+), 11 deletions(-) diff --git a/launcher/ui/pages/instance/ExternalResourcesPage.ui b/launcher/ui/pages/instance/ExternalResourcesPage.ui index 33a033366..b110dbfd6 100644 --- a/launcher/ui/pages/instance/ExternalResourcesPage.ui +++ b/launcher/ui/pages/instance/ExternalResourcesPage.ui @@ -154,6 +154,17 @@ Try to check or update all selected resources (all resources if none are selected) + + + false + + + Visit on mod's page + + + Go to mods home page + + diff --git a/launcher/ui/pages/instance/ModFolderPage.cpp b/launcher/ui/pages/instance/ModFolderPage.cpp index 4548af59a..d1787e7db 100644 --- a/launcher/ui/pages/instance/ModFolderPage.cpp +++ b/launcher/ui/pages/instance/ModFolderPage.cpp @@ -44,6 +44,7 @@ #include #include #include +#include #include "Application.h" @@ -59,6 +60,7 @@ #include "minecraft/mod/Mod.h" #include "minecraft/mod/ModFolderModel.h" +#include "modplatform/ModIndex.h" #include "modplatform/ResourceAPI.h" #include "Version.h" @@ -85,22 +87,29 @@ ModFolderPage::ModFolderPage(BaseInstance* inst, std::shared_ptr ui->actionsToolbar->insertActionAfter(ui->actionAddItem, ui->actionUpdateItem); connect(ui->actionUpdateItem, &QAction::triggered, this, &ModFolderPage::updateMods); + ui->actionVisitItemPage->setToolTip(tr("Go to mods home page")); + ui->actionsToolbar->insertActionAfter(ui->actionViewFolder, ui->actionVisitItemPage); + connect(ui->actionVisitItemPage, &QAction::triggered, this, &ModFolderPage::visitModPages); + auto check_allow_update = [this] { - return (!m_instance || !m_instance->isRunning()) && - (ui->treeView->selectionModel()->hasSelection() || !m_model->empty()); + return (!m_instance || !m_instance->isRunning()) && (ui->treeView->selectionModel()->hasSelection() || !m_model->empty()); }; connect(ui->treeView->selectionModel(), &QItemSelectionModel::selectionChanged, this, [this, check_allow_update] { ui->actionUpdateItem->setEnabled(check_allow_update()); + + auto selection = m_filterModel->mapSelectionToSource(ui->treeView->selectionModel()->selection()).indexes(); + auto mods_list = m_model->selectedMods(selection); + auto enableView = std::any_of(mods_list.cbegin(), mods_list.cend(), + [](Mod* v) { return v->metadata() != nullptr || v->homeurl().size() != 0; }); + ui->actionVisitItemPage->setEnabled(enableView); }); - connect(mods.get(), &ModFolderModel::rowsInserted, this, [this, check_allow_update] { - ui->actionUpdateItem->setEnabled(check_allow_update()); - }); + connect(mods.get(), &ModFolderModel::rowsInserted, this, + [this, check_allow_update] { ui->actionUpdateItem->setEnabled(check_allow_update()); }); - connect(mods.get(), &ModFolderModel::rowsRemoved, this, [this, check_allow_update] { - ui->actionUpdateItem->setEnabled(check_allow_update()); - }); + connect(mods.get(), &ModFolderModel::rowsRemoved, this, + [this, check_allow_update] { ui->actionUpdateItem->setEnabled(check_allow_update()); }); connect(mods.get(), &ModFolderModel::updateFinished, this, [this, check_allow_update, mods] { ui->actionUpdateItem->setEnabled(check_allow_update()); @@ -140,7 +149,7 @@ bool ModFolderPage::onSelectionChanged(const QModelIndex& current, const QModelI return true; } -void ModFolderPage::removeItems(const QItemSelection &selection) +void ModFolderPage::removeItems(const QItemSelection& selection) { m_model->deleteMods(selection.indexes()); } @@ -214,8 +223,7 @@ void ModFolderPage::updateMods() message = tr("All selected mods are up-to-date! :)"); } } - CustomMessageBox::selectable(this, tr("Update checker"), message) - ->exec(); + CustomMessageBox::selectable(this, tr("Update checker"), message)->exec(); return; } @@ -282,3 +290,21 @@ bool NilModFolderPage::shouldDisplay() const { return m_model->dir().exists(); } + +void ModFolderPage::visitModPages() +{ + auto selection = m_filterModel->mapSelectionToSource(ui->treeView->selectionModel()->selection()).indexes(); + for (auto mod : m_model->selectedMods(selection)) + if (auto meta = mod->metadata(); meta != nullptr) { + auto slug = meta->slug.remove(".pw.toml"); + switch (meta->provider) { + case ModPlatform::ResourceProvider::MODRINTH: + DesktopServices::openUrl(QString("https://modrinth.com/mod/%1").arg(slug)); + break; + case ModPlatform::ResourceProvider::FLAME: + DesktopServices::openUrl(QString("https://www.curseforge.com/minecraft/mc-mods/%1").arg(slug)); + break; + } + } else if (mod->homeurl().size() != 0) + DesktopServices::openUrl(mod->homeurl()); +} \ No newline at end of file diff --git a/launcher/ui/pages/instance/ModFolderPage.h b/launcher/ui/pages/instance/ModFolderPage.h index 2fc7b5748..d36a79951 100644 --- a/launcher/ui/pages/instance/ModFolderPage.h +++ b/launcher/ui/pages/instance/ModFolderPage.h @@ -64,6 +64,7 @@ class ModFolderPage : public ExternalResourcesPage { void installMods(); void updateMods(); + void visitModPages(); protected: std::shared_ptr m_model; From e936bc4c60b4262cd70ff1eb3291dc3ead4c53ac Mon Sep 17 00:00:00 2001 From: Trial97 Date: Wed, 7 Jun 2023 01:38:10 +0300 Subject: [PATCH 004/216] Added custom text for multiple selection Signed-off-by: Trial97 --- launcher/ui/pages/instance/ModFolderPage.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/launcher/ui/pages/instance/ModFolderPage.cpp b/launcher/ui/pages/instance/ModFolderPage.cpp index d1787e7db..1dbb9f473 100644 --- a/launcher/ui/pages/instance/ModFolderPage.cpp +++ b/launcher/ui/pages/instance/ModFolderPage.cpp @@ -87,7 +87,7 @@ ModFolderPage::ModFolderPage(BaseInstance* inst, std::shared_ptr ui->actionsToolbar->insertActionAfter(ui->actionAddItem, ui->actionUpdateItem); connect(ui->actionUpdateItem, &QAction::triggered, this, &ModFolderPage::updateMods); - ui->actionVisitItemPage->setToolTip(tr("Go to mods home page")); + ui->actionVisitItemPage->setToolTip(tr("Go to mod's home page")); ui->actionsToolbar->insertActionAfter(ui->actionViewFolder, ui->actionVisitItemPage); connect(ui->actionVisitItemPage, &QAction::triggered, this, &ModFolderPage::visitModPages); @@ -100,9 +100,16 @@ ModFolderPage::ModFolderPage(BaseInstance* inst, std::shared_ptr auto selection = m_filterModel->mapSelectionToSource(ui->treeView->selectionModel()->selection()).indexes(); auto mods_list = m_model->selectedMods(selection); - auto enableView = std::any_of(mods_list.cbegin(), mods_list.cend(), + auto selected = std::count_if(mods_list.cbegin(), mods_list.cend(), [](Mod* v) { return v->metadata() != nullptr || v->homeurl().size() != 0; }); - ui->actionVisitItemPage->setEnabled(enableView); + if (selected <= 1) { + ui->actionVisitItemPage->setText(tr("Visit on mod's page")); + ui->actionVisitItemPage->setToolTip(tr("Go to mod's home page")); + } else { + ui->actionVisitItemPage->setText(tr("Visit the pages of the selected mods")); + ui->actionVisitItemPage->setToolTip(tr("Go to the pages of the selected mods")); + } + ui->actionVisitItemPage->setEnabled(selected != 0); }); connect(mods.get(), &ModFolderModel::rowsInserted, this, From a90eaafa70e74ceaee22298b3c1ead8c1778e5ec Mon Sep 17 00:00:00 2001 From: PandaNinjas Date: Wed, 7 Jun 2023 15:18:59 -0400 Subject: [PATCH 005/216] Make it clear that the statements are meant to fall through in Murmur hash Signed-off-by: PandaNinjas --- libraries/murmur2/src/MurmurHash2.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libraries/murmur2/src/MurmurHash2.cpp b/libraries/murmur2/src/MurmurHash2.cpp index c13608f07..e73127953 100644 --- a/libraries/murmur2/src/MurmurHash2.cpp +++ b/libraries/murmur2/src/MurmurHash2.cpp @@ -89,8 +89,10 @@ void FourBytes_MurmurHash2(const unsigned char* data, IncrementalHashInfo& prev) switch (prev.len) { case 3: prev.h ^= data[2] << 16; + /* fall through */ case 2: prev.h ^= data[1] << 8; + /* fall through */ case 1: prev.h ^= data[0]; prev.h *= m; From d33de2e4277dfcd090a36c96e09148ea6a5d2e55 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 8 Jun 2023 00:54:32 +0300 Subject: [PATCH 006/216] Made cat scalable Signed-off-by: Trial97 --- launcher/ui/MainWindow.cpp | 17 ++--------------- launcher/ui/instanceview/InstanceView.cpp | 23 ++++++++++++++++++++++- launcher/ui/instanceview/InstanceView.h | 8 ++++---- 3 files changed, 28 insertions(+), 20 deletions(-) diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp index 834f57dd9..4b77dd1c7 100644 --- a/launcher/ui/MainWindow.cpp +++ b/launcher/ui/MainWindow.cpp @@ -901,21 +901,8 @@ void MainWindow::onCatToggled(bool state) void MainWindow::setCatBackground(bool enabled) { - if (enabled) { - view->setStyleSheet(QString(R"( -InstanceView -{ - background-image: url(:/backgrounds/%1); - background-attachment: fixed; - background-clip: padding; - background-position: bottom right; - background-repeat: none; - background-color:palette(base); -})") - .arg(ThemeManager::getCatImage())); - } else { - view->setStyleSheet(QString()); - } + view->setCatVisible(enabled); + view->viewport()->repaint(); } void MainWindow::runModalTask(Task *task) diff --git a/launcher/ui/instanceview/InstanceView.cpp b/launcher/ui/instanceview/InstanceView.cpp index fbeffe350..4c83e94a0 100644 --- a/launcher/ui/instanceview/InstanceView.cpp +++ b/launcher/ui/instanceview/InstanceView.cpp @@ -48,6 +48,7 @@ #include #include "VisualGroup.h" +#include "ui/themes/ThemeManager.h" #include #include @@ -73,6 +74,7 @@ InstanceView::InstanceView(QWidget *parent) setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); setAcceptDrops(true); setAutoScroll(true); + setCatVisible(APPLICATION->settings()->get("TheCat").toBool()); } InstanceView::~InstanceView() @@ -498,12 +500,31 @@ void InstanceView::mouseDoubleClickEvent(QMouseEvent *event) } } -void InstanceView::paintEvent(QPaintEvent *event) +void InstanceView::setCatVisible(bool visible) +{ + m_catVisible = visible; + m_catPixmap.load(QString(":/backgrounds/%1").arg(ThemeManager::getCatImage())); +} + +void InstanceView::paintEvent(QPaintEvent* event) { executeDelayedItemsLayout(); QPainter painter(this->viewport()); + if (m_catVisible) { + int widWidth = this->viewport()->width(); + int widHeight = this->viewport()->height(); + if (m_catPixmap.width() < widWidth) + widWidth = m_catPixmap.width(); + if (m_catPixmap.height() < widHeight) + widHeight = m_catPixmap.height(); + auto pixmap = m_catPixmap.scaled(widWidth, widHeight, Qt::KeepAspectRatio); + QRect rectOfPixmap = pixmap.rect(); + rectOfPixmap.moveBottomRight(this->viewport()->rect().bottomRight()); + painter.drawPixmap(rectOfPixmap.topLeft(), pixmap); + } + #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) QStyleOptionViewItem option; initViewItemOption(&option); diff --git a/launcher/ui/instanceview/InstanceView.h b/launcher/ui/instanceview/InstanceView.h index ac3382742..a9bd0bd7e 100644 --- a/launcher/ui/instanceview/InstanceView.h +++ b/launcher/ui/instanceview/InstanceView.h @@ -85,10 +85,8 @@ public: virtual QRegion visualRegionForSelection(const QItemSelection &selection) const override; - int spacing() const - { - return m_spacing; - }; + int spacing() const { return m_spacing; }; + void setCatVisible(bool visible); public slots: virtual void updateGeometries() override; @@ -139,6 +137,8 @@ private: int m_currentItemsPerRow = -1; int m_currentCursorColumn= -1; mutable QCache geometryCache; + bool m_catVisible = false; + QPixmap m_catPixmap; // point where the currently active mouse action started in geometry coordinates QPoint m_pressedPosition; From c225ecbb557b656184f35fdd3daa3a8aaa048f1f Mon Sep 17 00:00:00 2001 From: PandaNinjas Date: Wed, 7 Jun 2023 18:00:14 -0400 Subject: [PATCH 007/216] Add sensible defaults in AccountList.cpp Signed-off-by: PandaNinjas --- launcher/minecraft/auth/AccountList.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/launcher/minecraft/auth/AccountList.cpp b/launcher/minecraft/auth/AccountList.cpp index 9e2fd1113..9069db6e0 100644 --- a/launcher/minecraft/auth/AccountList.cpp +++ b/launcher/minecraft/auth/AccountList.cpp @@ -328,6 +328,9 @@ QVariant AccountList::data(const QModelIndex &index, int role) const case AccountState::Gone: { return tr("Gone", "Account status"); } + case default: { + return tr("Unknown", "Account status"); + } } } From 5d425ecc025aa1fc4a5292961a5ff1b18a108885 Mon Sep 17 00:00:00 2001 From: PandaNinjas Date: Wed, 7 Jun 2023 18:12:46 -0400 Subject: [PATCH 008/216] Fix the AccountList code Signed-off-by: PandaNinjas --- launcher/minecraft/auth/AccountList.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/minecraft/auth/AccountList.cpp b/launcher/minecraft/auth/AccountList.cpp index 9069db6e0..e454bcc49 100644 --- a/launcher/minecraft/auth/AccountList.cpp +++ b/launcher/minecraft/auth/AccountList.cpp @@ -328,7 +328,7 @@ QVariant AccountList::data(const QModelIndex &index, int role) const case AccountState::Gone: { return tr("Gone", "Account status"); } - case default: { + default: { return tr("Unknown", "Account status"); } } From 318d11481d719cf537ecdc00f8d676494bab22b6 Mon Sep 17 00:00:00 2001 From: PandaNinjas Date: Wed, 7 Jun 2023 19:37:54 -0400 Subject: [PATCH 009/216] Resolve other switch fallthrough issues --- launcher/LaunchController.cpp | 4 +- launcher/VersionProxyModel.cpp | 100 ++++++------------ launcher/meta/Index.cpp | 2 +- launcher/minecraft/auth/AccountList.cpp | 9 +- launcher/minecraft/auth/Yggdrasil.cpp | 1 + launcher/minecraft/mod/DataPack.cpp | 2 + launcher/minecraft/mod/Mod.cpp | 3 + launcher/minecraft/mod/Resource.cpp | 3 + launcher/minecraft/mod/ResourcePack.cpp | 2 + .../flame/FlameInstanceCreationTask.cpp | 3 +- launcher/translations/TranslationsModel.cpp | 1 + .../instanceview/AccessibleInstanceView.cpp | 2 +- launcher/ui/pages/instance/WorldListPage.cpp | 1 + launcher/ui/setupwizard/JavaWizardPage.cpp | 1 + 14 files changed, 60 insertions(+), 74 deletions(-) diff --git a/launcher/LaunchController.cpp b/launcher/LaunchController.cpp index 070ee283c..5d84b3bf6 100644 --- a/launcher/LaunchController.cpp +++ b/launcher/LaunchController.cpp @@ -187,8 +187,8 @@ void LaunchController::login() { switch(m_accountToUse->accountState()) { case AccountState::Offline: { m_session->wants_online = false; - // NOTE: fallthrough is intentional } + /* fallthrough */ case AccountState::Online: { if(!m_session->wants_online) { // we ask the user for a player name @@ -267,8 +267,8 @@ void LaunchController::login() { // This means some sort of soft error that we can fix with a refresh ... so let's refresh. case AccountState::Unchecked: { m_accountToUse->refresh(); - // NOTE: fallthrough intentional } + /* fallthrough */ case AccountState::Working: { // refresh is in progress, we need to wait for it to finish to proceed. ProgressDialog progDialog(m_parentWidget); diff --git a/launcher/VersionProxyModel.cpp b/launcher/VersionProxyModel.cpp index 6aba268d8..3c2948734 100644 --- a/launcher/VersionProxyModel.cpp +++ b/launcher/VersionProxyModel.cpp @@ -185,80 +185,50 @@ QVariant VersionProxyModel::data(const QModelIndex &index, int role) const return QVariant(); } } - case Qt::ToolTipRole: - { - switch(column) - { - case Name: - { - if(hasRecommended) + case Qt::ToolTipRole: { + if (column == Name && hasRecommended) { + auto value = sourceModel()->data(parentIndex, BaseVersionList::RecommendedRole); + if(value.toBool()) { + return tr("Recommended"); + } + else if(hasLatest) { + auto value = sourceModel()->data(parentIndex, BaseVersionList::LatestRole); + if(value.toBool()) { - auto value = sourceModel()->data(parentIndex, BaseVersionList::RecommendedRole); - if(value.toBool()) - { - return tr("Recommended"); - } - else if(hasLatest) - { - auto value = sourceModel()->data(parentIndex, BaseVersionList::LatestRole); - if(value.toBool()) - { - return tr("Latest"); - } - } - else if(index.row() == 0) - { - return tr("Latest"); - } + return tr("Latest"); } } - default: - { - return sourceModel()->data(parentIndex, BaseVersionList::VersionIdRole); + else if(index.row() == 0) { + return tr("Latest"); } } + return sourceModel()->data(parentIndex, BaseVersionList::VersionIdRole); } - case Qt::DecorationRole: - { - switch(column) - { - case Name: - { - if(hasRecommended) - { - auto value = sourceModel()->data(parentIndex, BaseVersionList::RecommendedRole); - if(value.toBool()) - { - return APPLICATION->getThemedIcon("star"); - } - else if(hasLatest) - { - auto value = sourceModel()->data(parentIndex, BaseVersionList::LatestRole); - if(value.toBool()) - { - return APPLICATION->getThemedIcon("bug"); - } - } - else if(index.row() == 0) - { - return APPLICATION->getThemedIcon("bug"); - } - QPixmap pixmap; - QPixmapCache::find("placeholder", &pixmap); - if(!pixmap) - { - QPixmap px(16,16); - px.fill(Qt::transparent); - QPixmapCache::insert("placeholder", px); - return px; - } - return pixmap; + case Qt::DecorationRole: { + if (column == Name && hasRecommended) { + auto value = sourceModel()->data(parentIndex, BaseVersionList::RecommendedRole); + if(value.toBool()) { + return APPLICATION->getThemedIcon("star"); + } else if(hasLatest) { + auto value = sourceModel()->data(parentIndex, BaseVersionList::LatestRole); + if(value.toBool()) { + return APPLICATION->getThemedIcon("bug"); } } - default: - { - return QVariant(); + else if(index.row() == 0) { + return APPLICATION->getThemedIcon("bug"); } + QPixmap pixmap; + QPixmapCache::find("placeholder", &pixmap); + if(!pixmap) { + QPixmap px(16,16); + px.fill(Qt::transparent); + QPixmapCache::insert("placeholder", px); + return px; + } + return pixmap; + } else { + return QVariant(); } } default: diff --git a/launcher/meta/Index.cpp b/launcher/meta/Index.cpp index 242aad9f9..2902f290b 100644 --- a/launcher/meta/Index.cpp +++ b/launcher/meta/Index.cpp @@ -48,8 +48,8 @@ QVariant Index::data(const QModelIndex &index, int role) const switch (index.column()) { case 0: return list->humanReadable(); - default: break; } + break; case UidRole: return list->uid(); case NameRole: return list->name(); case ListPtrRole: return QVariant::fromValue(list); diff --git a/launcher/minecraft/auth/AccountList.cpp b/launcher/minecraft/auth/AccountList.cpp index e454bcc49..184f8e100 100644 --- a/launcher/minecraft/auth/AccountList.cpp +++ b/launcher/minecraft/auth/AccountList.cpp @@ -357,11 +357,12 @@ QVariant AccountList::data(const QModelIndex &index, int role) const return QVariant::fromValue(account); case Qt::CheckStateRole: - switch (index.column()) - { - case ProfileNameColumn: - return account == m_defaultAccount ? Qt::Checked : Qt::Unchecked; + if (index.column() == ProfileNameColumn) { + return account == m_defaultAccount ? Qt::Checked : Qt::Unchecked; + } else { + return QVariant(); } + default: return QVariant(); diff --git a/launcher/minecraft/auth/Yggdrasil.cpp b/launcher/minecraft/auth/Yggdrasil.cpp index 299784119..d3e7ccddb 100644 --- a/launcher/minecraft/auth/Yggdrasil.cpp +++ b/launcher/minecraft/auth/Yggdrasil.cpp @@ -273,6 +273,7 @@ void Yggdrasil::processReply() { AccountTaskState::STATE_FAILED_GONE, tr("The Mojang account no longer exists. It may have been migrated to a Microsoft account.") ); + return; } default: changeState( diff --git a/launcher/minecraft/mod/DataPack.cpp b/launcher/minecraft/mod/DataPack.cpp index ca75cd2aa..c5754638a 100644 --- a/launcher/minecraft/mod/DataPack.cpp +++ b/launcher/minecraft/mod/DataPack.cpp @@ -74,6 +74,7 @@ std::pair DataPack::compare(const Resource& other, SortType type) con auto res = Resource::compare(other, type); if (res.first != 0) return res; + break; } case SortType::PACK_FORMAT: { auto this_ver = packFormat(); @@ -83,6 +84,7 @@ std::pair DataPack::compare(const Resource& other, SortType type) con return { 1, type == SortType::PACK_FORMAT }; if (this_ver < other_ver) return { -1, type == SortType::PACK_FORMAT }; + break; } } return { 0, false }; diff --git a/launcher/minecraft/mod/Mod.cpp b/launcher/minecraft/mod/Mod.cpp index c495cd47e..6cda6185c 100644 --- a/launcher/minecraft/mod/Mod.cpp +++ b/launcher/minecraft/mod/Mod.cpp @@ -89,6 +89,7 @@ std::pair Mod::compare(const Resource& other, SortType type) const auto res = Resource::compare(other, type); if (res.first != 0) return res; + break; } case SortType::VERSION: { auto this_ver = Version(version()); @@ -97,11 +98,13 @@ std::pair Mod::compare(const Resource& other, SortType type) const return { 1, type == SortType::VERSION }; if (this_ver < other_ver) return { -1, type == SortType::VERSION }; + break; } case SortType::PROVIDER: { auto compare_result = QString::compare(provider().value_or("Unknown"), cast_other->provider().value_or("Unknown"), Qt::CaseInsensitive); if (compare_result != 0) return { compare_result, type == SortType::PROVIDER }; + break; } } return { 0, false }; diff --git a/launcher/minecraft/mod/Resource.cpp b/launcher/minecraft/mod/Resource.cpp index a0b8a4bbc..e50772601 100644 --- a/launcher/minecraft/mod/Resource.cpp +++ b/launcher/minecraft/mod/Resource.cpp @@ -71,6 +71,7 @@ std::pair Resource::compare(const Resource& other, SortType type) con return { 1, type == SortType::ENABLED }; if (!enabled() && other.enabled()) return { -1, type == SortType::ENABLED }; + break; case SortType::NAME: { QString this_name{ name() }; QString other_name{ other.name() }; @@ -81,12 +82,14 @@ std::pair Resource::compare(const Resource& other, SortType type) con auto compare_result = QString::compare(this_name, other_name, Qt::CaseInsensitive); if (compare_result != 0) return { compare_result, type == SortType::NAME }; + break; } case SortType::DATE: if (dateTimeChanged() > other.dateTimeChanged()) return { 1, type == SortType::DATE }; if (dateTimeChanged() < other.dateTimeChanged()) return { -1, type == SortType::DATE }; + break; } return { 0, false }; diff --git a/launcher/minecraft/mod/ResourcePack.cpp b/launcher/minecraft/mod/ResourcePack.cpp index 759d2b566..32a789f55 100644 --- a/launcher/minecraft/mod/ResourcePack.cpp +++ b/launcher/minecraft/mod/ResourcePack.cpp @@ -95,6 +95,7 @@ std::pair ResourcePack::compare(const Resource& other, SortType type) auto res = Resource::compare(other, type); if (res.first != 0) return res; + break; } case SortType::PACK_FORMAT: { auto this_ver = packFormat(); @@ -104,6 +105,7 @@ std::pair ResourcePack::compare(const Resource& other, SortType type) return { 1, type == SortType::PACK_FORMAT }; if (this_ver < other_ver) return { -1, type == SortType::PACK_FORMAT }; + break; } } return { 0, false }; diff --git a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp index dae93d1c6..11365a214 100644 --- a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp +++ b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp @@ -467,8 +467,9 @@ void FlameCreationTask::setupDownloadJob(QEventLoop& loop) switch (result.type) { case Flame::File::Type::Folder: { logWarning(tr("This 'Folder' may need extracting: %1").arg(relpath)); - // fall-through intentional, we treat these as plain old mods and dump them wherever. + // fallthrough intentional, we treat these as plain old mods and dump them wherever. } + /* fallthrough */ case Flame::File::Type::SingleFile: case Flame::File::Type::Mod: { if (!result.url.isEmpty()) { diff --git a/launcher/translations/TranslationsModel.cpp b/launcher/translations/TranslationsModel.cpp index 23e55c51d..489dff86d 100644 --- a/launcher/translations/TranslationsModel.cpp +++ b/launcher/translations/TranslationsModel.cpp @@ -454,6 +454,7 @@ QVariant TranslationsModel::data(const QModelIndex& index, int role) const return QString("%1%").arg(lang.percentTranslated(), 3, 'f', 1); } } + qWarning("TranslationModel::data not implemented when role is DisplayRole"); } case Qt::ToolTipRole: { diff --git a/launcher/ui/instanceview/AccessibleInstanceView.cpp b/launcher/ui/instanceview/AccessibleInstanceView.cpp index 7de3ac726..2e7b83000 100644 --- a/launcher/ui/instanceview/AccessibleInstanceView.cpp +++ b/launcher/ui/instanceview/AccessibleInstanceView.cpp @@ -248,8 +248,8 @@ bool AccessibleInstanceView::selectColumn(int column) if (view()->selectionBehavior() != QAbstractItemView::SelectColumns && rowCount() > 1) { return false; } - // fallthrough intentional } + /* fallthrough */ case QAbstractItemView::ContiguousSelection: { if ((!column || !view()->selectionModel()->isColumnSelected(column - 1, view()->rootIndex())) && !view()->selectionModel()->isColumnSelected(column + 1, view()->rootIndex())) { view()->clearSelection(); diff --git a/launcher/ui/pages/instance/WorldListPage.cpp b/launcher/ui/pages/instance/WorldListPage.cpp index b6ad159e1..b5dc5a17c 100644 --- a/launcher/ui/pages/instance/WorldListPage.cpp +++ b/launcher/ui/pages/instance/WorldListPage.cpp @@ -338,6 +338,7 @@ void WorldListPage::mceditState(LoggedProcess::State state) case LoggedProcess::Aborted: { failed = true; + break; } case LoggedProcess::Running: case LoggedProcess::Finished: diff --git a/launcher/ui/setupwizard/JavaWizardPage.cpp b/launcher/ui/setupwizard/JavaWizardPage.cpp index 14683778a..e88335355 100644 --- a/launcher/ui/setupwizard/JavaWizardPage.cpp +++ b/launcher/ui/setupwizard/JavaWizardPage.cpp @@ -69,6 +69,7 @@ bool JavaWizardPage::validatePage() case JavaSettingsWidget::ValidationStatus::AllOK: { settings->set("JavaPath", m_java_widget->javaPath()); + break; } case JavaSettingsWidget::ValidationStatus::JavaBad: { From 534328f16d0322c937a690f2f15eaa81489a54fe Mon Sep 17 00:00:00 2001 From: PandaNinjas Date: Wed, 7 Jun 2023 19:45:23 -0400 Subject: [PATCH 010/216] Remove unnecessary switch statement Signed-off-by: PandaNinjas DCO Remediation Commit for PandaNinjas I, PandaNinjas , hereby add my Signed-off-by to this commit: 318d11481d719cf537ecdc00f8d676494bab22b6 Signed-off-by: PandaNinjas --- launcher/meta/Index.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/launcher/meta/Index.cpp b/launcher/meta/Index.cpp index 2902f290b..0c6ecccff 100644 --- a/launcher/meta/Index.cpp +++ b/launcher/meta/Index.cpp @@ -45,11 +45,11 @@ QVariant Index::data(const QModelIndex &index, int role) const switch (role) { case Qt::DisplayRole: - switch (index.column()) - { - case 0: return list->humanReadable(); + if (list.column() == 0) { + return list->humanReadable(); + } else { + break; } - break; case UidRole: return list->uid(); case NameRole: return list->name(); case ListPtrRole: return QVariant::fromValue(list); From 886b372adef86d84ca50d2e3e5b7ac39f1a5a42e Mon Sep 17 00:00:00 2001 From: PandaNinjas Date: Wed, 7 Jun 2023 20:03:36 -0400 Subject: [PATCH 011/216] Fix accidentally renamed variable Signed-off-by: PandaNinjas --- launcher/meta/Index.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/meta/Index.cpp b/launcher/meta/Index.cpp index 0c6ecccff..4dccccca8 100644 --- a/launcher/meta/Index.cpp +++ b/launcher/meta/Index.cpp @@ -45,7 +45,7 @@ QVariant Index::data(const QModelIndex &index, int role) const switch (role) { case Qt::DisplayRole: - if (list.column() == 0) { + if (index.column() == 0) { return list->humanReadable(); } else { break; From 11cbeb8f96b9e6bc86290581128e28554123a427 Mon Sep 17 00:00:00 2001 From: PandaNinjas Date: Wed, 7 Jun 2023 22:13:57 -0400 Subject: [PATCH 012/216] Fix shadowing and add copyright header Signed-off-by: PandaNinjas --- launcher/VersionProxyModel.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/launcher/VersionProxyModel.cpp b/launcher/VersionProxyModel.cpp index 3c2948734..15ae1cc3c 100644 --- a/launcher/VersionProxyModel.cpp +++ b/launcher/VersionProxyModel.cpp @@ -1,8 +1,8 @@ // SPDX-License-Identifier: GPL-3.0-only /* * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu - * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, version 3. @@ -187,13 +187,13 @@ QVariant VersionProxyModel::data(const QModelIndex &index, int role) const } case Qt::ToolTipRole: { if (column == Name && hasRecommended) { - auto value = sourceModel()->data(parentIndex, BaseVersionList::RecommendedRole); - if(value.toBool()) { + auto recommendedValue = sourceModel()->data(parentIndex, BaseVersionList::RecommendedRole); + if(recommendedValue.toBool()) { return tr("Recommended"); } else if(hasLatest) { - auto value = sourceModel()->data(parentIndex, BaseVersionList::LatestRole); - if(value.toBool()) + auto latestValue = sourceModel()->data(parentIndex, BaseVersionList::LatestRole); + if(latestValue.toBool()) { return tr("Latest"); } @@ -206,12 +206,12 @@ QVariant VersionProxyModel::data(const QModelIndex &index, int role) const } case Qt::DecorationRole: { if (column == Name && hasRecommended) { - auto value = sourceModel()->data(parentIndex, BaseVersionList::RecommendedRole); - if(value.toBool()) { + auto recommendedValue = sourceModel()->data(parentIndex, BaseVersionList::RecommendedRole); + if(recommendedValue.toBool()) { return APPLICATION->getThemedIcon("star"); } else if(hasLatest) { - auto value = sourceModel()->data(parentIndex, BaseVersionList::LatestRole); - if(value.toBool()) { + auto latestValue = sourceModel()->data(parentIndex, BaseVersionList::LatestRole); + if(latestValue.toBool()) { return APPLICATION->getThemedIcon("bug"); } } From e6872aba75231d409b19da5b876bb518b24976cc Mon Sep 17 00:00:00 2001 From: PandaNinjas Date: Wed, 7 Jun 2023 22:15:44 -0400 Subject: [PATCH 013/216] Readd deleted line Signed-off-by: PandaNinjas --- launcher/VersionProxyModel.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/launcher/VersionProxyModel.cpp b/launcher/VersionProxyModel.cpp index 15ae1cc3c..aca7ef002 100644 --- a/launcher/VersionProxyModel.cpp +++ b/launcher/VersionProxyModel.cpp @@ -3,6 +3,7 @@ * PolyMC - Minecraft Launcher * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, version 3. From 95f6860005341ebf81a7bed60a4e267f3057d2a6 Mon Sep 17 00:00:00 2001 From: PandaNinjas Date: Thu, 8 Jun 2023 10:12:27 -0400 Subject: [PATCH 014/216] Apply suggestions from code review Signed-off-by: PandaNinjas --- launcher/VersionProxyModel.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/launcher/VersionProxyModel.cpp b/launcher/VersionProxyModel.cpp index aca7ef002..0dbd1c951 100644 --- a/launcher/VersionProxyModel.cpp +++ b/launcher/VersionProxyModel.cpp @@ -1,6 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * From be0df38453977c37ae8b6b241e82ace41149fdcc Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 15 Jun 2023 11:40:39 +0300 Subject: [PATCH 015/216] Added tooltip for name label Signed-off-by: Trial97 --- launcher/ui/pages/instance/ModFolderPage.cpp | 1 + launcher/ui/pages/instance/ModFolderPage.h | 3 +- launcher/ui/widgets/InfoFrame.cpp | 111 +++++++++++-------- launcher/ui/widgets/InfoFrame.h | 45 +++++--- 4 files changed, 97 insertions(+), 63 deletions(-) diff --git a/launcher/ui/pages/instance/ModFolderPage.cpp b/launcher/ui/pages/instance/ModFolderPage.cpp index 1dbb9f473..650bf5bdb 100644 --- a/launcher/ui/pages/instance/ModFolderPage.cpp +++ b/launcher/ui/pages/instance/ModFolderPage.cpp @@ -4,6 +4,7 @@ * Copyright (c) 2022 Jamie Mansfield * Copyright (C) 2022 Sefa Eyeoglu * Copyright (C) 2022 TheKodeToad + * Copyright (c) 2023 Trial97 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/launcher/ui/pages/instance/ModFolderPage.h b/launcher/ui/pages/instance/ModFolderPage.h index d36a79951..2c1a9c772 100644 --- a/launcher/ui/pages/instance/ModFolderPage.h +++ b/launcher/ui/pages/instance/ModFolderPage.h @@ -4,6 +4,7 @@ * Copyright (c) 2022 Jamie Mansfield * Copyright (C) 2022 Sefa Eyeoglu * Copyright (C) 2022 TheKodeToad + * Copyright (c) 2023 Trial97 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -60,7 +61,7 @@ class ModFolderPage : public ExternalResourcesPage { private slots: void runningStateChanged(bool running); - void removeItems(const QItemSelection &selection) override; + void removeItems(const QItemSelection& selection) override; void installMods(); void updateMods(); diff --git a/launcher/ui/widgets/InfoFrame.cpp b/launcher/ui/widgets/InfoFrame.cpp index fdc581b41..d0b55c0bb 100644 --- a/launcher/ui/widgets/InfoFrame.cpp +++ b/launcher/ui/widgets/InfoFrame.cpp @@ -1,37 +1,38 @@ // SPDX-License-Identifier: GPL-3.0-only /* -* PolyMC - Minecraft Launcher -* Copyright (c) 2022 flowln -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, version 3. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -* -* This file incorporates work covered by the following copyright and -* permission notice: -* -* Copyright 2013-2021 MultiMC Contributors -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ + * Prism Launcher - Minecraft Launcher + * Copyright (c) 2022 flowln + * Copyright (c) 2023 Trial97 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Copyright 2013-2021 MultiMC Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ #include @@ -57,34 +58,47 @@ InfoFrame::~InfoFrame() void InfoFrame::updateWithMod(Mod const& m) { - if (m.type() == ResourceType::FOLDER) - { + if (m.type() == ResourceType::FOLDER) { clear(); return; } QString text = ""; QString name = ""; + QString link = ""; + QString toolTip = ""; if (m.name().isEmpty()) name = m.internal_id(); else name = m.name(); - if (m.homeurl().isEmpty()) + if (auto meta = m.metadata(); meta != nullptr) { + auto slug = meta->slug.remove(".pw.toml"); + switch (meta->provider) { + case ModPlatform::ResourceProvider::MODRINTH: + link = QString("https://modrinth.com/mod/%1").arg(slug); + break; + case ModPlatform::ResourceProvider::FLAME: + link = QString("https://www.curseforge.com/minecraft/mc-mods/%1").arg(slug); + break; + } + } else if (!m.homeurl().isEmpty()) + link = m.homeurl(); + + if (link.isEmpty()) text = name; - else - text = "" + name + ""; + else { + text = "" + name + ""; + toolTip = tr("Go to mod's home page"); + } if (!m.authors().isEmpty()) text += " by " + m.authors().join(", "); - setName(text); + setName(text, toolTip); - if (m.description().isEmpty()) - { + if (m.description().isEmpty()) { setDescription(QString()); - } - else - { + } else { setDescription(m.description()); } @@ -191,16 +205,15 @@ void InfoFrame::updateHiddenState() } } -void InfoFrame::setName(QString text) +void InfoFrame::setName(QString text, QString toolTip) { - if(text.isEmpty()) - { + if (text.isEmpty()) { ui->nameLabel->setHidden(true); - } - else - { + ui->nameLabel->setToolTip({}); + } else { ui->nameLabel->setText(text); ui->nameLabel->setHidden(false); + ui->nameLabel->setToolTip(toolTip); } updateHiddenState(); } diff --git a/launcher/ui/widgets/InfoFrame.h b/launcher/ui/widgets/InfoFrame.h index 84523e281..4f6adc6d6 100644 --- a/launcher/ui/widgets/InfoFrame.h +++ b/launcher/ui/widgets/InfoFrame.h @@ -1,16 +1,36 @@ -/* Copyright 2013-2021 MultiMC Contributors +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (c) 2023 Trial97 * - * 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 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * 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. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Copyright 2013-2021 MultiMC Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ #pragma once @@ -21,8 +41,7 @@ #include "minecraft/mod/ResourcePack.h" #include "minecraft/mod/TexturePack.h" -namespace Ui -{ +namespace Ui { class InfoFrame; } @@ -33,7 +52,7 @@ class InfoFrame : public QFrame { InfoFrame(QWidget* parent = nullptr); ~InfoFrame() override; - void setName(QString text = {}); + void setName(QString text = {}, QString toolTip = {}); void setDescription(QString text = {}); void setImage(QPixmap img = {}); From d9b24f770561e3bb139955854ac7f3ca4d92a122 Mon Sep 17 00:00:00 2001 From: James Beddek Date: Tue, 20 Jun 2023 16:52:57 +1200 Subject: [PATCH 016/216] Screenshots: remove path from watcher if it no longer exists Signed-off-by: James Beddek --- launcher/ui/pages/instance/ScreenshotsPage.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/launcher/ui/pages/instance/ScreenshotsPage.cpp b/launcher/ui/pages/instance/ScreenshotsPage.cpp index ca368d3b7..8f134efd3 100644 --- a/launcher/ui/pages/instance/ScreenshotsPage.cpp +++ b/launcher/ui/pages/instance/ScreenshotsPage.cpp @@ -145,7 +145,6 @@ public: m_thumbnailCache = std::make_shared(); m_thumbnailCache->add("placeholder", APPLICATION->getThemedIcon("screenshot-placeholder")); connect(&watcher, SIGNAL(fileChanged(QString)), SLOT(fileChanged(QString))); - // FIXME: the watched file set is not updated when files are removed } virtual ~FilterModel() { m_thumbnailingPool.waitForDone(500); } virtual QVariant data(const QModelIndex &proxyIndex, int role = Qt::DisplayRole) const @@ -214,10 +213,12 @@ private slots: void fileChanged(QString filepath) { m_thumbnailCache->setStale(filepath); - thumbnailImage(filepath); // reinsert the path... watcher.removePath(filepath); - watcher.addPath(filepath); + if (QFile::exists(filepath)) { + watcher.addPath(filepath); + thumbnailImage(filepath); + } } private: From f2471f0f68e436d25d27ccc750e6668c07a29070 Mon Sep 17 00:00:00 2001 From: James Beddek Date: Tue, 20 Jun 2023 16:54:15 +1200 Subject: [PATCH 017/216] Screenshots: clear the thumbnailing pool on page delete Removes pending QThreadPool jobs which linger after page delete. May help with #1201 by allowing the pool to finish earlier. Signed-off-by: James Beddek --- launcher/ui/pages/instance/ScreenshotsPage.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/launcher/ui/pages/instance/ScreenshotsPage.cpp b/launcher/ui/pages/instance/ScreenshotsPage.cpp index 8f134efd3..9d1f8421c 100644 --- a/launcher/ui/pages/instance/ScreenshotsPage.cpp +++ b/launcher/ui/pages/instance/ScreenshotsPage.cpp @@ -146,7 +146,11 @@ public: m_thumbnailCache->add("placeholder", APPLICATION->getThemedIcon("screenshot-placeholder")); connect(&watcher, SIGNAL(fileChanged(QString)), SLOT(fileChanged(QString))); } - virtual ~FilterModel() { m_thumbnailingPool.waitForDone(500); } + virtual ~FilterModel() { + m_thumbnailingPool.clear(); + if (!m_thumbnailingPool.waitForDone(500)) + qDebug() << "Thumbnail pool took longer than 500ms to finish"; + } virtual QVariant data(const QModelIndex &proxyIndex, int role = Qt::DisplayRole) const { auto model = sourceModel(); From 75bd626f33a5182facff2ef1f9938f60553c3352 Mon Sep 17 00:00:00 2001 From: James Beddek Date: Tue, 20 Jun 2023 16:59:59 +1200 Subject: [PATCH 018/216] Screenshots: do not retry image thumbnailing on null result This causes the thumbnailing thread pool to spend a lot of time attempting to retry an image that failed. A null result is common where the image is too large to be allocated (>128MiB alloc). The repeated retries continue after page delete, causing hangs if a user tries to exit the application. Fixes: #1201 Signed-off-by: James Beddek --- .../ui/pages/instance/ScreenshotsPage.cpp | 51 ++++++++----------- 1 file changed, 22 insertions(+), 29 deletions(-) diff --git a/launcher/ui/pages/instance/ScreenshotsPage.cpp b/launcher/ui/pages/instance/ScreenshotsPage.cpp index 9d1f8421c..75bb48b2d 100644 --- a/launcher/ui/pages/instance/ScreenshotsPage.cpp +++ b/launcher/ui/pages/instance/ScreenshotsPage.cpp @@ -96,37 +96,30 @@ public: return; if ((info.suffix().compare("png", Qt::CaseInsensitive) != 0)) return; - int tries = 5; - while (tries) - { - if (!m_cache->stale(m_path)) - return; - QImage image(m_path); - if (image.isNull()) - { - QThread::msleep(500); - tries--; - continue; - } - QImage small; - if (image.width() > image.height()) - small = image.scaledToWidth(512).scaledToWidth(256, Qt::SmoothTransformation); - else - small = image.scaledToHeight(512).scaledToHeight(256, Qt::SmoothTransformation); - QPoint offset((256 - small.width()) / 2, (256 - small.height()) / 2); - QImage square(QSize(256, 256), QImage::Format_ARGB32); - square.fill(Qt::transparent); - - QPainter painter(&square); - painter.drawImage(offset, small); - painter.end(); - - QIcon icon(QPixmap::fromImage(square)); - m_cache->add(m_path, icon); - m_resultEmitter.emitResultsReady(m_path); + if (!m_cache->stale(m_path)) + return; + QImage image(m_path); + if (image.isNull()) { + m_resultEmitter.emitResultsFailed(m_path); + qDebug() << "Error loading screenshot: " + m_path + ". Perhaps too large?"; return; } - m_resultEmitter.emitResultsFailed(m_path); + QImage small; + if (image.width() > image.height()) + small = image.scaledToWidth(512).scaledToWidth(256, Qt::SmoothTransformation); + else + small = image.scaledToHeight(512).scaledToHeight(256, Qt::SmoothTransformation); + QPoint offset((256 - small.width()) / 2, (256 - small.height()) / 2); + QImage square(QSize(256, 256), QImage::Format_ARGB32); + square.fill(Qt::transparent); + + QPainter painter(&square); + painter.drawImage(offset, small); + painter.end(); + + QIcon icon(QPixmap::fromImage(square)); + m_cache->add(m_path, icon); + m_resultEmitter.emitResultsReady(m_path); } QString m_path; SharedIconCachePtr m_cache; From 480faca5598b503eb130566061f06348e4a42b8f Mon Sep 17 00:00:00 2001 From: Trial97 Date: Wed, 21 Jun 2023 21:17:17 +0300 Subject: [PATCH 019/216] Removed unused variable Signed-off-by: Trial97 --- .../ui/pages/instance/ExternalResourcesPage.cpp | 15 --------------- .../ui/pages/instance/ExternalResourcesPage.h | 2 -- launcher/ui/pages/instance/ModFolderPage.cpp | 4 +--- launcher/ui/pages/instance/ResourcePackPage.cpp | 2 -- launcher/ui/pages/instance/ShaderPackPage.cpp | 3 --- launcher/ui/pages/instance/TexturePackPage.cpp | 2 -- 6 files changed, 1 insertion(+), 27 deletions(-) diff --git a/launcher/ui/pages/instance/ExternalResourcesPage.cpp b/launcher/ui/pages/instance/ExternalResourcesPage.cpp index e50fa6353..e77e45726 100644 --- a/launcher/ui/pages/instance/ExternalResourcesPage.cpp +++ b/launcher/ui/pages/instance/ExternalResourcesPage.cpp @@ -135,9 +135,6 @@ void ExternalResourcesPage::retranslate() void ExternalResourcesPage::itemActivated(const QModelIndex&) { - if (!m_controlsEnabled) - return; - auto selection = m_filterModel->mapSelectionToSource(ui->treeView->selectionModel()->selection()); m_model->setResourceEnabled(selection.indexes(), EnableAction::TOGGLE); } @@ -182,9 +179,6 @@ bool ExternalResourcesPage::eventFilter(QObject* obj, QEvent* ev) void ExternalResourcesPage::addItem() { - if (!m_controlsEnabled) - return; - auto list = GuiUtil::BrowseForFiles( helpPage(), tr("Select %1", "Select whatever type of files the page contains. Example: 'Loader Mods'").arg(displayName()), m_fileSelectionFilter.arg(displayName()), APPLICATION->settings()->get("CentralModsDir").toString(), this->parentWidget()); @@ -198,9 +192,6 @@ void ExternalResourcesPage::addItem() void ExternalResourcesPage::removeItem() { - if (!m_controlsEnabled) - return; - auto selection = m_filterModel->mapSelectionToSource(ui->treeView->selectionModel()->selection()); int count = 0; @@ -249,18 +240,12 @@ void ExternalResourcesPage::removeItems(const QItemSelection& selection) void ExternalResourcesPage::enableItem() { - if (!m_controlsEnabled) - return; - auto selection = m_filterModel->mapSelectionToSource(ui->treeView->selectionModel()->selection()); m_model->setResourceEnabled(selection.indexes(), EnableAction::ENABLE); } void ExternalResourcesPage::disableItem() { - if (!m_controlsEnabled) - return; - auto selection = m_filterModel->mapSelectionToSource(ui->treeView->selectionModel()->selection()); m_model->setResourceEnabled(selection.indexes(), EnableAction::DISABLE); } diff --git a/launcher/ui/pages/instance/ExternalResourcesPage.h b/launcher/ui/pages/instance/ExternalResourcesPage.h index fd2001938..acea81b59 100644 --- a/launcher/ui/pages/instance/ExternalResourcesPage.h +++ b/launcher/ui/pages/instance/ExternalResourcesPage.h @@ -72,7 +72,5 @@ class ExternalResourcesPage : public QMainWindow, public BasePage { QString m_fileSelectionFilter; QString m_viewFilter; - bool m_controlsEnabled = true; - std::shared_ptr m_wide_bar_setting = nullptr; }; diff --git a/launcher/ui/pages/instance/ModFolderPage.cpp b/launcher/ui/pages/instance/ModFolderPage.cpp index 90e7d0d62..ef7b1f2b8 100644 --- a/launcher/ui/pages/instance/ModFolderPage.cpp +++ b/launcher/ui/pages/instance/ModFolderPage.cpp @@ -133,15 +133,13 @@ bool ModFolderPage::onSelectionChanged(const QModelIndex& current, const QModelI return true; } -void ModFolderPage::removeItems(const QItemSelection &selection) +void ModFolderPage::removeItems(const QItemSelection& selection) { m_model->deleteMods(selection.indexes()); } void ModFolderPage::installMods() { - if (!m_controlsEnabled) - return; if (m_instance->typeName() != "Minecraft") return; // this is a null instance or a legacy instance diff --git a/launcher/ui/pages/instance/ResourcePackPage.cpp b/launcher/ui/pages/instance/ResourcePackPage.cpp index 24bfb38dc..12b371df4 100644 --- a/launcher/ui/pages/instance/ResourcePackPage.cpp +++ b/launcher/ui/pages/instance/ResourcePackPage.cpp @@ -67,8 +67,6 @@ bool ResourcePackPage::onSelectionChanged(const QModelIndex& current, const QMod void ResourcePackPage::downloadRPs() { - if (!m_controlsEnabled) - return; if (m_instance->typeName() != "Minecraft") return; // this is a null instance or a legacy instance diff --git a/launcher/ui/pages/instance/ShaderPackPage.cpp b/launcher/ui/pages/instance/ShaderPackPage.cpp index 2d0c10aaf..dc8b0a05b 100644 --- a/launcher/ui/pages/instance/ShaderPackPage.cpp +++ b/launcher/ui/pages/instance/ShaderPackPage.cpp @@ -46,7 +46,6 @@ #include "ui/dialogs/ProgressDialog.h" #include "ui/dialogs/ResourceDownloadDialog.h" - ShaderPackPage::ShaderPackPage(MinecraftInstance* instance, std::shared_ptr model, QWidget* parent) : ExternalResourcesPage(instance, model, parent) { @@ -61,8 +60,6 @@ ShaderPackPage::ShaderPackPage(MinecraftInstance* instance, std::shared_ptrtypeName() != "Minecraft") return; // this is a null instance or a legacy instance diff --git a/launcher/ui/pages/instance/TexturePackPage.cpp b/launcher/ui/pages/instance/TexturePackPage.cpp index 427aba11a..e477ceda3 100644 --- a/launcher/ui/pages/instance/TexturePackPage.cpp +++ b/launcher/ui/pages/instance/TexturePackPage.cpp @@ -69,8 +69,6 @@ bool TexturePackPage::onSelectionChanged(const QModelIndex& current, const QMode void TexturePackPage::downloadTPs() { - if (!m_controlsEnabled) - return; if (m_instance->typeName() != "Minecraft") return; // this is a null instance or a legacy instance From 0d2105dec44bb1b5234e18ce6a8de5b2d26eb93a Mon Sep 17 00:00:00 2001 From: Trial97 Date: Wed, 21 Jun 2023 21:34:40 +0300 Subject: [PATCH 020/216] Made buttons on ModsFolderPage enabled all the time Signed-off-by: Trial97 --- launcher/minecraft/MinecraftInstance.cpp | 15 +--- launcher/minecraft/mod/ModFolderModel.cpp | 11 +-- .../minecraft/mod/ResourceFolderModel.cpp | 69 +++++++------------ launcher/minecraft/mod/ResourceFolderModel.h | 14 ++-- launcher/ui/pages/instance/ModFolderPage.cpp | 20 +----- launcher/ui/pages/instance/ModFolderPage.h | 3 +- 6 files changed, 39 insertions(+), 93 deletions(-) diff --git a/launcher/minecraft/MinecraftInstance.cpp b/launcher/minecraft/MinecraftInstance.cpp index f8ed5214e..e896799a7 100644 --- a/launcher/minecraft/MinecraftInstance.cpp +++ b/launcher/minecraft/MinecraftInstance.cpp @@ -1112,36 +1112,27 @@ JavaVersion MinecraftInstance::getJavaVersion() std::shared_ptr MinecraftInstance::loaderModList() { - if (!m_loader_mod_list) - { + if (!m_loader_mod_list) { bool is_indexed = !APPLICATION->settings()->get("ModMetadataDisabled").toBool(); m_loader_mod_list.reset(new ModFolderModel(modsRoot(), this, is_indexed)); - m_loader_mod_list->disableInteraction(isRunning()); - connect(this, &BaseInstance::runningStatusChanged, m_loader_mod_list.get(), &ModFolderModel::disableInteraction); } return m_loader_mod_list; } std::shared_ptr MinecraftInstance::coreModList() { - if (!m_core_mod_list) - { + if (!m_core_mod_list) { bool is_indexed = !APPLICATION->settings()->get("ModMetadataDisabled").toBool(); m_core_mod_list.reset(new ModFolderModel(coreModsDir(), this, is_indexed)); - m_core_mod_list->disableInteraction(isRunning()); - connect(this, &BaseInstance::runningStatusChanged, m_core_mod_list.get(), &ModFolderModel::disableInteraction); } return m_core_mod_list; } std::shared_ptr MinecraftInstance::nilModList() { - if (!m_nil_mod_list) - { + if (!m_nil_mod_list) { bool is_indexed = !APPLICATION->settings()->get("ModMetadataDisabled").toBool(); m_nil_mod_list.reset(new ModFolderModel(nilModsDir(), this, is_indexed, false)); - m_nil_mod_list->disableInteraction(isRunning()); - connect(this, &BaseInstance::runningStatusChanged, m_nil_mod_list.get(), &ModFolderModel::disableInteraction); } return m_nil_mod_list; } diff --git a/launcher/minecraft/mod/ModFolderModel.cpp b/launcher/minecraft/mod/ModFolderModel.cpp index 5e3b31e08..0089cd8be 100644 --- a/launcher/minecraft/mod/ModFolderModel.cpp +++ b/launcher/minecraft/mod/ModFolderModel.cpp @@ -213,16 +213,11 @@ bool ModFolderModel::uninstallMod(const QString& filename, bool preserve_metadat bool ModFolderModel::deleteMods(const QModelIndexList& indexes) { - if(!m_can_interact) { - return false; - } - - if(indexes.isEmpty()) + if (indexes.isEmpty()) return true; - for (auto i: indexes) - { - if(i.column() != 0) { + for (auto i : indexes) { + if (i.column() != 0) { continue; } auto m = at(i.row()); diff --git a/launcher/minecraft/mod/ResourceFolderModel.cpp b/launcher/minecraft/mod/ResourceFolderModel.cpp index d2d875e48..c38e97d92 100644 --- a/launcher/minecraft/mod/ResourceFolderModel.cpp +++ b/launcher/minecraft/mod/ResourceFolderModel.cpp @@ -74,10 +74,6 @@ bool ResourceFolderModel::stopWatching(const QStringList paths) bool ResourceFolderModel::installResource(QString original_path) { - if (!m_can_interact) { - return false; - } - // NOTE: fix for GH-1178: remove trailing slash to avoid issues with using the empty result of QFileInfo::fileName original_path = FS::NormalizePath(original_path); QFileInfo file_info(original_path); @@ -168,9 +164,6 @@ bool ResourceFolderModel::uninstallResource(QString file_name) bool ResourceFolderModel::deleteResources(const QModelIndexList& indexes) { - if (!m_can_interact) - return false; - if (indexes.isEmpty()) return true; @@ -189,11 +182,8 @@ bool ResourceFolderModel::deleteResources(const QModelIndexList& indexes) return true; } -bool ResourceFolderModel::setResourceEnabled(const QModelIndexList &indexes, EnableAction action) +bool ResourceFolderModel::setResourceEnabled(const QModelIndexList& indexes, EnableAction action) { - if (!m_can_interact) - return false; - if (indexes.isEmpty()) return true; @@ -246,15 +236,18 @@ bool ResourceFolderModel::update() connect(m_current_update_task.get(), &Task::succeeded, this, &ResourceFolderModel::onUpdateSucceeded, Qt::ConnectionType::QueuedConnection); connect(m_current_update_task.get(), &Task::failed, this, &ResourceFolderModel::onUpdateFailed, Qt::ConnectionType::QueuedConnection); - connect(m_current_update_task.get(), &Task::finished, this, [=] { - m_current_update_task.reset(); - if (m_scheduled_update) { - m_scheduled_update = false; - update(); - } else { - emit updateFinished(); - } - }, Qt::ConnectionType::QueuedConnection); + connect( + m_current_update_task.get(), &Task::finished, this, + [=] { + m_current_update_task.reset(); + if (m_scheduled_update) { + m_scheduled_update = false; + update(); + } else { + emit updateFinished(); + } + }, + Qt::ConnectionType::QueuedConnection); QThreadPool::globalInstance()->start(m_current_update_task.get()); @@ -344,15 +337,9 @@ Qt::DropActions ResourceFolderModel::supportedDropActions() const Qt::ItemFlags ResourceFolderModel::flags(const QModelIndex& index) const { Qt::ItemFlags defaultFlags = QAbstractListModel::flags(index); - auto flags = defaultFlags; - if (!m_can_interact) { - flags &= ~Qt::ItemIsDropEnabled; - } else { - flags |= Qt::ItemIsDropEnabled; - if (index.isValid()) { - flags |= Qt::ItemIsUserCheckable; - } - } + auto flags = defaultFlags | Qt::ItemIsDropEnabled; + if (index.isValid()) + flags |= Qt::ItemIsUserCheckable; return flags; } @@ -425,16 +412,17 @@ QVariant ResourceFolderModel::data(const QModelIndex& index, int role) const if (column == NAME_COLUMN) { if (at(row).isSymLinkUnder(instDirPath())) { return m_resources[row]->internal_id() + - tr("\nWarning: This resource is symbolically linked from elsewhere. Editing it will also change the original." - "\nCanonical Path: %1") - .arg(at(row).fileinfo().canonicalFilePath());; + tr("\nWarning: This resource is symbolically linked from elsewhere. Editing it will also change the original." + "\nCanonical Path: %1") + .arg(at(row).fileinfo().canonicalFilePath()); + ; } if (at(row).isMoreThanOneHardLink()) { return m_resources[row]->internal_id() + - tr("\nWarning: This resource is hard linked elsewhere. Editing it will also change the original."); + tr("\nWarning: This resource is hard linked elsewhere. Editing it will also change the original."); } } - + return m_resources[row]->internal_id(); case Qt::DecorationRole: { if (column == NAME_COLUMN && (at(row).isSymLinkUnder(instDirPath()) || at(row).isMoreThanOneHardLink())) @@ -511,16 +499,6 @@ SortType ResourceFolderModel::columnToSortKey(size_t column) const return m_column_sort_keys.at(column); } -void ResourceFolderModel::enableInteraction(bool enabled) -{ - if (m_can_interact == enabled) - return; - - m_can_interact = enabled; - if (size()) - emit dataChanged(index(0), index(size() - 1)); -} - /* Standard Proxy Model for createFilterProxyModel */ [[nodiscard]] bool ResourceFolderModel::ProxyModel::filterAcceptsRow(int source_row, const QModelIndex& source_parent) const { @@ -556,6 +534,7 @@ void ResourceFolderModel::enableInteraction(bool enabled) return (compare_result.first > 0); } -QString ResourceFolderModel::instDirPath() const { +QString ResourceFolderModel::instDirPath() const +{ return QFileInfo(m_instance->instanceRoot()).absoluteFilePath(); } diff --git a/launcher/minecraft/mod/ResourceFolderModel.h b/launcher/minecraft/mod/ResourceFolderModel.h index 0a35e1bca..d5ca08e82 100644 --- a/launcher/minecraft/mod/ResourceFolderModel.h +++ b/launcher/minecraft/mod/ResourceFolderModel.h @@ -11,8 +11,8 @@ #include "BaseInstance.h" -#include "tasks/Task.h" #include "tasks/ConcurrentTask.h" +#include "tasks/Task.h" class QSortFilterProxyModel; @@ -129,10 +129,6 @@ class ResourceFolderModel : public QAbstractListModel { QString instDirPath() const; - public slots: - void enableInteraction(bool enabled); - void disableInteraction(bool disabled) { enableInteraction(!disabled); } - signals: void updateFinished(); @@ -181,15 +177,17 @@ class ResourceFolderModel : public QAbstractListModel { * if the resource is complex and has more stuff to parse. */ virtual void onParseSucceeded(int ticket, QString resource_id); - virtual void onParseFailed(int ticket, QString resource_id) { Q_UNUSED(ticket); Q_UNUSED(resource_id); } + virtual void onParseFailed(int ticket, QString resource_id) + { + Q_UNUSED(ticket); + Q_UNUSED(resource_id); + } protected: // Represents the relationship between a column's index (represented by the list index), and it's sorting key. // As such, the order in with they appear is very important! QList m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::DATE }; - bool m_can_interact = true; - QDir m_dir; BaseInstance* m_instance; QFileSystemWatcher m_watcher; diff --git a/launcher/ui/pages/instance/ModFolderPage.cpp b/launcher/ui/pages/instance/ModFolderPage.cpp index ef7b1f2b8..9812bbe93 100644 --- a/launcher/ui/pages/instance/ModFolderPage.cpp +++ b/launcher/ui/pages/instance/ModFolderPage.cpp @@ -86,9 +86,7 @@ ModFolderPage::ModFolderPage(BaseInstance* inst, std::shared_ptr ui->actionsToolbar->insertActionAfter(ui->actionAddItem, ui->actionUpdateItem); connect(ui->actionUpdateItem, &QAction::triggered, this, &ModFolderPage::updateMods); - auto check_allow_update = [this] { - return (!m_instance || !m_instance->isRunning()) && (ui->treeView->selectionModel()->hasSelection() || !m_model->empty()); - }; + auto check_allow_update = [this] { return ui->treeView->selectionModel()->hasSelection() || !m_model->empty(); }; connect(ui->treeView->selectionModel(), &QItemSelectionModel::selectionChanged, this, [this, check_allow_update] { ui->actionUpdateItem->setEnabled(check_allow_update()); }); @@ -101,22 +99,9 @@ ModFolderPage::ModFolderPage(BaseInstance* inst, std::shared_ptr connect(mods.get(), &ModFolderModel::updateFinished, this, [this, check_allow_update] { ui->actionUpdateItem->setEnabled(check_allow_update()); }); - - connect(m_instance, &BaseInstance::runningStatusChanged, this, &ModFolderPage::runningStateChanged); - ModFolderPage::runningStateChanged(m_instance && m_instance->isRunning()); } } -void ModFolderPage::runningStateChanged(bool running) -{ - ui->actionDownloadItem->setEnabled(!running); - ui->actionUpdateItem->setEnabled(!running); - ui->actionAddItem->setEnabled(!running); - ui->actionEnableItem->setEnabled(!running); - ui->actionDisableItem->setEnabled(!running); - ui->actionRemoveItem->setEnabled(!running); -} - bool ModFolderPage::shouldDisplay() const { return true; @@ -205,8 +190,7 @@ void ModFolderPage::updateMods() message = tr("All selected mods are up-to-date! :)"); } } - CustomMessageBox::selectable(this, tr("Update checker"), message) - ->exec(); + CustomMessageBox::selectable(this, tr("Update checker"), message)->exec(); return; } diff --git a/launcher/ui/pages/instance/ModFolderPage.h b/launcher/ui/pages/instance/ModFolderPage.h index 2fc7b5748..b59841959 100644 --- a/launcher/ui/pages/instance/ModFolderPage.h +++ b/launcher/ui/pages/instance/ModFolderPage.h @@ -59,8 +59,7 @@ class ModFolderPage : public ExternalResourcesPage { bool onSelectionChanged(const QModelIndex& current, const QModelIndex& previous) override; private slots: - void runningStateChanged(bool running); - void removeItems(const QItemSelection &selection) override; + void removeItems(const QItemSelection& selection) override; void installMods(); void updateMods(); From 820892d7cc7864315bd73dcd877cb0a1beb2b106 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Wed, 21 Jun 2023 22:42:08 +0300 Subject: [PATCH 021/216] Made settings editable when instance is running Signed-off-by: Trial97 --- launcher/ui/pages/instance/InstanceSettingsPage.cpp | 13 ++----------- launcher/ui/pages/instance/InstanceSettingsPage.h | 3 +-- 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/launcher/ui/pages/instance/InstanceSettingsPage.cpp b/launcher/ui/pages/instance/InstanceSettingsPage.cpp index 08977841a..1108d2643 100644 --- a/launcher/ui/pages/instance/InstanceSettingsPage.cpp +++ b/launcher/ui/pages/instance/InstanceSettingsPage.cpp @@ -60,17 +60,13 @@ InstanceSettingsPage::InstanceSettingsPage(BaseInstance *inst, QWidget *parent) m_settings = inst->settings(); ui->setupUi(this); - // As the signal will (probably) not be triggered once we click edit, let's update it manually instead. - updateRunningStatus(m_instance->isRunning()); - - connect(m_instance, &BaseInstance::runningStatusChanged, this, &InstanceSettingsPage::updateRunningStatus); connect(ui->openGlobalJavaSettingsButton, &QCommandLinkButton::clicked, this, &InstanceSettingsPage::globalSettingsButtonClicked); connect(APPLICATION, &Application::globalSettingsAboutToOpen, this, &InstanceSettingsPage::applySettings); connect(APPLICATION, &Application::globalSettingsClosed, this, &InstanceSettingsPage::loadSettings); - connect(ui->instanceAccountSelector, QOverload::of(&QComboBox::currentIndexChanged), this, &InstanceSettingsPage::changeInstanceAccount); + connect(ui->instanceAccountSelector, QOverload::of(&QComboBox::currentIndexChanged), this, + &InstanceSettingsPage::changeInstanceAccount); loadSettings(); - updateThresholds(); } @@ -523,8 +519,3 @@ void InstanceSettingsPage::updateThresholds() ui->labelMaxMemIcon->setPixmap(pix); } } - -void InstanceSettingsPage::updateRunningStatus(bool running) -{ - setEnabled(!running); -} diff --git a/launcher/ui/pages/instance/InstanceSettingsPage.h b/launcher/ui/pages/instance/InstanceSettingsPage.h index 0438fe3b2..036b41818 100644 --- a/launcher/ui/pages/instance/InstanceSettingsPage.h +++ b/launcher/ui/pages/instance/InstanceSettingsPage.h @@ -79,8 +79,7 @@ public: void updateThresholds(); -private slots: - void updateRunningStatus(bool running); + private slots: void on_javaDetectBtn_clicked(); void on_javaTestBtn_clicked(); void on_javaBrowseBtn_clicked(); From 9d2516a199ae4c33f773ab00ce59ecb2a6dfd0a5 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 22 Jun 2023 16:00:45 +0300 Subject: [PATCH 022/216] Added ExportModsToStringTask Signed-off-by: Trial97 --- launcher/CMakeLists.txt | 3 + .../helpers/ExportModsToStringTask.cpp | 114 ++++++++++++++++++ .../helpers/ExportModsToStringTask.h | 33 +++++ 3 files changed, 150 insertions(+) create mode 100644 launcher/modplatform/helpers/ExportModsToStringTask.cpp create mode 100644 launcher/modplatform/helpers/ExportModsToStringTask.h diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index ce2771a49..c7efdad84 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -487,6 +487,9 @@ set(API_SOURCES modplatform/helpers/HashUtils.cpp modplatform/helpers/OverrideUtils.h modplatform/helpers/OverrideUtils.cpp + + modplatform/helpers/ExportModsToStringTask.h + modplatform/helpers/ExportModsToStringTask.cpp ) set(FTB_SOURCES diff --git a/launcher/modplatform/helpers/ExportModsToStringTask.cpp b/launcher/modplatform/helpers/ExportModsToStringTask.cpp new file mode 100644 index 000000000..a105fc352 --- /dev/null +++ b/launcher/modplatform/helpers/ExportModsToStringTask.cpp @@ -0,0 +1,114 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (c) 2023 Trial97 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include "ExportModsToStringTask.h" +#include "modplatform/ModIndex.h" + +namespace ExportToString { +QString ExportModsToStringTask(QList mods, Formats format, OptionalData extraData) +{ + switch (format) { + case HTML: { + QStringList lines; + for (auto mod : mods) { + auto meta = mod->metadata(); + auto modName = mod->name(); + if (extraData & Url) { + auto url = mod->homeurl(); + if (meta != nullptr) { + url = (meta->provider == ModPlatform::ResourceProvider::FLAME ? "https://www.curseforge.com/minecraft/mc-mods/" + : "https://modrinth.com/mod/") + + meta->project_id.toString(); + } + if (!url.isEmpty()) + modName = QString("%2").arg(url, modName); + } + auto line = modName; + if (extraData & Version) { + auto ver = mod->version(); + if (ver.isEmpty() && meta != nullptr) + ver = meta->version().toString(); + if (!ver.isEmpty()) + line += QString("[%1]").arg(ver); + } + if (extraData & Authors && !mod->authors().isEmpty()) + line += " by " + mod->authors().join(", "); + lines.append(QString("
    %1
").arg(line)); + } + return QString("\n\t%1\n").arg(lines.join("\n\t")); + } + case MARKDOWN: { + QStringList lines; + for (auto mod : mods) { + auto meta = mod->metadata(); + auto modName = mod->name(); + if (extraData & Url) { + auto url = mod->homeurl(); + if (meta != nullptr) { + url = (meta->provider == ModPlatform::ResourceProvider::FLAME ? "https://www.curseforge.com/minecraft/mc-mods/" + : "https://modrinth.com/mod/") + + meta->project_id.toString(); + } + if (!url.isEmpty()) + modName = QString("[%1](%2)").arg(modName, url); + } + auto line = modName; + if (extraData & Version) { + auto ver = mod->version(); + if (ver.isEmpty() && meta != nullptr) + ver = meta->version().toString(); + if (!ver.isEmpty()) + line += QString("[%1]").arg(ver); + } + if (extraData & Authors && !mod->authors().isEmpty()) + line += " by " + mod->authors().join(", "); + lines << line; + } + return lines.join("\n"); + } + default: { + return QString("unknown format:%1").arg(format); + } + } +} + +QString ExportModsToStringTask(QList mods, QString lineTemplate) +{ + QStringList lines; + for (auto mod : mods) { + auto meta = mod->metadata(); + auto modName = mod->name(); + + auto url = mod->homeurl(); + if (meta != nullptr) { + url = (meta->provider == ModPlatform::ResourceProvider::FLAME ? "https://www.curseforge.com/minecraft/mc-mods/" + : "https://modrinth.com/mod/") + + meta->project_id.toString(); + } + auto ver = mod->version(); + if (ver.isEmpty() && meta != nullptr) + ver = meta->version().toString(); + auto authors = mod->authors().join(", "); + lines << QString(lineTemplate) + .replace("{name}", modName) + .replace("{url}", url) + .replace("{version}", ver) + .replace("{authors}", authors); + } + return lines.join("\n"); +} +} // namespace ExportToString \ No newline at end of file diff --git a/launcher/modplatform/helpers/ExportModsToStringTask.h b/launcher/modplatform/helpers/ExportModsToStringTask.h new file mode 100644 index 000000000..756c69f77 --- /dev/null +++ b/launcher/modplatform/helpers/ExportModsToStringTask.h @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (c) 2023 Trial97 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once +#include +#include +#include "minecraft/mod/Mod.h" + +namespace ExportToString { + +enum Formats { HTML, MARKDOWN }; +enum OptionalData { + Authors = 1 << 0, + Url = 1 << 1, + Version = 1 << 2, +}; +QString ExportModsToStringTask(QList mods, Formats format, OptionalData extraData); +QString ExportModsToStringTask(QList mods, QString lineTemplate); +} // namespace ExportToString From f7d502c68c530d66b385d530c838a9a6566828d0 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 22 Jun 2023 16:05:47 +0300 Subject: [PATCH 023/216] Added ExportModsToStringDialog Signed-off-by: Trial97 --- launcher/CMakeLists.txt | 3 + launcher/ui/MainWindow.cpp | 10 + launcher/ui/MainWindow.h | 1 + launcher/ui/MainWindow.ui | 8 + .../ui/dialogs/ExportModsToStringDialog.cpp | 119 ++++++++++++ .../ui/dialogs/ExportModsToStringDialog.h | 45 +++++ .../ui/dialogs/ExportModsToStringDialog.ui | 171 ++++++++++++++++++ 7 files changed, 357 insertions(+) create mode 100644 launcher/ui/dialogs/ExportModsToStringDialog.cpp create mode 100644 launcher/ui/dialogs/ExportModsToStringDialog.h create mode 100644 launcher/ui/dialogs/ExportModsToStringDialog.ui diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index c7efdad84..5ef97f422 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -911,6 +911,8 @@ SET(LAUNCHER_SOURCES ui/dialogs/ExportInstanceDialog.h ui/dialogs/ExportMrPackDialog.cpp ui/dialogs/ExportMrPackDialog.h + ui/dialogs/ExportModsToStringDialog.cpp + ui/dialogs/ExportModsToStringDialog.h ui/dialogs/IconPickerDialog.cpp ui/dialogs/IconPickerDialog.h ui/dialogs/ImportResourceDialog.cpp @@ -1058,6 +1060,7 @@ qt_wrap_ui(LAUNCHER_UI ui/dialogs/SkinUploadDialog.ui ui/dialogs/ExportInstanceDialog.ui ui/dialogs/ExportMrPackDialog.ui + ui/dialogs/ExportModsToStringDialog.ui ui/dialogs/IconPickerDialog.ui ui/dialogs/ImportResourceDialog.ui ui/dialogs/MSALoginDialog.ui diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp index e04011cab..02ea30c36 100644 --- a/launcher/ui/MainWindow.cpp +++ b/launcher/ui/MainWindow.cpp @@ -43,6 +43,7 @@ #include "FileSystem.h" #include "MainWindow.h" +#include "ui/dialogs/ExportModsToStringDialog.h" #include "ui_MainWindow.h" #include @@ -205,6 +206,7 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi auto exportInstanceMenu = new QMenu(this); exportInstanceMenu->addAction(ui->actionExportInstanceZip); exportInstanceMenu->addAction(ui->actionExportInstanceMrPack); + exportInstanceMenu->addAction(ui->actionExportInstanceToString); ui->actionExportInstance->setMenu(exportInstanceMenu); } @@ -1416,6 +1418,14 @@ void MainWindow::on_actionExportInstanceMrPack_triggered() } } +void MainWindow::on_actionExportInstanceToString_triggered() +{ + if (m_selectedInstance) { + ExportModsToStringDialog dlg(m_selectedInstance, this); + dlg.exec(); + } +} + void MainWindow::on_actionRenameInstance_triggered() { if (m_selectedInstance) diff --git a/launcher/ui/MainWindow.h b/launcher/ui/MainWindow.h index 3bb20c4a4..9b38810f0 100644 --- a/launcher/ui/MainWindow.h +++ b/launcher/ui/MainWindow.h @@ -157,6 +157,7 @@ private slots: inline void on_actionExportInstance_triggered() { on_actionExportInstanceZip_triggered(); } void on_actionExportInstanceZip_triggered(); void on_actionExportInstanceMrPack_triggered(); + void on_actionExportInstanceToString_triggered(); void on_actionRenameInstance_triggered(); diff --git a/launcher/ui/MainWindow.ui b/launcher/ui/MainWindow.ui index f67fb1859..e6e52a912 100644 --- a/launcher/ui/MainWindow.ui +++ b/launcher/ui/MainWindow.ui @@ -479,6 +479,14 @@ Modrinth (mrpack) + + + + + + Text + + diff --git a/launcher/ui/dialogs/ExportModsToStringDialog.cpp b/launcher/ui/dialogs/ExportModsToStringDialog.cpp new file mode 100644 index 000000000..d08a4c70c --- /dev/null +++ b/launcher/ui/dialogs/ExportModsToStringDialog.cpp @@ -0,0 +1,119 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (c) 2023 Trial97 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "ExportModsToStringDialog.h" +#include +#include +#include +#include "minecraft/MinecraftInstance.h" +#include "minecraft/mod/ModFolderModel.h" +#include "modplatform/helpers/ExportModsToStringTask.h" +#include "ui_ExportModsToStringDialog.h" + +#include +#include +#include +#include +#include + +ExportModsToStringDialog::ExportModsToStringDialog(InstancePtr instance, QWidget* parent) + : QDialog(parent), m_template_selected(false), ui(new Ui::ExportModsToStringDialog) +{ + ui->setupUi(this); + ui->templateGroup->setDisabled(true); + + MinecraftInstance* mcInstance = dynamic_cast(instance.get()); + if (mcInstance) { + mcInstance->loaderModList()->update(); + connect(mcInstance->loaderModList().get(), &ModFolderModel::updateFinished, this, [this, mcInstance]() { + m_allMods = mcInstance->loaderModList()->allMods(); + trigger(); + }); + } + + connect(ui->formatComboBox, &QComboBox::currentIndexChanged, this, &ExportModsToStringDialog::formatChanged); + connect(ui->authorsCheckBox, &QCheckBox::stateChanged, this, &ExportModsToStringDialog::trigger); + connect(ui->versionCheckBox, &QCheckBox::stateChanged, this, &ExportModsToStringDialog::trigger); + connect(ui->urlCheckBox, &QCheckBox::stateChanged, this, &ExportModsToStringDialog::trigger); + connect(ui->templateText, &QTextEdit::textChanged, this, &ExportModsToStringDialog::trigger); + connect(ui->copyButton, &QPushButton::clicked, this, [this]() { + this->ui->finalText->selectAll(); + this->ui->finalText->copy(); + }); +} + +ExportModsToStringDialog::~ExportModsToStringDialog() +{ + delete ui; +} + +void ExportModsToStringDialog::formatChanged(int index) +{ + switch (index) { + case 0: { + ui->templateGroup->setDisabled(true); + ui->optionsGroup->setDisabled(false); + break; + } + case 1: { + ui->templateGroup->setDisabled(true); + ui->optionsGroup->setDisabled(false); + break; + } + case 2: { + ui->templateGroup->setDisabled(false); + ui->optionsGroup->setDisabled(true); + break; + } + } + trigger(); +} + +void ExportModsToStringDialog::trigger() +{ + ExportToString::Formats format; + switch (ui->formatComboBox->currentIndex()) { + case 2: { + m_template_selected = true; + ui->finalText->setPlainText(ExportToString::ExportModsToStringTask(m_allMods, ui->templateText->toPlainText())); + return; + } + case 0: { + format = ExportToString::HTML; + break; + } + case 1: { + format = ExportToString::MARKDOWN; + break; + } + } + auto opt = 0; + if (ui->authorsCheckBox->isChecked()) + opt |= ExportToString::Authors; + if (ui->versionCheckBox->isChecked()) + opt |= ExportToString::Version; + if (ui->urlCheckBox->isChecked()) + opt |= ExportToString::Url; + ui->finalText->setPlainText(ExportToString::ExportModsToStringTask(m_allMods, format, static_cast(opt))); + if (!m_template_selected) { + auto exampleLine = format == ExportToString::HTML ? "
    {name}[{version}] by {authors}
" + : "[{name}]({url})[{version}] by {authors}"; + if (ui->templateText->toPlainText() != exampleLine) + ui->templateText->setPlainText(exampleLine); + } +} diff --git a/launcher/ui/dialogs/ExportModsToStringDialog.h b/launcher/ui/dialogs/ExportModsToStringDialog.h new file mode 100644 index 000000000..7fada4d54 --- /dev/null +++ b/launcher/ui/dialogs/ExportModsToStringDialog.h @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (c) 2023 Trial97 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include +#include +#include "BaseInstance.h" +#include "minecraft/mod/Mod.h" + +namespace Ui { +class ExportModsToStringDialog; +} + +class ExportModsToStringDialog : public QDialog { + Q_OBJECT + + public: + explicit ExportModsToStringDialog(InstancePtr instance, QWidget* parent = nullptr); + ~ExportModsToStringDialog(); + + protected slots: + void formatChanged(int index); + void trigger(); + + private: + QList m_allMods; + bool m_template_selected; + Ui::ExportModsToStringDialog* ui; +}; diff --git a/launcher/ui/dialogs/ExportModsToStringDialog.ui b/launcher/ui/dialogs/ExportModsToStringDialog.ui new file mode 100644 index 000000000..4451a2785 --- /dev/null +++ b/launcher/ui/dialogs/ExportModsToStringDialog.ui @@ -0,0 +1,171 @@ + + + ExportModsToStringDialog + + + + 0 + 0 + 650 + 446 + + + + Export Modrinth Pack + + + true + + + + + + + + Settings + + + + + + QFrame::NoFrame + + + QFrame::Plain + + + 1 + + + Format + + + + + + + + HTML + + + + + Markdown + + + + + Custom + + + + + + + + Template + + + + + + + + + + + + Optional Info + + + + + + Version + + + + + + + Authors + + + + + + + URL + + + + + + + + + + + + + Result + + + + + + + 0 + 143 + + + + true + + + + + + + + + + + + + + Copy + + + + + + + QDialogButtonBox::Ok + + + + + + + + + + + buttonBox + accepted() + ExportModsToStringDialog + accept() + + + 334 + 435 + + + 324 + 206 + + + + + From b84dc8551a13ed87d09e6f8ca8b401c57d549f95 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 22 Jun 2023 16:49:19 +0300 Subject: [PATCH 024/216] Fixed trigger function Signed-off-by: Trial97 --- launcher/ui/dialogs/ExportModsToStringDialog.cpp | 12 ++++++------ launcher/ui/dialogs/ExportModsToStringDialog.h | 3 ++- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/launcher/ui/dialogs/ExportModsToStringDialog.cpp b/launcher/ui/dialogs/ExportModsToStringDialog.cpp index d08a4c70c..ae793dcb3 100644 --- a/launcher/ui/dialogs/ExportModsToStringDialog.cpp +++ b/launcher/ui/dialogs/ExportModsToStringDialog.cpp @@ -42,16 +42,16 @@ ExportModsToStringDialog::ExportModsToStringDialog(InstancePtr instance, QWidget mcInstance->loaderModList()->update(); connect(mcInstance->loaderModList().get(), &ModFolderModel::updateFinished, this, [this, mcInstance]() { m_allMods = mcInstance->loaderModList()->allMods(); - trigger(); + triggerImp(); }); } - connect(ui->formatComboBox, &QComboBox::currentIndexChanged, this, &ExportModsToStringDialog::formatChanged); + connect(ui->formatComboBox, QOverload::of(&QComboBox::currentIndexChanged), this, &ExportModsToStringDialog::formatChanged); connect(ui->authorsCheckBox, &QCheckBox::stateChanged, this, &ExportModsToStringDialog::trigger); connect(ui->versionCheckBox, &QCheckBox::stateChanged, this, &ExportModsToStringDialog::trigger); connect(ui->urlCheckBox, &QCheckBox::stateChanged, this, &ExportModsToStringDialog::trigger); - connect(ui->templateText, &QTextEdit::textChanged, this, &ExportModsToStringDialog::trigger); - connect(ui->copyButton, &QPushButton::clicked, this, [this]() { + connect(ui->templateText, &QTextEdit::textChanged, this, &ExportModsToStringDialog::triggerImp); + connect(ui->copyButton, &QPushButton::clicked, this, [this](bool) { this->ui->finalText->selectAll(); this->ui->finalText->copy(); }); @@ -81,10 +81,10 @@ void ExportModsToStringDialog::formatChanged(int index) break; } } - trigger(); + triggerImp(); } -void ExportModsToStringDialog::trigger() +void ExportModsToStringDialog::triggerImp() { ExportToString::Formats format; switch (ui->formatComboBox->currentIndex()) { diff --git a/launcher/ui/dialogs/ExportModsToStringDialog.h b/launcher/ui/dialogs/ExportModsToStringDialog.h index 7fada4d54..d195d1cec 100644 --- a/launcher/ui/dialogs/ExportModsToStringDialog.h +++ b/launcher/ui/dialogs/ExportModsToStringDialog.h @@ -36,7 +36,8 @@ class ExportModsToStringDialog : public QDialog { protected slots: void formatChanged(int index); - void trigger(); + void triggerImp(); + void trigger(int) { triggerImp(); }; private: QList m_allMods; From 836e8d2e28b4ab63e6c4189410c38ad1a7fd2718 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 22 Jun 2023 17:39:57 +0300 Subject: [PATCH 025/216] Fixed code quality Signed-off-by: Trial97 --- launcher/ui/dialogs/ExportModsToStringDialog.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/launcher/ui/dialogs/ExportModsToStringDialog.cpp b/launcher/ui/dialogs/ExportModsToStringDialog.cpp index ae793dcb3..29d69918e 100644 --- a/launcher/ui/dialogs/ExportModsToStringDialog.cpp +++ b/launcher/ui/dialogs/ExportModsToStringDialog.cpp @@ -86,7 +86,7 @@ void ExportModsToStringDialog::formatChanged(int index) void ExportModsToStringDialog::triggerImp() { - ExportToString::Formats format; + auto format = ExportToString::HTML; switch (ui->formatComboBox->currentIndex()) { case 2: { m_template_selected = true; @@ -101,6 +101,9 @@ void ExportModsToStringDialog::triggerImp() format = ExportToString::MARKDOWN; break; } + default: { + return; + } } auto opt = 0; if (ui->authorsCheckBox->isChecked()) From 9ad356d66f4c7bf1ccbbe251df800ebb1c4b67d4 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 22 Jun 2023 16:00:45 +0300 Subject: [PATCH 026/216] Added ExportModsToStringTask Signed-off-by: Trial97 --- launcher/CMakeLists.txt | 3 + .../helpers/ExportModsToStringTask.cpp | 114 ++++++++++++++++++ .../helpers/ExportModsToStringTask.h | 33 +++++ 3 files changed, 150 insertions(+) create mode 100644 launcher/modplatform/helpers/ExportModsToStringTask.cpp create mode 100644 launcher/modplatform/helpers/ExportModsToStringTask.h diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index ce2771a49..c7efdad84 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -487,6 +487,9 @@ set(API_SOURCES modplatform/helpers/HashUtils.cpp modplatform/helpers/OverrideUtils.h modplatform/helpers/OverrideUtils.cpp + + modplatform/helpers/ExportModsToStringTask.h + modplatform/helpers/ExportModsToStringTask.cpp ) set(FTB_SOURCES diff --git a/launcher/modplatform/helpers/ExportModsToStringTask.cpp b/launcher/modplatform/helpers/ExportModsToStringTask.cpp new file mode 100644 index 000000000..a105fc352 --- /dev/null +++ b/launcher/modplatform/helpers/ExportModsToStringTask.cpp @@ -0,0 +1,114 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (c) 2023 Trial97 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include "ExportModsToStringTask.h" +#include "modplatform/ModIndex.h" + +namespace ExportToString { +QString ExportModsToStringTask(QList mods, Formats format, OptionalData extraData) +{ + switch (format) { + case HTML: { + QStringList lines; + for (auto mod : mods) { + auto meta = mod->metadata(); + auto modName = mod->name(); + if (extraData & Url) { + auto url = mod->homeurl(); + if (meta != nullptr) { + url = (meta->provider == ModPlatform::ResourceProvider::FLAME ? "https://www.curseforge.com/minecraft/mc-mods/" + : "https://modrinth.com/mod/") + + meta->project_id.toString(); + } + if (!url.isEmpty()) + modName = QString("%2").arg(url, modName); + } + auto line = modName; + if (extraData & Version) { + auto ver = mod->version(); + if (ver.isEmpty() && meta != nullptr) + ver = meta->version().toString(); + if (!ver.isEmpty()) + line += QString("[%1]").arg(ver); + } + if (extraData & Authors && !mod->authors().isEmpty()) + line += " by " + mod->authors().join(", "); + lines.append(QString("
    %1
").arg(line)); + } + return QString("\n\t%1\n").arg(lines.join("\n\t")); + } + case MARKDOWN: { + QStringList lines; + for (auto mod : mods) { + auto meta = mod->metadata(); + auto modName = mod->name(); + if (extraData & Url) { + auto url = mod->homeurl(); + if (meta != nullptr) { + url = (meta->provider == ModPlatform::ResourceProvider::FLAME ? "https://www.curseforge.com/minecraft/mc-mods/" + : "https://modrinth.com/mod/") + + meta->project_id.toString(); + } + if (!url.isEmpty()) + modName = QString("[%1](%2)").arg(modName, url); + } + auto line = modName; + if (extraData & Version) { + auto ver = mod->version(); + if (ver.isEmpty() && meta != nullptr) + ver = meta->version().toString(); + if (!ver.isEmpty()) + line += QString("[%1]").arg(ver); + } + if (extraData & Authors && !mod->authors().isEmpty()) + line += " by " + mod->authors().join(", "); + lines << line; + } + return lines.join("\n"); + } + default: { + return QString("unknown format:%1").arg(format); + } + } +} + +QString ExportModsToStringTask(QList mods, QString lineTemplate) +{ + QStringList lines; + for (auto mod : mods) { + auto meta = mod->metadata(); + auto modName = mod->name(); + + auto url = mod->homeurl(); + if (meta != nullptr) { + url = (meta->provider == ModPlatform::ResourceProvider::FLAME ? "https://www.curseforge.com/minecraft/mc-mods/" + : "https://modrinth.com/mod/") + + meta->project_id.toString(); + } + auto ver = mod->version(); + if (ver.isEmpty() && meta != nullptr) + ver = meta->version().toString(); + auto authors = mod->authors().join(", "); + lines << QString(lineTemplate) + .replace("{name}", modName) + .replace("{url}", url) + .replace("{version}", ver) + .replace("{authors}", authors); + } + return lines.join("\n"); +} +} // namespace ExportToString \ No newline at end of file diff --git a/launcher/modplatform/helpers/ExportModsToStringTask.h b/launcher/modplatform/helpers/ExportModsToStringTask.h new file mode 100644 index 000000000..756c69f77 --- /dev/null +++ b/launcher/modplatform/helpers/ExportModsToStringTask.h @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (c) 2023 Trial97 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once +#include +#include +#include "minecraft/mod/Mod.h" + +namespace ExportToString { + +enum Formats { HTML, MARKDOWN }; +enum OptionalData { + Authors = 1 << 0, + Url = 1 << 1, + Version = 1 << 2, +}; +QString ExportModsToStringTask(QList mods, Formats format, OptionalData extraData); +QString ExportModsToStringTask(QList mods, QString lineTemplate); +} // namespace ExportToString From da6f846a496f70dd5339ed1bdba35842feaa1286 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 22 Jun 2023 18:11:03 +0300 Subject: [PATCH 027/216] Use slug for url Signed-off-by: Trial97 --- launcher/modplatform/helpers/ExportModsToStringTask.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/launcher/modplatform/helpers/ExportModsToStringTask.cpp b/launcher/modplatform/helpers/ExportModsToStringTask.cpp index a105fc352..c10560c1c 100644 --- a/launcher/modplatform/helpers/ExportModsToStringTask.cpp +++ b/launcher/modplatform/helpers/ExportModsToStringTask.cpp @@ -32,7 +32,7 @@ QString ExportModsToStringTask(QList mods, Formats format, OptionalData ex if (meta != nullptr) { url = (meta->provider == ModPlatform::ResourceProvider::FLAME ? "https://www.curseforge.com/minecraft/mc-mods/" : "https://modrinth.com/mod/") + - meta->project_id.toString(); + meta->slug.remove(".pw.toml"); } if (!url.isEmpty()) modName = QString("%2").arg(url, modName); @@ -61,7 +61,7 @@ QString ExportModsToStringTask(QList mods, Formats format, OptionalData ex if (meta != nullptr) { url = (meta->provider == ModPlatform::ResourceProvider::FLAME ? "https://www.curseforge.com/minecraft/mc-mods/" : "https://modrinth.com/mod/") + - meta->project_id.toString(); + meta->slug.remove(".pw.toml"); } if (!url.isEmpty()) modName = QString("[%1](%2)").arg(modName, url); From 4e07f9574af10943577726f795fc8fad249e90e4 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 22 Jun 2023 18:11:03 +0300 Subject: [PATCH 028/216] Use slug for url Signed-off-by: Trial97 --- launcher/modplatform/helpers/ExportModsToStringTask.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/launcher/modplatform/helpers/ExportModsToStringTask.cpp b/launcher/modplatform/helpers/ExportModsToStringTask.cpp index a105fc352..c10560c1c 100644 --- a/launcher/modplatform/helpers/ExportModsToStringTask.cpp +++ b/launcher/modplatform/helpers/ExportModsToStringTask.cpp @@ -32,7 +32,7 @@ QString ExportModsToStringTask(QList mods, Formats format, OptionalData ex if (meta != nullptr) { url = (meta->provider == ModPlatform::ResourceProvider::FLAME ? "https://www.curseforge.com/minecraft/mc-mods/" : "https://modrinth.com/mod/") + - meta->project_id.toString(); + meta->slug.remove(".pw.toml"); } if (!url.isEmpty()) modName = QString("%2").arg(url, modName); @@ -61,7 +61,7 @@ QString ExportModsToStringTask(QList mods, Formats format, OptionalData ex if (meta != nullptr) { url = (meta->provider == ModPlatform::ResourceProvider::FLAME ? "https://www.curseforge.com/minecraft/mc-mods/" : "https://modrinth.com/mod/") + - meta->project_id.toString(); + meta->slug.remove(".pw.toml"); } if (!url.isEmpty()) modName = QString("[%1](%2)").arg(modName, url); From 58321f34915bd22ab8a2c195b64af3006d962be9 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 22 Jun 2023 20:03:44 +0300 Subject: [PATCH 029/216] Added curseforge export Signed-off-by: Trial97 --- launcher/CMakeLists.txt | 2 + .../modplatform/flame/FlamePackExportTask.cpp | 223 ++++++++++++++++++ .../modplatform/flame/FlamePackExportTask.h | 74 ++++++ launcher/ui/MainWindow.cpp | 9 + launcher/ui/MainWindow.h | 1 + launcher/ui/MainWindow.ui | 8 + launcher/ui/dialogs/ExportMrPackDialog.cpp | 28 ++- launcher/ui/dialogs/ExportMrPackDialog.h | 6 +- 8 files changed, 341 insertions(+), 10 deletions(-) create mode 100644 launcher/modplatform/flame/FlamePackExportTask.cpp create mode 100644 launcher/modplatform/flame/FlamePackExportTask.h diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index c7efdad84..df6c90129 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -517,6 +517,8 @@ set(FLAME_SOURCES modplatform/flame/FlameCheckUpdate.h modplatform/flame/FlameInstanceCreationTask.h modplatform/flame/FlameInstanceCreationTask.cpp + modplatform/flame/FlamePackExportTask.h + modplatform/flame/FlamePackExportTask.cpp ) set(MODRINTH_SOURCES diff --git a/launcher/modplatform/flame/FlamePackExportTask.cpp b/launcher/modplatform/flame/FlamePackExportTask.cpp new file mode 100644 index 000000000..1ae13f72c --- /dev/null +++ b/launcher/modplatform/flame/FlamePackExportTask.cpp @@ -0,0 +1,223 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (c) 2023 Trial97 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "FlamePackExportTask.h" +#include +#include + +#include +#include +#include +#include +#include "Json.h" +#include "MMCZip.h" +#include "minecraft/PackProfile.h" +#include "minecraft/mod/ModFolderModel.h" +#include "modplatform/helpers/ExportModsToStringTask.h" + +const QStringList FlamePackExportTask::PREFIXES({ "mods/", "coremods/", "resourcepacks/", "texturepacks/", "shaderpacks/" }); +const QStringList FlamePackExportTask::FILE_EXTENSIONS({ "jar", "litemod", "zip" }); +const QString FlamePackExportTask::TEMPLATE = "
  • {name}({authors})
  • "; + +FlamePackExportTask::FlamePackExportTask(const QString& name, + const QString& version, + const QVariant& projectID, + InstancePtr instance, + const QString& output, + MMCZip::FilterFunction filter) + : name(name) + , version(version) + , projectID(projectID) + , instance(instance) + , mcInstance(dynamic_cast(instance.get())) + , gameRoot(instance->gameRoot()) + , output(output) + , filter(filter) +{} + +void FlamePackExportTask::executeTask() +{ + setStatus(tr("Searching for files...")); + setProgress(0, 0); + collectFiles(); +} + +bool FlamePackExportTask::abort() +{ + if (task != nullptr) { + task->abort(); + task = nullptr; + emitAborted(); + return true; + } + + if (buildZipFuture.isRunning()) { + buildZipFuture.cancel(); + // NOTE: Here we don't do `emitAborted()` because it will be done when `buildZipFuture` actually cancels, which may not occur + // immediately. + return true; + } + + return false; +} + +void FlamePackExportTask::collectFiles() +{ + setAbortable(false); + QCoreApplication::processEvents(); + + files.clear(); + if (!MMCZip::collectFileListRecursively(instance->gameRoot(), nullptr, &files, filter)) { + emitFailed(tr("Could not search for files")); + return; + } + + resolvedFiles.clear(); + + mcInstance->loaderModList()->update(); + connect(mcInstance->loaderModList().get(), &ModFolderModel::updateFinished, this, [this]() { + mods = mcInstance->loaderModList()->allMods(); + buildZip(); + }); +} + +void FlamePackExportTask::buildZip() +{ + setStatus(tr("Adding files...")); + + buildZipFuture = QtConcurrent::run(QThreadPool::globalInstance(), [this]() { + QuaZip zip(output); + if (!zip.open(QuaZip::mdCreate)) { + QFile::remove(output); + return BuildZipResult(tr("Could not create file")); + } + + if (buildZipFuture.isCanceled()) + return BuildZipResult(); + + QuaZipFile indexFile(&zip); + if (!indexFile.open(QIODevice::WriteOnly, QuaZipNewInfo("manifest.json"))) { + QFile::remove(output); + return BuildZipResult(tr("Could not create index")); + } + indexFile.write(generateIndex()); + + QuaZipFile modlist(&zip); + if (!modlist.open(QIODevice::WriteOnly, QuaZipNewInfo("modlist.html"))) { + QFile::remove(output); + return BuildZipResult(tr("Could not create index")); + } + QString content = ExportToString::ExportModsToStringTask(mods, TEMPLATE); + content = "
      " + content + "
    "; + modlist.write(content.toUtf8()); + + size_t progress = 0; + for (const QFileInfo& file : files) { + if (buildZipFuture.isCanceled()) { + QFile::remove(output); + return BuildZipResult(); + } + + setProgress(progress, files.length()); + const QString relative = gameRoot.relativeFilePath(file.absoluteFilePath()); + if (!resolvedFiles.contains(relative) && !JlCompress::compressFile(&zip, file.absoluteFilePath(), "overrides/" + relative)) { + QFile::remove(output); + return BuildZipResult(tr("Could not read and compress %1").arg(relative)); + } + progress++; + } + + zip.close(); + + if (zip.getZipError() != 0) { + QFile::remove(output); + return BuildZipResult(tr("A zip error occurred")); + } + + return BuildZipResult(); + }); + connect(&buildZipWatcher, &QFutureWatcher::finished, this, &FlamePackExportTask::finish); + buildZipWatcher.setFuture(buildZipFuture); +} + +void FlamePackExportTask::finish() +{ + if (buildZipFuture.isCanceled()) + emitAborted(); + else { + const BuildZipResult result = buildZipFuture.result(); + if (result.has_value()) + emitFailed(result.value()); + else + emitSucceeded(); + } +} + +QByteArray FlamePackExportTask::generateIndex() +{ + QJsonObject obj; + obj["manifestType"] = "minecraftModpack"; + obj["manifestVersion"] = 1; + obj["name"] = name; + obj["version"] = version; + obj["author"] = author; + obj["projectID"] = projectID.toInt(); + obj["overrides"] = "overrides"; + if (mcInstance) { + QJsonObject version; + auto profile = mcInstance->getPackProfile(); + // collect all supported components + const ComponentPtr minecraft = profile->getComponent("net.minecraft"); + const ComponentPtr quilt = profile->getComponent("org.quiltmc.quilt-loader"); + const ComponentPtr fabric = profile->getComponent("net.fabricmc.fabric-loader"); + const ComponentPtr forge = profile->getComponent("net.minecraftforge"); + + // convert all available components to mrpack dependencies + if (minecraft != nullptr) + version["version"] = minecraft->m_version; + + QJsonObject loader; + if (quilt != nullptr) + loader["id"] = quilt->getName(); + else if (fabric != nullptr) + loader["id"] = fabric->getName(); + else if (forge != nullptr) + loader["id"] = forge->getName(); + loader["primary"] = true; + + version["modLoaders"] = QJsonArray({ loader }); + obj["minecraft"] = version; + } + + QJsonArray files; + QMapIterator iterator(resolvedFiles); + while (iterator.hasNext()) { + iterator.next(); + + const ResolvedFile& value = iterator.value(); + + QJsonObject file; + file["projectID"] = value.projectID.toInt(); + file["fileID"] = value.fileID.toInt(); + file["required"] = value.required; + files << file; + } + obj["files"] = files; + + return QJsonDocument(obj).toJson(QJsonDocument::Compact); +} diff --git a/launcher/modplatform/flame/FlamePackExportTask.h b/launcher/modplatform/flame/FlamePackExportTask.h new file mode 100644 index 000000000..83927099a --- /dev/null +++ b/launcher/modplatform/flame/FlamePackExportTask.h @@ -0,0 +1,74 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (c) 2023 Trial97 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include +#include +#include "BaseInstance.h" +#include "MMCZip.h" +#include "minecraft/MinecraftInstance.h" +#include "tasks/Task.h" + +class FlamePackExportTask : public Task { + public: + FlamePackExportTask(const QString& name, + const QString& version, + const QVariant& projectID, + InstancePtr instance, + const QString& output, + MMCZip::FilterFunction filter); + + protected: + void executeTask() override; + bool abort() override; + + private: + struct ResolvedFile { + QVariant projectID, fileID; + bool required; + }; + + static const QStringList PREFIXES; + static const QStringList FILE_EXTENSIONS; + static const QString TEMPLATE; + + // inputs + const QString name, version, author; + const QVariant projectID; + const InstancePtr instance; + MinecraftInstance* mcInstance; + const QDir gameRoot; + const QString output; + const MMCZip::FilterFunction filter; + + typedef std::optional BuildZipResult; + + QFileInfoList files; + QMap resolvedFiles; + Task::Ptr task; + QFuture buildZipFuture; + QFutureWatcher buildZipWatcher; + QList mods; + + void collectFiles(); + void buildZip(); + void finish(); + + QByteArray generateIndex(); +}; diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp index e04011cab..0027d1804 100644 --- a/launcher/ui/MainWindow.cpp +++ b/launcher/ui/MainWindow.cpp @@ -205,6 +205,7 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi auto exportInstanceMenu = new QMenu(this); exportInstanceMenu->addAction(ui->actionExportInstanceZip); exportInstanceMenu->addAction(ui->actionExportInstanceMrPack); + exportInstanceMenu->addAction(ui->actionExportInstanceFlamePack); ui->actionExportInstance->setMenu(exportInstanceMenu); } @@ -1416,6 +1417,14 @@ void MainWindow::on_actionExportInstanceMrPack_triggered() } } +void MainWindow::on_actionExportInstanceFlamePack_triggered() +{ + if (m_selectedInstance) { + ExportMrPackDialog dlg(m_selectedInstance, this, ModPlatform::ResourceProvider::FLAME); + dlg.exec(); + } +} + void MainWindow::on_actionRenameInstance_triggered() { if (m_selectedInstance) diff --git a/launcher/ui/MainWindow.h b/launcher/ui/MainWindow.h index 3bb20c4a4..5f74b501c 100644 --- a/launcher/ui/MainWindow.h +++ b/launcher/ui/MainWindow.h @@ -157,6 +157,7 @@ private slots: inline void on_actionExportInstance_triggered() { on_actionExportInstanceZip_triggered(); } void on_actionExportInstanceZip_triggered(); void on_actionExportInstanceMrPack_triggered(); + void on_actionExportInstanceFlamePack_triggered(); void on_actionRenameInstance_triggered(); diff --git a/launcher/ui/MainWindow.ui b/launcher/ui/MainWindow.ui index f67fb1859..f7e93f483 100644 --- a/launcher/ui/MainWindow.ui +++ b/launcher/ui/MainWindow.ui @@ -479,6 +479,14 @@ Modrinth (mrpack)
    + + + + + + Curseforge (zip) + + diff --git a/launcher/ui/dialogs/ExportMrPackDialog.cpp b/launcher/ui/dialogs/ExportMrPackDialog.cpp index 561b92e40..16ef526a8 100644 --- a/launcher/ui/dialogs/ExportMrPackDialog.cpp +++ b/launcher/ui/dialogs/ExportMrPackDialog.cpp @@ -18,6 +18,8 @@ #include "ExportMrPackDialog.h" #include "minecraft/mod/ModFolderModel.h" +#include "modplatform/ModIndex.h" +#include "modplatform/flame/FlamePackExportTask.h" #include "ui/dialogs/CustomMessageBox.h" #include "ui/dialogs/ProgressDialog.h" #include "ui_ExportMrPackDialog.h" @@ -32,12 +34,15 @@ #include "MMCZip.h" #include "modplatform/modrinth/ModrinthPackExportTask.h" -ExportMrPackDialog::ExportMrPackDialog(InstancePtr instance, QWidget* parent) - : QDialog(parent), instance(instance), ui(new Ui::ExportMrPackDialog) +ExportMrPackDialog::ExportMrPackDialog(InstancePtr instance, QWidget* parent, ModPlatform::ResourceProvider provider) + : QDialog(parent), instance(instance), ui(new Ui::ExportMrPackDialog), m_provider(provider) { ui->setupUi(this); ui->name->setText(instance->name()); - ui->summary->setText(instance->notes().split(QRegularExpression("\\r?\\n"))[0]); + if (m_provider == ModPlatform::ResourceProvider::MODRINTH) + ui->summary->setText(instance->notes().split(QRegularExpression("\\r?\\n"))[0]); + else + ui->summaryLabel->setText("ProjectID"); // ensure a valid pack is generated // the name and version fields mustn't be empty @@ -97,20 +102,25 @@ void ExportMrPackDialog::done(int result) if (output.isEmpty()) return; + Task* task; + if (m_provider == ModPlatform::ResourceProvider::MODRINTH) + task = new ModrinthPackExportTask(ui->name->text(), ui->version->text(), ui->summary->text(), instance, output, + [this](const QString& path) { return proxy->blockedPaths().covers(path); }); + else + task = new FlamePackExportTask(ui->name->text(), ui->version->text(), ui->summary->text(), instance, output, + [this](const QString& path) { return proxy->blockedPaths().covers(path); }); - ModrinthPackExportTask task(ui->name->text(), ui->version->text(), ui->summary->text(), instance, output, - [this](const QString& path) { return proxy->blockedPaths().covers(path); }); - - connect(&task, &Task::failed, + connect(task, &Task::failed, [this](const QString reason) { CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->show(); }); - connect(&task, &Task::aborted, [this] { + connect(task, &Task::aborted, [this] { CustomMessageBox::selectable(this, tr("Task aborted"), tr("The task has been aborted by the user."), QMessageBox::Information) ->show(); }); + connect(task, &Task::finished, [task] { task->deleteLater(); }); ProgressDialog progress(this); progress.setSkipButton(true, tr("Abort")); - if (progress.execWithTask(&task) != QDialog::Accepted) + if (progress.execWithTask(task) != QDialog::Accepted) return; } diff --git a/launcher/ui/dialogs/ExportMrPackDialog.h b/launcher/ui/dialogs/ExportMrPackDialog.h index 1c70c4ae1..858a31bf9 100644 --- a/launcher/ui/dialogs/ExportMrPackDialog.h +++ b/launcher/ui/dialogs/ExportMrPackDialog.h @@ -22,6 +22,7 @@ #include "BaseInstance.h" #include "FastFileIconProvider.h" #include "FileIgnoreProxy.h" +#include "modplatform/ModIndex.h" namespace Ui { class ExportMrPackDialog; @@ -31,7 +32,9 @@ class ExportMrPackDialog : public QDialog { Q_OBJECT public: - explicit ExportMrPackDialog(InstancePtr instance, QWidget* parent = nullptr); + explicit ExportMrPackDialog(InstancePtr instance, + QWidget* parent = nullptr, + ModPlatform::ResourceProvider provider = ModPlatform::ResourceProvider::MODRINTH); ~ExportMrPackDialog(); void done(int result) override; @@ -42,4 +45,5 @@ class ExportMrPackDialog : public QDialog { Ui::ExportMrPackDialog* ui; FileIgnoreProxy* proxy; FastFileIconProvider icons; + const ModPlatform::ResourceProvider m_provider; }; From 377f27b16fbd8adb21d4907101d195ef6f3a9e88 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 22 Jun 2023 20:04:06 +0300 Subject: [PATCH 030/216] Updated slug for url Signed-off-by: Trial97 --- launcher/modplatform/helpers/ExportModsToStringTask.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/modplatform/helpers/ExportModsToStringTask.cpp b/launcher/modplatform/helpers/ExportModsToStringTask.cpp index c10560c1c..e7be5ce13 100644 --- a/launcher/modplatform/helpers/ExportModsToStringTask.cpp +++ b/launcher/modplatform/helpers/ExportModsToStringTask.cpp @@ -97,7 +97,7 @@ QString ExportModsToStringTask(QList mods, QString lineTemplate) if (meta != nullptr) { url = (meta->provider == ModPlatform::ResourceProvider::FLAME ? "https://www.curseforge.com/minecraft/mc-mods/" : "https://modrinth.com/mod/") + - meta->project_id.toString(); + meta->slug.remove(".pw.toml"); } auto ver = mod->version(); if (ver.isEmpty() && meta != nullptr) From 3c9c39cb890252f94d0c50caa00de5439881d7f6 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 22 Jun 2023 20:04:06 +0300 Subject: [PATCH 031/216] Updated slug for url Signed-off-by: Trial97 --- launcher/modplatform/helpers/ExportModsToStringTask.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/modplatform/helpers/ExportModsToStringTask.cpp b/launcher/modplatform/helpers/ExportModsToStringTask.cpp index c10560c1c..e7be5ce13 100644 --- a/launcher/modplatform/helpers/ExportModsToStringTask.cpp +++ b/launcher/modplatform/helpers/ExportModsToStringTask.cpp @@ -97,7 +97,7 @@ QString ExportModsToStringTask(QList mods, QString lineTemplate) if (meta != nullptr) { url = (meta->provider == ModPlatform::ResourceProvider::FLAME ? "https://www.curseforge.com/minecraft/mc-mods/" : "https://modrinth.com/mod/") + - meta->project_id.toString(); + meta->slug.remove(".pw.toml"); } auto ver = mod->version(); if (ver.isEmpty() && meta != nullptr) From 049b02cee46358a3d1dd13769e2c6f4ba27bc55e Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 22 Jun 2023 21:06:01 +0300 Subject: [PATCH 032/216] finished up the curesforge export Signed-off-by: Trial97 --- .../modplatform/flame/FlamePackExportTask.cpp | 28 +++++++++---------- .../modplatform/flame/FlamePackExportTask.h | 10 ++----- launcher/ui/dialogs/ExportMrPackDialog.cpp | 20 +++++++++---- launcher/ui/dialogs/ExportMrPackDialog.ui | 14 ++++++++-- 4 files changed, 42 insertions(+), 30 deletions(-) diff --git a/launcher/modplatform/flame/FlamePackExportTask.cpp b/launcher/modplatform/flame/FlamePackExportTask.cpp index 1ae13f72c..4ac2c8ab8 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.cpp +++ b/launcher/modplatform/flame/FlamePackExportTask.cpp @@ -28,20 +28,21 @@ #include "MMCZip.h" #include "minecraft/PackProfile.h" #include "minecraft/mod/ModFolderModel.h" +#include "modplatform/ModIndex.h" #include "modplatform/helpers/ExportModsToStringTask.h" -const QStringList FlamePackExportTask::PREFIXES({ "mods/", "coremods/", "resourcepacks/", "texturepacks/", "shaderpacks/" }); -const QStringList FlamePackExportTask::FILE_EXTENSIONS({ "jar", "litemod", "zip" }); const QString FlamePackExportTask::TEMPLATE = "
  • {name}({authors})
  • "; FlamePackExportTask::FlamePackExportTask(const QString& name, const QString& version, + const QString& author, const QVariant& projectID, InstancePtr instance, const QString& output, MMCZip::FilterFunction filter) : name(name) , version(version) + , author(author) , projectID(projectID) , instance(instance) , mcInstance(dynamic_cast(instance.get())) @@ -193,28 +194,27 @@ QByteArray FlamePackExportTask::generateIndex() QJsonObject loader; if (quilt != nullptr) - loader["id"] = quilt->getName(); + loader["id"] = "quilt-" + quilt->getVersion(); else if (fabric != nullptr) - loader["id"] = fabric->getName(); + loader["id"] = "fabric-" + fabric->getVersion(); else if (forge != nullptr) - loader["id"] = forge->getName(); + loader["id"] = "forge-" + forge->getVersion(); loader["primary"] = true; - version["modLoaders"] = QJsonArray({ loader }); obj["minecraft"] = version; } QJsonArray files; - QMapIterator iterator(resolvedFiles); - while (iterator.hasNext()) { - iterator.next(); - - const ResolvedFile& value = iterator.value(); + for (auto mod : mods) { + auto meta = mod->metadata(); + if (meta == nullptr || meta->provider != ModPlatform::ResourceProvider::FLAME) + continue; + resolvedFiles[gameRoot.relativeFilePath(mod->fileinfo().absoluteFilePath())] = {}; QJsonObject file; - file["projectID"] = value.projectID.toInt(); - file["fileID"] = value.fileID.toInt(); - file["required"] = value.required; + file["projectID"] = meta->project_id.toInt(); + file["fileID"] = meta->file_id.toInt(); + file["required"] = true; files << file; } obj["files"] = files; diff --git a/launcher/modplatform/flame/FlamePackExportTask.h b/launcher/modplatform/flame/FlamePackExportTask.h index 83927099a..c3cda9267 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.h +++ b/launcher/modplatform/flame/FlamePackExportTask.h @@ -29,6 +29,7 @@ class FlamePackExportTask : public Task { public: FlamePackExportTask(const QString& name, const QString& version, + const QString& author, const QVariant& projectID, InstancePtr instance, const QString& output, @@ -39,13 +40,6 @@ class FlamePackExportTask : public Task { bool abort() override; private: - struct ResolvedFile { - QVariant projectID, fileID; - bool required; - }; - - static const QStringList PREFIXES; - static const QStringList FILE_EXTENSIONS; static const QString TEMPLATE; // inputs @@ -60,7 +54,7 @@ class FlamePackExportTask : public Task { typedef std::optional BuildZipResult; QFileInfoList files; - QMap resolvedFiles; + QMap resolvedFiles; Task::Ptr task; QFuture buildZipFuture; QFutureWatcher buildZipWatcher; diff --git a/launcher/ui/dialogs/ExportMrPackDialog.cpp b/launcher/ui/dialogs/ExportMrPackDialog.cpp index 16ef526a8..aaa528aa1 100644 --- a/launcher/ui/dialogs/ExportMrPackDialog.cpp +++ b/launcher/ui/dialogs/ExportMrPackDialog.cpp @@ -39,10 +39,13 @@ ExportMrPackDialog::ExportMrPackDialog(InstancePtr instance, QWidget* parent, Mo { ui->setupUi(this); ui->name->setText(instance->name()); - if (m_provider == ModPlatform::ResourceProvider::MODRINTH) + if (m_provider == ModPlatform::ResourceProvider::MODRINTH) { ui->summary->setText(instance->notes().split(QRegularExpression("\\r?\\n"))[0]); - else + ui->author->hide(); + ui->authorLabel->hide(); + } else { ui->summaryLabel->setText("ProjectID"); + } // ensure a valid pack is generated // the name and version fields mustn't be empty @@ -96,9 +99,14 @@ void ExportMrPackDialog::done(int result) { if (result == Accepted) { const QString filename = FS::RemoveInvalidFilenameChars(ui->name->text()); - const QString output = QFileDialog::getSaveFileName(this, tr("Export %1").arg(ui->name->text()), - FS::PathCombine(QDir::homePath(), filename + ".mrpack"), - "Modrinth pack (*.mrpack *.zip)", nullptr); + QString output; + if (m_provider == ModPlatform::ResourceProvider::MODRINTH) + output = QFileDialog::getSaveFileName(this, tr("Export %1").arg(ui->name->text()), + FS::PathCombine(QDir::homePath(), filename + ".mrpack"), "Modrinth pack (*.mrpack *.zip)", + nullptr); + else + output = QFileDialog::getSaveFileName(this, tr("Export %1").arg(ui->name->text()), + FS::PathCombine(QDir::homePath(), filename + ".zip"), "Curseforge pack (*.zip)", nullptr); if (output.isEmpty()) return; @@ -107,7 +115,7 @@ void ExportMrPackDialog::done(int result) task = new ModrinthPackExportTask(ui->name->text(), ui->version->text(), ui->summary->text(), instance, output, [this](const QString& path) { return proxy->blockedPaths().covers(path); }); else - task = new FlamePackExportTask(ui->name->text(), ui->version->text(), ui->summary->text(), instance, output, + task = new FlamePackExportTask(ui->name->text(), ui->version->text(), ui->author->text(), ui->summary->text(), instance, output, [this](const QString& path) { return proxy->blockedPaths().covers(path); }); connect(task, &Task::failed, diff --git a/launcher/ui/dialogs/ExportMrPackDialog.ui b/launcher/ui/dialogs/ExportMrPackDialog.ui index 9a7897378..59ecb17c0 100644 --- a/launcher/ui/dialogs/ExportMrPackDialog.ui +++ b/launcher/ui/dialogs/ExportMrPackDialog.ui @@ -24,7 +24,7 @@
    - + Summary @@ -41,7 +41,7 @@ - + Version @@ -57,6 +57,16 @@ + + + + Author + + + + + + From 85495c794de2b7c9ae64bbf43156b3e4e6ecfed0 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 22 Jun 2023 21:12:02 +0300 Subject: [PATCH 033/216] changed map tipe Signed-off-by: Trial97 --- launcher/modplatform/flame/FlamePackExportTask.cpp | 2 +- launcher/modplatform/flame/FlamePackExportTask.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/launcher/modplatform/flame/FlamePackExportTask.cpp b/launcher/modplatform/flame/FlamePackExportTask.cpp index 4ac2c8ab8..6114f1b16 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.cpp +++ b/launcher/modplatform/flame/FlamePackExportTask.cpp @@ -209,7 +209,7 @@ QByteArray FlamePackExportTask::generateIndex() auto meta = mod->metadata(); if (meta == nullptr || meta->provider != ModPlatform::ResourceProvider::FLAME) continue; - resolvedFiles[gameRoot.relativeFilePath(mod->fileinfo().absoluteFilePath())] = {}; + resolvedFiles[gameRoot.relativeFilePath(mod->fileinfo().absoluteFilePath())] = true; QJsonObject file; file["projectID"] = meta->project_id.toInt(); diff --git a/launcher/modplatform/flame/FlamePackExportTask.h b/launcher/modplatform/flame/FlamePackExportTask.h index c3cda9267..370cd67e4 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.h +++ b/launcher/modplatform/flame/FlamePackExportTask.h @@ -54,7 +54,7 @@ class FlamePackExportTask : public Task { typedef std::optional BuildZipResult; QFileInfoList files; - QMap resolvedFiles; + QMap resolvedFiles; Task::Ptr task; QFuture buildZipFuture; QFutureWatcher buildZipWatcher; From bf95cfb30eee52f23d0279284f70931b2c968dd3 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 23 Jun 2023 01:37:28 +0300 Subject: [PATCH 034/216] Added CatPacks Signed-off-by: Trial97 --- launcher/Application.cpp | 12 +- launcher/Application.h | 9 +- launcher/CMakeLists.txt | 2 + launcher/ui/MainWindow.cpp | 4 +- launcher/ui/setupwizard/ThemeWizardPage.cpp | 2 +- launcher/ui/themes/CatPack.cpp | 109 ++++++++++++++++++ launcher/ui/themes/CatPack.h | 98 ++++++++++++++++ launcher/ui/themes/ThemeManager.cpp | 82 ++++++++++--- launcher/ui/themes/ThemeManager.h | 15 ++- .../ui/widgets/ThemeCustomizationWidget.cpp | 17 ++- .../ui/widgets/ThemeCustomizationWidget.h | 34 +++--- 11 files changed, 331 insertions(+), 53 deletions(-) create mode 100644 launcher/ui/themes/CatPack.cpp create mode 100644 launcher/ui/themes/CatPack.h diff --git a/launcher/Application.cpp b/launcher/Application.cpp index 724e6e44d..d8ac2168d 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -1173,7 +1173,17 @@ QIcon Application::getThemedIcon(const QString& name) return QIcon::fromTheme(name); } -bool Application::openJsonEditor(const QString &filename) +QList Application::getValidCatPacks() +{ + return m_themeManager->getValidCatPacks(); +} + +QString Application::getCatPack(QString catName) +{ + return m_themeManager->getCatPack(catName); +} + +bool Application::openJsonEditor(const QString& filename) { const QString file = QDir::current().absoluteFilePath(filename); if (m_settings->get("JsonEditor").toString().isEmpty()) diff --git a/launcher/Application.h b/launcher/Application.h index ced0af17d..55b01cd49 100644 --- a/launcher/Application.h +++ b/launcher/Application.h @@ -48,6 +48,7 @@ #include #include "minecraft/launch/MinecraftServerTarget.h" +#include "ui/themes/CatPack.h" class LaunchController; class LocalPeer; @@ -126,9 +127,11 @@ public: void setApplicationTheme(const QString& name); - shared_qobject_ptr updater() { - return m_updater; - } + QList getValidCatPacks(); + + QString getCatPack(QString catName = ""); + + shared_qobject_ptr updater() { return m_updater; } void triggerUpdateCheck(); diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index ce2771a49..4d0f7d06e 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -755,6 +755,8 @@ SET(LAUNCHER_SOURCES ui/themes/SystemTheme.h ui/themes/ThemeManager.cpp ui/themes/ThemeManager.h + ui/themes/CatPack.cpp + ui/themes/CatPack.h # Processes LaunchController.h diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp index e04011cab..8e1b56136 100644 --- a/launcher/ui/MainWindow.cpp +++ b/launcher/ui/MainWindow.cpp @@ -924,14 +924,14 @@ void MainWindow::setCatBackground(bool enabled) view->setStyleSheet(QString(R"( InstanceView { - background-image: url(:/backgrounds/%1); + background-image: url(%1); background-attachment: fixed; background-clip: padding; background-position: bottom right; background-repeat: none; background-color:palette(base); })") - .arg(ThemeManager::getCatImage())); + .arg(APPLICATION->getCatPack())); } else { view->setStyleSheet(QString()); } diff --git a/launcher/ui/setupwizard/ThemeWizardPage.cpp b/launcher/ui/setupwizard/ThemeWizardPage.cpp index 42826aba1..282a01acb 100644 --- a/launcher/ui/setupwizard/ThemeWizardPage.cpp +++ b/launcher/ui/setupwizard/ThemeWizardPage.cpp @@ -61,7 +61,7 @@ void ThemeWizardPage::updateIcons() void ThemeWizardPage::updateCat() { qDebug() << "Setting Cat"; - ui->catImagePreviewButton->setIcon(QIcon(QString(R"(:/backgrounds/%1)").arg(ThemeManager::getCatImage()))); + ui->catImagePreviewButton->setIcon(QIcon(QString(R"(%1)").arg(APPLICATION->getCatPack()))); } void ThemeWizardPage::retranslate() diff --git a/launcher/ui/themes/CatPack.cpp b/launcher/ui/themes/CatPack.cpp new file mode 100644 index 000000000..e74b9709a --- /dev/null +++ b/launcher/ui/themes/CatPack.cpp @@ -0,0 +1,109 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (c) 2023 Trial97 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Copyright 2013-2021 MultiMC Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ui/themes/CatPack.h" +#include +#include +#include +#include +#include +#include +#include +#include "FileSystem.h" +#include "Json.h" +#include "ui/themes/ThemeManager.h" + +QString BasicCatPack::path() +{ + const QDateTime now = QDateTime::currentDateTime(); + const QDateTime birthday(QDate(now.date().year(), 11, 30), QTime(0, 0)); + const QDateTime xmas(QDate(now.date().year(), 12, 25), QTime(0, 0)); + const QDateTime halloween(QDate(now.date().year(), 10, 31), QTime(0, 0)); + + QString cat = QString(":/backgrounds/%1").arg(m_id); + if (std::abs(now.daysTo(xmas)) <= 4) { + cat += "-xmas"; + } else if (std::abs(now.daysTo(halloween)) <= 4) { + cat += "-spooky"; + } else if (std::abs(now.daysTo(birthday)) <= 12) { + cat += "-bday"; + } + return cat; +} + +JsonCatPack::JsonCatPack(QFileInfo& manifestInfo) : BasicCatPack(manifestInfo.dir().dirName()) +{ + QString path = FS::PathCombine("catpacks", m_id); + + if (!FS::ensureFolderPathExists(path)) { + themeWarningLog() << "couldn't create folder for catpack!"; + return; + } + + if (manifestInfo.exists() && manifestInfo.isFile()) { + try { + auto doc = Json::requireDocument(manifestInfo.absoluteFilePath(), "CatPack JSON file"); + const auto root = doc.object(); + m_name = Json::requireString(root, "name", "Catpack name"); + m_id = Json::requireString(root, "id", "Catpack ID"); + m_defaultPath = FS::PathCombine(path, Json::requireString(root, "default", "Deafult Cat")); + auto variants = Json::ensureArray(root, "variants", QJsonArray(), "Catpack Variants"); + for (auto v : variants) { + auto variant = Json::ensureObject(v, QJsonObject(), "Cat variant"); + m_variants << Variant{ FS::PathCombine(path, Json::requireString(variant, "path", "Variant path")), + date(Json::requireString(variant, "startTime", "Variant startTime")), + date(Json::requireString(variant, "endTime", "Variant endTime")) }; + } + + } catch (const Exception& e) { + themeWarningLog() << "Couldn't load catpack json: " << e.cause(); + return; + } + } else { + themeDebugLog() << "No catpack json present."; + } +} + +QString JsonCatPack::path() +{ + const QDateTime now = QDateTime::currentDateTime(); + for (auto var : m_variants) { + QDateTime startDate(QDate(now.date().year(), var.startTime.mounth, var.startTime.day), QTime(0, 0)); + QDateTime endDate(QDate(now.date().year(), var.endTime.mounth, var.endTime.day), QTime(0, 0)); + if (startDate.daysTo(now) > 0 && now.daysTo(endDate) > 0) + return var.path; + } + return m_defaultPath; +} diff --git a/launcher/ui/themes/CatPack.h b/launcher/ui/themes/CatPack.h new file mode 100644 index 000000000..d9010b8ea --- /dev/null +++ b/launcher/ui/themes/CatPack.h @@ -0,0 +1,98 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (c) 2023 Trial97 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Copyright 2013-2021 MultiMC Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include +#include +#include + +class CatPack { + public: + virtual ~CatPack() {} + virtual QString id() = 0; + virtual QString name() = 0; + virtual QString path() = 0; +}; + +class BasicCatPack : public CatPack { + public: + BasicCatPack(QString id, QString name) : m_id(id), m_name(name) {} + BasicCatPack(QString id) : BasicCatPack(id, id) {} + virtual QString id() { return m_id; }; + virtual QString name() { return m_name; }; + virtual QString path(); + + protected: + QString m_id; + QString m_name; +}; + +class FileCatPack : public BasicCatPack { + public: + FileCatPack(QString id, QFileInfo& fileInfo) : BasicCatPack(id), m_path(fileInfo.absoluteFilePath()) {} + FileCatPack(QFileInfo& fileInfo) : FileCatPack(fileInfo.baseName(), fileInfo) {} + virtual QString path() { return m_path; } + + private: + QString m_path; +}; + +class JsonCatPack : public BasicCatPack { + public: + struct date { + date(QString d) + { + auto sp = d.split("-"); + day = sp[0].toInt(); + if (sp.length() >= 2) + mounth = sp[1].length(); + } + int mounth; + int day; + }; + struct Variant { + QString path; + date startTime; + date endTime; + }; + JsonCatPack(QFileInfo& manifestInfo); + virtual QString path(); + + private: + QString m_defaultPath; + QList m_variants; +}; diff --git a/launcher/ui/themes/ThemeManager.cpp b/launcher/ui/themes/ThemeManager.cpp index 94ac8a245..bfd0550a8 100644 --- a/launcher/ui/themes/ThemeManager.cpp +++ b/launcher/ui/themes/ThemeManager.cpp @@ -22,6 +22,7 @@ #include #include #include "ui/themes/BrightTheme.h" +#include "ui/themes/CatPack.h" #include "ui/themes/CustomTheme.h" #include "ui/themes/DarkTheme.h" #include "ui/themes/SystemTheme.h" @@ -32,6 +33,7 @@ ThemeManager::ThemeManager(MainWindow* mainWindow) { m_mainWindow = mainWindow; initializeThemes(); + initializeCatPacks(); } /// @brief Adds the Theme to the list of themes @@ -111,6 +113,16 @@ QList ThemeManager::getValidApplicationThemes() return ret; } +QList ThemeManager::getValidCatPacks() +{ + QList ret; + ret.reserve(m_catPacks.size()); + for (auto&& [id, theme] : m_catPacks) { + ret.append(theme.get()); + } + return ret; +} + void ThemeManager::setIconTheme(const QString& name) { QIcon::setThemeName(name); @@ -137,19 +149,63 @@ void ThemeManager::setApplicationTheme(const QString& name, bool initial) } } -QString ThemeManager::getCatImage(QString catName) +QString ThemeManager::getCatPack(QString catName) { - QDateTime now = QDateTime::currentDateTime(); - QDateTime birthday(QDate(now.date().year(), 11, 30), QTime(0, 0)); - QDateTime xmas(QDate(now.date().year(), 12, 25), QTime(0, 0)); - QDateTime halloween(QDate(now.date().year(), 10, 31), QTime(0, 0)); - QString cat = !catName.isEmpty() ? catName : APPLICATION->settings()->get("BackgroundCat").toString(); - if (std::abs(now.daysTo(xmas)) <= 4) { - cat += "-xmas"; - } else if (std::abs(now.daysTo(halloween)) <= 4) { - cat += "-spooky"; - } else if (std::abs(now.daysTo(birthday)) <= 12) { - cat += "-bday"; + auto catIter = m_catPacks.find(!catName.isEmpty() ? catName : APPLICATION->settings()->get("BackgroundCat").toString()); + if (catIter != m_catPacks.end()) { + auto& catPack = catIter->second; + themeDebugLog() << "applying catpack" << catPack->id(); + return catPack->path(); + } else { + themeWarningLog() << "Tried to get invalid catPack:" << catName; + } + + return m_catPacks.begin()->second->path(); +} + +QString ThemeManager::addCatPack(std::unique_ptr catPack) +{ + QString id = catPack->id(); + m_catPacks.emplace(id, std::move(catPack)); + return id; +} + +void ThemeManager::initializeCatPacks() +{ + QList> defaultCats{ { "kitteh", QObject::tr("Background Cat (from MultiMC)") }, + { "rory", QObject::tr("Rory ID 11 (drawn by Ashtaka)") }, + { "rory-flat", QObject::tr("Rory ID 11 (flat edition, drawn by Ashtaka)") }, + { "teawie", QObject::tr("Teawie (drawn by SympathyTea)") } }; + for (auto [id, name] : defaultCats) { + addCatPack(std::unique_ptr(new BasicCatPack(id, name))); + } + QDir catpacksDir("./catpacks/"); + QString catpacksFolder = catpacksDir.absoluteFilePath(""); + themeDebugLog() << "CatPacks Folder Path: " << catpacksFolder; + + auto loadFiles = [this](QDir dir) { + // Load image files directly + QDirIterator ImageFileIterator(dir.absoluteFilePath(""), { "*.png", "*.gif", "*.jpg", "*.apng", "*.jxl", "*.avif" }, QDir::Files); + while (ImageFileIterator.hasNext()) { + QFile customCatFile(ImageFileIterator.next()); + QFileInfo customCatFileInfo(customCatFile); + themeDebugLog() << "Loading QSS Theme from:" << customCatFileInfo.absoluteFilePath(); + addCatPack(std::unique_ptr(new FileCatPack(customCatFileInfo))); + } + }; + + loadFiles(catpacksDir); + + QDirIterator directoryIterator(catpacksFolder, QDir::Dirs | QDir::NoDotAndDotDot, QDirIterator::Subdirectories); + while (directoryIterator.hasNext()) { + QDir dir(directoryIterator.next()); + QFileInfo manifest(dir.absoluteFilePath("catpack.json")); + if (manifest.exists()) { + // Load background manifest + themeDebugLog() << "Loading background manifest from:" << manifest.absoluteFilePath(); + addCatPack(std::unique_ptr(new JsonCatPack(manifest))); + } else { + loadFiles(dir); + } } - return cat; } diff --git a/launcher/ui/themes/ThemeManager.h b/launcher/ui/themes/ThemeManager.h index 87f36d9c1..bc0d31cd0 100644 --- a/launcher/ui/themes/ThemeManager.h +++ b/launcher/ui/themes/ThemeManager.h @@ -20,6 +20,7 @@ #include #include "ui/MainWindow.h" +#include "ui/themes/CatPack.h" #include "ui/themes/ITheme.h" inline auto themeDebugLog() @@ -40,18 +41,20 @@ class ThemeManager { void applyCurrentlySelectedTheme(bool initial = false); void setApplicationTheme(const QString& name, bool initial = false); - /// - /// Returns the cat based on selected cat and with events (Birthday, XMas, etc.) - /// - /// Optional, if you need a specific cat. - /// - static QString getCatImage(QString catName = ""); + /// @brief Returns the background based on selected and with events (Birthday, XMas, etc.) + /// @param catName Optional, if you need a specific background. + /// @return + QString getCatPack(QString catName = ""); + QList getValidCatPacks(); private: std::map> m_themes; + std::map> m_catPacks; MainWindow* m_mainWindow; void initializeThemes(); + void initializeCatPacks(); QString addTheme(std::unique_ptr theme); ITheme* getTheme(QString themeId); + QString addCatPack(std::unique_ptr catPack); }; diff --git a/launcher/ui/widgets/ThemeCustomizationWidget.cpp b/launcher/ui/widgets/ThemeCustomizationWidget.cpp index dcf13303c..e2c5ce3d7 100644 --- a/launcher/ui/widgets/ThemeCustomizationWidget.cpp +++ b/launcher/ui/widgets/ThemeCustomizationWidget.cpp @@ -95,9 +95,14 @@ void ThemeCustomizationWidget::applyWidgetTheme(int index) { emit currentWidgetThemeChanged(index); } -void ThemeCustomizationWidget::applyCatTheme(int index) { +void ThemeCustomizationWidget::applyCatTheme(int index) +{ auto settings = APPLICATION->settings(); - settings->set("BackgroundCat", m_catOptions[index].first); + auto originalCat = settings->get("BackgroundCat").toString(); + auto newCat = ui->backgroundCatComboBox->currentData().toString(); + if (originalCat != newCat) { + settings->set("BackgroundCat", newCat); + } emit currentCatChanged(index); } @@ -135,10 +140,10 @@ void ThemeCustomizationWidget::loadSettings() } auto cat = settings->get("BackgroundCat").toString(); - for (auto& catFromList : m_catOptions) { - QIcon catIcon = QIcon(QString(":/backgrounds/%1").arg(ThemeManager::getCatImage(catFromList.first))); - ui->backgroundCatComboBox->addItem(catIcon, catFromList.second); - if (cat == catFromList.first) { + for (auto& catFromList : APPLICATION->getValidCatPacks()) { + QIcon catIcon = QIcon(QString("%1").arg(catFromList->path())); + ui->backgroundCatComboBox->addItem(catIcon, catFromList->name(), catFromList->id()); + if (cat == catFromList->id()) { ui->backgroundCatComboBox->setCurrentIndex(ui->backgroundCatComboBox->count() - 1); } } diff --git a/launcher/ui/widgets/ThemeCustomizationWidget.h b/launcher/ui/widgets/ThemeCustomizationWidget.h index d955a2665..be204e57c 100644 --- a/launcher/ui/widgets/ThemeCustomizationWidget.h +++ b/launcher/ui/widgets/ThemeCustomizationWidget.h @@ -53,25 +53,17 @@ class ThemeCustomizationWidget : public QWidget { private: Ui::ThemeCustomizationWidget* ui; - //TODO finish implementing - QList> m_iconThemeOptions{ - { "pe_colored", QObject::tr("Simple (Colored Icons)") }, - { "pe_light", QObject::tr("Simple (Light Icons)") }, - { "pe_dark", QObject::tr("Simple (Dark Icons)") }, - { "pe_blue", QObject::tr("Simple (Blue Icons)") }, - { "breeze_light", QObject::tr("Breeze Light") }, - { "breeze_dark", QObject::tr("Breeze Dark") }, - { "OSX", QObject::tr("OSX") }, - { "iOS", QObject::tr("iOS") }, - { "flat", QObject::tr("Flat") }, - { "flat_white", QObject::tr("Flat (White)") }, - { "multimc", QObject::tr("Legacy") }, - { "custom", QObject::tr("Custom") } - }; - QList> m_catOptions{ - { "kitteh", QObject::tr("Background Cat (from MultiMC)") }, - { "rory", QObject::tr("Rory ID 11 (drawn by Ashtaka)") }, - { "rory-flat", QObject::tr("Rory ID 11 (flat edition, drawn by Ashtaka)") }, - { "teawie", QObject::tr("Teawie (drawn by SympathyTea)") } - }; + // TODO finish implementing + QList> m_iconThemeOptions{ { "pe_colored", QObject::tr("Simple (Colored Icons)") }, + { "pe_light", QObject::tr("Simple (Light Icons)") }, + { "pe_dark", QObject::tr("Simple (Dark Icons)") }, + { "pe_blue", QObject::tr("Simple (Blue Icons)") }, + { "breeze_light", QObject::tr("Breeze Light") }, + { "breeze_dark", QObject::tr("Breeze Dark") }, + { "OSX", QObject::tr("OSX") }, + { "iOS", QObject::tr("iOS") }, + { "flat", QObject::tr("Flat") }, + { "flat_white", QObject::tr("Flat (White)") }, + { "multimc", QObject::tr("Legacy") }, + { "custom", QObject::tr("Custom") } }; }; From 718aca3d066fc24c03b7ac6d625d68829fcaa427 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 23 Jun 2023 09:24:18 +0300 Subject: [PATCH 035/216] Fixed date constructor Signed-off-by: Trial97 --- launcher/ui/themes/CatPack.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/ui/themes/CatPack.h b/launcher/ui/themes/CatPack.h index d9010b8ea..9f288d3dd 100644 --- a/launcher/ui/themes/CatPack.h +++ b/launcher/ui/themes/CatPack.h @@ -79,7 +79,7 @@ class JsonCatPack : public BasicCatPack { auto sp = d.split("-"); day = sp[0].toInt(); if (sp.length() >= 2) - mounth = sp[1].length(); + mounth = sp[1].toInt(); } int mounth; int day; From f8adb508ab0152af76829e0fdee92b451dcc1acf Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 23 Jun 2023 11:44:40 +0300 Subject: [PATCH 036/216] Made catpack id optional in catpack.json Signed-off-by: Trial97 --- launcher/ui/themes/CatPack.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/launcher/ui/themes/CatPack.cpp b/launcher/ui/themes/CatPack.cpp index e74b9709a..2d5653a67 100644 --- a/launcher/ui/themes/CatPack.cpp +++ b/launcher/ui/themes/CatPack.cpp @@ -77,7 +77,8 @@ JsonCatPack::JsonCatPack(QFileInfo& manifestInfo) : BasicCatPack(manifestInfo.di auto doc = Json::requireDocument(manifestInfo.absoluteFilePath(), "CatPack JSON file"); const auto root = doc.object(); m_name = Json::requireString(root, "name", "Catpack name"); - m_id = Json::requireString(root, "id", "Catpack ID"); + auto id = Json::ensureString(root, "id", "", "Catpack ID"); + m_id = id.isEmpty() ? m_id : id; m_defaultPath = FS::PathCombine(path, Json::requireString(root, "default", "Deafult Cat")); auto variants = Json::ensureArray(root, "variants", QJsonArray(), "Catpack Variants"); for (auto v : variants) { From c5ea8367aaf9d61a6362427a55206d8891f40cda Mon Sep 17 00:00:00 2001 From: Alexandru Ionut Tripon Date: Fri, 23 Jun 2023 14:25:21 +0300 Subject: [PATCH 037/216] Update launcher/ui/themes/CatPack.cpp Co-authored-by: TheKodeToad Signed-off-by: Alexandru Ionut Tripon --- launcher/ui/themes/CatPack.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/launcher/ui/themes/CatPack.cpp b/launcher/ui/themes/CatPack.cpp index 2d5653a67..bee632029 100644 --- a/launcher/ui/themes/CatPack.cpp +++ b/launcher/ui/themes/CatPack.cpp @@ -78,7 +78,8 @@ JsonCatPack::JsonCatPack(QFileInfo& manifestInfo) : BasicCatPack(manifestInfo.di const auto root = doc.object(); m_name = Json::requireString(root, "name", "Catpack name"); auto id = Json::ensureString(root, "id", "", "Catpack ID"); - m_id = id.isEmpty() ? m_id : id; + if (!id.isEmpty()) + m_id = id; m_defaultPath = FS::PathCombine(path, Json::requireString(root, "default", "Deafult Cat")); auto variants = Json::ensureArray(root, "variants", QJsonArray(), "Catpack Variants"); for (auto v : variants) { From 0a566318315c4e1566cb4ef7c99321a025e998a2 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 23 Jun 2023 19:35:41 +0300 Subject: [PATCH 038/216] Added curseforge search Signed-off-by: Trial97 --- .../modplatform/flame/FlamePackExportTask.cpp | 130 ++++++++++++++++-- .../modplatform/flame/FlamePackExportTask.h | 13 +- launcher/ui/dialogs/ExportMrPackDialog.cpp | 5 +- 3 files changed, 133 insertions(+), 15 deletions(-) diff --git a/launcher/modplatform/flame/FlamePackExportTask.cpp b/launcher/modplatform/flame/FlamePackExportTask.cpp index 6114f1b16..7130b502e 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.cpp +++ b/launcher/modplatform/flame/FlamePackExportTask.cpp @@ -24,12 +24,15 @@ #include #include #include +#include #include "Json.h" #include "MMCZip.h" #include "minecraft/PackProfile.h" +#include "minecraft/mod/ModDetails.h" #include "minecraft/mod/ModFolderModel.h" #include "modplatform/ModIndex.h" #include "modplatform/helpers/ExportModsToStringTask.h" +#include "modplatform/helpers/HashUtils.h" const QString FlamePackExportTask::TEMPLATE = "
  • {name}({authors})
  • "; @@ -88,13 +91,118 @@ void FlamePackExportTask::collectFiles() return; } + pendingHashes.clear(); resolvedFiles.clear(); - mcInstance->loaderModList()->update(); - connect(mcInstance->loaderModList().get(), &ModFolderModel::updateFinished, this, [this]() { - mods = mcInstance->loaderModList()->allMods(); + if (mcInstance) { + mcInstance->loaderModList()->update(); + connect(mcInstance->loaderModList().get(), &ModFolderModel::updateFinished, this, [this]() { + mods = mcInstance->loaderModList()->allMods(); + collectHashes(); + }); + } else + collectHashes(); +} + +void FlamePackExportTask::collectHashes() +{ + ConcurrentTask::Ptr hashing_task(new ConcurrentTask(this, "MakeHashesTask", 10)); + for (auto* mod : mods) { + if (!mod || !mod->valid() || mod->type() == ResourceType::FOLDER) + continue; + if (mod->metadata() && mod->metadata()->provider == ModPlatform::ResourceProvider::FLAME) { + resolvedFiles.insert(mod->fileinfo().absoluteFilePath(), + { mod->metadata()->project_id.toInt(), mod->metadata()->file_id.toInt(), mod->enabled() }); + continue; + } + + auto hash_task = Hashing::createFlameHasher(mod->fileinfo().absoluteFilePath()); + connect(hash_task.get(), &Task::succeeded, [this, hash_task, mod] { pendingHashes.insert(hash_task->getResult(), mod); }); + connect(hash_task.get(), &Task::failed, this, &FlamePackExportTask::emitFailed); + connect(hash_task.get(), &Task::finished, [hash_task] { hash_task->deleteLater(); }); + hashing_task->addTask(hash_task); + } + connect(hashing_task.get(), &Task::succeeded, this, &FlamePackExportTask::makeApiRequest); + connect(hashing_task.get(), &Task::failed, this, &FlamePackExportTask::emitFailed); + connect(hashing_task.get(), &Task::finished, [hashing_task] { hashing_task->deleteLater(); }); + hashing_task->start(); +} + +void FlamePackExportTask::makeApiRequest() +{ + setAbortable(true); + if (pendingHashes.isEmpty()) { + buildZip(); + return; + } + + auto response = std::make_shared(); + + QList fingerprints; + for (auto& murmur : pendingHashes.keys()) { + fingerprints.push_back(murmur.toUInt()); + } + + auto task = api.matchFingerprints(fingerprints, response.get()); + + connect(task.get(), &Task::succeeded, this, [this, response] { + QJsonParseError parse_error{}; + QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error); + if (parse_error.error != QJsonParseError::NoError) { + qWarning() << "Error while parsing JSON response from Modrinth::CurrentVersions at " << parse_error.offset + << " reason: " << parse_error.errorString(); + qWarning() << *response; + + failed(parse_error.errorString()); + return; + } + + try { + auto doc_obj = Json::requireObject(doc); + auto data_obj = Json::requireObject(doc_obj, "data"); + auto data_arr = Json::requireArray(data_obj, "exactMatches"); + + if (data_arr.isEmpty()) { + qWarning() << "No matches found for fingerprint search!"; + + return; + } + + for (auto match : data_arr) { + auto match_obj = Json::ensureObject(match, {}); + auto file_obj = Json::ensureObject(match_obj, "file", {}); + + if (match_obj.isEmpty() || file_obj.isEmpty()) { + qWarning() << "Fingerprint match is empty!"; + + return; + } + + auto fingerprint = QString::number(Json::ensureVariant(file_obj, "fileFingerprint").toUInt()); + auto mod = pendingHashes.find(fingerprint); + if (mod == pendingHashes.end()) { + qWarning() << "Invalid fingerprint from the API response."; + continue; + } + + setStatus(tr("Parsing API response from CurseForge for '%1'...").arg((*mod)->name())); + + resolvedFiles.insert( + mod.value()->fileinfo().absoluteFilePath(), + { Json::requireInteger(file_obj, "modId"), Json::requireInteger(file_obj, "modId"), mod.value()->enabled() }); + } + + } catch (Json::JsonException& e) { + qDebug() << e.cause(); + qDebug() << doc; + } + pendingHashes.clear(); buildZip(); }); + + connect(task.get(), &NetJob::finished, [task]() { task->deleteLater(); }); + connect(task.get(), &NetJob::failed, this, &FlamePackExportTask::emitFailed); + task->start(); } void FlamePackExportTask::buildZip() @@ -177,7 +285,8 @@ QByteArray FlamePackExportTask::generateIndex() obj["name"] = name; obj["version"] = version; obj["author"] = author; - obj["projectID"] = projectID.toInt(); + if (projectID.toInt() != 0) + obj["projectID"] = projectID.toInt(); obj["overrides"] = "overrides"; if (mcInstance) { QJsonObject version; @@ -205,16 +314,11 @@ QByteArray FlamePackExportTask::generateIndex() } QJsonArray files; - for (auto mod : mods) { - auto meta = mod->metadata(); - if (meta == nullptr || meta->provider != ModPlatform::ResourceProvider::FLAME) - continue; - resolvedFiles[gameRoot.relativeFilePath(mod->fileinfo().absoluteFilePath())] = true; - + for (auto mod : resolvedFiles) { QJsonObject file; - file["projectID"] = meta->project_id.toInt(); - file["fileID"] = meta->file_id.toInt(); - file["required"] = true; + file["projectID"] = mod.addonId; + file["fileID"] = mod.version; + file["required"] = mod.enabled; files << file; } obj["files"] = files; diff --git a/launcher/modplatform/flame/FlamePackExportTask.h b/launcher/modplatform/flame/FlamePackExportTask.h index 370cd67e4..58f66cc52 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.h +++ b/launcher/modplatform/flame/FlamePackExportTask.h @@ -23,6 +23,7 @@ #include "BaseInstance.h" #include "MMCZip.h" #include "minecraft/MinecraftInstance.h" +#include "modplatform/flame/FlameAPI.h" #include "tasks/Task.h" class FlamePackExportTask : public Task { @@ -52,15 +53,25 @@ class FlamePackExportTask : public Task { const MMCZip::FilterFunction filter; typedef std::optional BuildZipResult; + struct ResolvedFile { + int addonId; + int version; + bool enabled; + }; + + FlameAPI api; QFileInfoList files; - QMap resolvedFiles; + QMap pendingHashes; + QMap resolvedFiles; Task::Ptr task; QFuture buildZipFuture; QFutureWatcher buildZipWatcher; QList mods; void collectFiles(); + void collectHashes(); + void makeApiRequest(); void buildZip(); void finish(); diff --git a/launcher/ui/dialogs/ExportMrPackDialog.cpp b/launcher/ui/dialogs/ExportMrPackDialog.cpp index aaa528aa1..3711bb8fb 100644 --- a/launcher/ui/dialogs/ExportMrPackDialog.cpp +++ b/launcher/ui/dialogs/ExportMrPackDialog.cpp @@ -44,6 +44,8 @@ ExportMrPackDialog::ExportMrPackDialog(InstancePtr instance, QWidget* parent, Mo ui->author->hide(); ui->authorLabel->hide(); } else { + setWindowTitle("Export CurseForge Pack"); + ui->version->setText(""); ui->summaryLabel->setText("ProjectID"); } @@ -137,6 +139,7 @@ void ExportMrPackDialog::done(int result) void ExportMrPackDialog::validate() { - const bool invalid = ui->name->text().isEmpty() || ui->version->text().isEmpty(); + const bool invalid = + ui->name->text().isEmpty() || ((m_provider == ModPlatform::ResourceProvider::MODRINTH) && ui->version->text().isEmpty()); ui->buttonBox->button(QDialogButtonBox::Ok)->setDisabled(invalid); } From 222a10891c103d1357448d6aaff5da8d94e576af Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 23 Jun 2023 19:41:55 +0300 Subject: [PATCH 039/216] Fixed merge Signed-off-by: Trial97 --- launcher/modplatform/flame/FlamePackExportTask.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/modplatform/flame/FlamePackExportTask.cpp b/launcher/modplatform/flame/FlamePackExportTask.cpp index 7130b502e..28c62f534 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.cpp +++ b/launcher/modplatform/flame/FlamePackExportTask.cpp @@ -143,7 +143,7 @@ void FlamePackExportTask::makeApiRequest() fingerprints.push_back(murmur.toUInt()); } - auto task = api.matchFingerprints(fingerprints, response.get()); + auto task = api.matchFingerprints(fingerprints, response); connect(task.get(), &Task::succeeded, this, [this, response] { QJsonParseError parse_error{}; From 823cd3862d15f8e9d47cdc5fc8662a20f774567a Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 23 Jun 2023 22:41:01 +0300 Subject: [PATCH 040/216] Fixed hash checking Signed-off-by: Trial97 --- .../modplatform/flame/FlamePackExportTask.cpp | 41 +++++++++++-------- .../modplatform/flame/FlamePackExportTask.h | 5 +-- launcher/modplatform/helpers/HashUtils.cpp | 2 + 3 files changed, 29 insertions(+), 19 deletions(-) diff --git a/launcher/modplatform/flame/FlamePackExportTask.cpp b/launcher/modplatform/flame/FlamePackExportTask.cpp index 28c62f534..880d4324c 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.cpp +++ b/launcher/modplatform/flame/FlamePackExportTask.cpp @@ -28,11 +28,11 @@ #include "Json.h" #include "MMCZip.h" #include "minecraft/PackProfile.h" -#include "minecraft/mod/ModDetails.h" #include "minecraft/mod/ModFolderModel.h" #include "modplatform/ModIndex.h" #include "modplatform/helpers/ExportModsToStringTask.h" #include "modplatform/helpers/HashUtils.h" +#include "tasks/Task.h" const QString FlamePackExportTask::TEMPLATE = "
  • {name}({authors})
  • "; @@ -94,43 +94,51 @@ void FlamePackExportTask::collectFiles() pendingHashes.clear(); resolvedFiles.clear(); - if (mcInstance) { + if (mcInstance != nullptr) { + connect(mcInstance->loaderModList().get(), &ModFolderModel::updateFinished, this, &FlamePackExportTask::collectHashes); mcInstance->loaderModList()->update(); - connect(mcInstance->loaderModList().get(), &ModFolderModel::updateFinished, this, [this]() { - mods = mcInstance->loaderModList()->allMods(); - collectHashes(); - }); } else collectHashes(); } void FlamePackExportTask::collectHashes() { + setAbortable(true); + setStatus(tr("Find file hashes...")); + auto mods = mcInstance->loaderModList()->allMods(); ConcurrentTask::Ptr hashing_task(new ConcurrentTask(this, "MakeHashesTask", 10)); + task.reset(hashing_task); + setProgress(0, mods.count()); for (auto* mod : mods) { - if (!mod || !mod->valid() || mod->type() == ResourceType::FOLDER) + if (!mod || mod->type() == ResourceType::FOLDER) { + setProgress(m_progress + 1, mods.count()); continue; + } if (mod->metadata() && mod->metadata()->provider == ModPlatform::ResourceProvider::FLAME) { resolvedFiles.insert(mod->fileinfo().absoluteFilePath(), { mod->metadata()->project_id.toInt(), mod->metadata()->file_id.toInt(), mod->enabled() }); + setProgress(m_progress + 1, mods.count()); continue; } auto hash_task = Hashing::createFlameHasher(mod->fileinfo().absoluteFilePath()); - connect(hash_task.get(), &Task::succeeded, [this, hash_task, mod] { pendingHashes.insert(hash_task->getResult(), mod); }); + connect(hash_task.get(), &Hashing::Hasher::resultsReady, [this, mod, mods](QString hash) { + if (m_state == Task::State::Running) { + setProgress(m_progress + 1, mods.count()); + pendingHashes.insert(hash, mod); + } + }); connect(hash_task.get(), &Task::failed, this, &FlamePackExportTask::emitFailed); - connect(hash_task.get(), &Task::finished, [hash_task] { hash_task->deleteLater(); }); hashing_task->addTask(hash_task); } connect(hashing_task.get(), &Task::succeeded, this, &FlamePackExportTask::makeApiRequest); connect(hashing_task.get(), &Task::failed, this, &FlamePackExportTask::emitFailed); - connect(hashing_task.get(), &Task::finished, [hashing_task] { hashing_task->deleteLater(); }); hashing_task->start(); } void FlamePackExportTask::makeApiRequest() { - setAbortable(true); + setStatus(tr("Find versions for hashes...")); if (pendingHashes.isEmpty()) { buildZip(); return; @@ -143,7 +151,7 @@ void FlamePackExportTask::makeApiRequest() fingerprints.push_back(murmur.toUInt()); } - auto task = api.matchFingerprints(fingerprints, response); + task.reset(api.matchFingerprints(fingerprints, response)); connect(task.get(), &Task::succeeded, this, [this, response] { QJsonParseError parse_error{}; @@ -167,8 +175,9 @@ void FlamePackExportTask::makeApiRequest() return; } - + size_t progress = 0; for (auto match : data_arr) { + setProgress(progress++, data_arr.count()); auto match_obj = Json::ensureObject(match, {}); auto file_obj = Json::ensureObject(match_obj, "file", {}); @@ -200,7 +209,6 @@ void FlamePackExportTask::makeApiRequest() buildZip(); }); - connect(task.get(), &NetJob::finished, [task]() { task->deleteLater(); }); connect(task.get(), &NetJob::failed, this, &FlamePackExportTask::emitFailed); task->start(); } @@ -231,7 +239,7 @@ void FlamePackExportTask::buildZip() QFile::remove(output); return BuildZipResult(tr("Could not create index")); } - QString content = ExportToString::ExportModsToStringTask(mods, TEMPLATE); + QString content = ExportToString::ExportModsToStringTask(mcInstance->loaderModList()->allMods(), TEMPLATE); content = "
      " + content + "
    "; modlist.write(content.toUtf8()); @@ -244,7 +252,8 @@ void FlamePackExportTask::buildZip() setProgress(progress, files.length()); const QString relative = gameRoot.relativeFilePath(file.absoluteFilePath()); - if (!resolvedFiles.contains(relative) && !JlCompress::compressFile(&zip, file.absoluteFilePath(), "overrides/" + relative)) { + if (!resolvedFiles.contains(file.absoluteFilePath()) && + !JlCompress::compressFile(&zip, file.absoluteFilePath(), "overrides/" + relative)) { QFile::remove(output); return BuildZipResult(tr("Could not read and compress %1").arg(relative)); } diff --git a/launcher/modplatform/flame/FlamePackExportTask.h b/launcher/modplatform/flame/FlamePackExportTask.h index 58f66cc52..f00696788 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.h +++ b/launcher/modplatform/flame/FlamePackExportTask.h @@ -62,12 +62,11 @@ class FlamePackExportTask : public Task { FlameAPI api; QFileInfoList files; - QMap pendingHashes; - QMap resolvedFiles; + QMap pendingHashes{}; + QMap resolvedFiles{}; Task::Ptr task; QFuture buildZipFuture; QFutureWatcher buildZipWatcher; - QList mods; void collectFiles(); void collectHashes(); diff --git a/launcher/modplatform/helpers/HashUtils.cpp b/launcher/modplatform/helpers/HashUtils.cpp index 7d188a2f1..6ff1d1710 100644 --- a/launcher/modplatform/helpers/HashUtils.cpp +++ b/launcher/modplatform/helpers/HashUtils.cpp @@ -89,6 +89,7 @@ void FlameHasher::executeTask() emitFailed("Empty hash!"); } else { emitSucceeded(); + emit resultsReady(m_hash); } } @@ -120,6 +121,7 @@ void BlockedModHasher::executeTask() emitFailed("Empty hash!"); } else { emitSucceeded(); + emit resultsReady(m_hash); } } From cf94adb363c1ae791ebd6f0149899f63c78bfb1b Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sat, 24 Jun 2023 01:05:49 +0300 Subject: [PATCH 041/216] Added some warnings Signed-off-by: Trial97 --- launcher/minecraft/mod/Mod.cpp | 7 + launcher/minecraft/mod/Mod.h | 1 + launcher/modplatform/ModIndex.cpp | 9 +- launcher/modplatform/ModIndex.h | 1 + .../modplatform/flame/FlamePackExportTask.cpp | 124 +++++++++++++++--- .../modplatform/flame/FlamePackExportTask.h | 7 + .../helpers/ExportModsToStringTask.cpp | 22 +--- launcher/ui/MainWindow.cpp | 13 +- launcher/ui/dialogs/ExportMrPackDialog.cpp | 4 +- launcher/ui/dialogs/ExportMrPackDialog.ui | 7 + 10 files changed, 158 insertions(+), 37 deletions(-) diff --git a/launcher/minecraft/mod/Mod.cpp b/launcher/minecraft/mod/Mod.cpp index e613ddeb7..e93ff8bcc 100644 --- a/launcher/minecraft/mod/Mod.cpp +++ b/launcher/minecraft/mod/Mod.cpp @@ -166,6 +166,13 @@ auto Mod::homeurl() const -> QString return details().homeurl; } +auto Mod::metaurl() const -> QString +{ + if (metadata() == nullptr) + return homeurl(); + return ModPlatform::getMetaURL(metadata()->provider, metadata()->slug); +} + auto Mod::description() const -> QString { return details().description; diff --git a/launcher/minecraft/mod/Mod.h b/launcher/minecraft/mod/Mod.h index d4e419f4f..d6272f4d0 100644 --- a/launcher/minecraft/mod/Mod.h +++ b/launcher/minecraft/mod/Mod.h @@ -70,6 +70,7 @@ public: auto provider() const -> std::optional; auto licenses() const -> const QList&; auto issueTracker() const -> QString; + auto metaurl() const -> QString; /** Get the intneral path to the mod's icon file*/ QString iconPath() const { return m_local_details.icon_file; }; diff --git a/launcher/modplatform/ModIndex.cpp b/launcher/modplatform/ModIndex.cpp index 6a507caf4..c68333c5d 100644 --- a/launcher/modplatform/ModIndex.cpp +++ b/launcher/modplatform/ModIndex.cpp @@ -70,11 +70,18 @@ auto ProviderCapabilities::hash(ResourceProvider p, QIODevice* device, QString t } QCryptographicHash hash(algo); - if(!hash.addData(device)) + if (!hash.addData(device)) qCritical() << "Failed to read JAR to create hash!"; Q_ASSERT(hash.result().length() == hash.hashLength(algo)); return { hash.result().toHex() }; } +QString getMetaURL(ResourceProvider provider, QString slug) +{ + return ((provider == ModPlatform::ResourceProvider::FLAME) ? "https://www.curseforge.com/minecraft/mc-mods/" + : "https://modrinth.com/mod/") + + slug.remove(".pw.toml"); +} + } // namespace ModPlatform diff --git a/launcher/modplatform/ModIndex.h b/launcher/modplatform/ModIndex.h index 82da2ab2f..7d8199b39 100644 --- a/launcher/modplatform/ModIndex.h +++ b/launcher/modplatform/ModIndex.h @@ -118,6 +118,7 @@ struct IndexedPack { return std::any_of(versions.constBegin(), versions.constEnd(), [](auto const& v) { return v.is_currently_selected; }); } }; +QString getMetaURL(ResourceProvider provider, QString slug); } // namespace ModPlatform diff --git a/launcher/modplatform/flame/FlamePackExportTask.cpp b/launcher/modplatform/flame/FlamePackExportTask.cpp index 880d4324c..2f1201e11 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.cpp +++ b/launcher/modplatform/flame/FlamePackExportTask.cpp @@ -24,13 +24,14 @@ #include #include #include +#include #include #include "Json.h" #include "MMCZip.h" #include "minecraft/PackProfile.h" #include "minecraft/mod/ModFolderModel.h" #include "modplatform/ModIndex.h" -#include "modplatform/helpers/ExportModsToStringTask.h" +#include "modplatform/flame/FlameModIndex.h" #include "modplatform/helpers/HashUtils.h" #include "tasks/Task.h" @@ -40,6 +41,7 @@ FlamePackExportTask::FlamePackExportTask(const QString& name, const QString& version, const QString& author, const QVariant& projectID, + const bool generateModList, InstancePtr instance, const QString& output, MMCZip::FilterFunction filter) @@ -52,6 +54,7 @@ FlamePackExportTask::FlamePackExportTask(const QString& name, , gameRoot(instance->gameRoot()) , output(output) , filter(filter) + , generateModList(generateModList) {} void FlamePackExportTask::executeTask() @@ -116,7 +119,8 @@ void FlamePackExportTask::collectHashes() } if (mod->metadata() && mod->metadata()->provider == ModPlatform::ResourceProvider::FLAME) { resolvedFiles.insert(mod->fileinfo().absoluteFilePath(), - { mod->metadata()->project_id.toInt(), mod->metadata()->file_id.toInt(), mod->enabled() }); + { mod->metadata()->project_id.toInt(), mod->metadata()->file_id.toInt(), mod->enabled(), + mod->metadata()->name, mod->metadata()->slug, mod->authors().join(", ") }); setProgress(m_progress + 1, mods.count()); continue; } @@ -195,10 +199,10 @@ void FlamePackExportTask::makeApiRequest() } setStatus(tr("Parsing API response from CurseForge for '%1'...").arg((*mod)->name())); - - resolvedFiles.insert( - mod.value()->fileinfo().absoluteFilePath(), - { Json::requireInteger(file_obj, "modId"), Json::requireInteger(file_obj, "modId"), mod.value()->enabled() }); + if (Json::ensureBoolean(file_obj, "isAvailable", false)) + resolvedFiles.insert( + mod.value()->fileinfo().absoluteFilePath(), + { Json::requireInteger(file_obj, "modId"), Json::requireInteger(file_obj, "id"), mod.value()->enabled() }); } } catch (Json::JsonException& e) { @@ -206,10 +210,91 @@ void FlamePackExportTask::makeApiRequest() qDebug() << doc; } pendingHashes.clear(); + }); + connect(task.get(), &Task::finished, this, &FlamePackExportTask::getProjectsInfo); + connect(task.get(), &NetJob::failed, this, &FlamePackExportTask::emitFailed); + task->start(); +} + +void FlamePackExportTask::getProjectsInfo() +{ + if (!generateModList) { + buildZip(); + return; + } + setStatus(tr("Find project info from curseforge...")); + QList addonIds; + for (auto resolved : resolvedFiles) { + if (resolved.slug.isEmpty()) { + addonIds << QString::number(resolved.addonId); + } + } + + auto response = std::make_shared(); + Task::Ptr proj_task; + + if (addonIds.isEmpty()) { + buildZip(); + return; + } else if (addonIds.size() == 1) { + proj_task = api.getProject(*addonIds.begin(), response); + } else { + proj_task = api.getProjects(addonIds, response); + } + + connect(proj_task.get(), &Task::succeeded, this, [this, response, addonIds] { + QJsonParseError parse_error{}; + auto doc = QJsonDocument::fromJson(*response, &parse_error); + if (parse_error.error != QJsonParseError::NoError) { + qWarning() << "Error while parsing JSON response from Modrinth projects task at " << parse_error.offset + << " reason: " << parse_error.errorString(); + qWarning() << *response; + return; + } + + try { + QJsonArray entries; + if (addonIds.size() == 1) + entries = { Json::requireObject(Json::requireObject(doc), "data") }; + else + entries = Json::requireArray(Json::requireObject(doc), "data"); + + size_t progress = 0; + for (auto entry : entries) { + setProgress(progress++, entries.count()); + auto entry_obj = Json::requireObject(entry); + + try { + setStatus(tr("Parsing API response from CurseForge for '%1'...").arg(Json::requireString(entry_obj, "name"))); + + ModPlatform::IndexedPack pack; + FlameMod::loadIndexedPack(pack, entry_obj); + for (auto key : resolvedFiles.keys()) { + auto val = resolvedFiles.value(key); + if (val.addonId == pack.addonId) { + val.name = pack.name; + val.slug = pack.slug; + QStringList authors; + for (auto author : pack.authors) + authors << author.name; + + val.authors = authors.join(", "); + resolvedFiles[key] = val; + } + } + + } catch (Json::JsonException& e) { + qDebug() << e.cause(); + qDebug() << entries; + } + } + } catch (Json::JsonException& e) { + qDebug() << e.cause(); + qDebug() << doc; + } buildZip(); }); - - connect(task.get(), &NetJob::failed, this, &FlamePackExportTask::emitFailed); + task.reset(proj_task); task->start(); } @@ -234,14 +319,23 @@ void FlamePackExportTask::buildZip() } indexFile.write(generateIndex()); - QuaZipFile modlist(&zip); - if (!modlist.open(QIODevice::WriteOnly, QuaZipNewInfo("modlist.html"))) { - QFile::remove(output); - return BuildZipResult(tr("Could not create index")); + if (generateModList) { + QuaZipFile modlist(&zip); + if (!modlist.open(QIODevice::WriteOnly, QuaZipNewInfo("modlist.html"))) { + QFile::remove(output); + return BuildZipResult(tr("Could not create index")); + } + QString content = ""; + for (auto mod : resolvedFiles) { + content += QString(TEMPLATE) + .replace("{name}", mod.name) + .replace("{url}", ModPlatform::getMetaURL(ModPlatform::ResourceProvider::FLAME, mod.slug)) + .replace("{authors}", mod.authors) + + "\n"; + } + content = "
      " + content + "
    "; + modlist.write(content.toUtf8()); } - QString content = ExportToString::ExportModsToStringTask(mcInstance->loaderModList()->allMods(), TEMPLATE); - content = "
      " + content + "
    "; - modlist.write(content.toUtf8()); size_t progress = 0; for (const QFileInfo& file : files) { diff --git a/launcher/modplatform/flame/FlamePackExportTask.h b/launcher/modplatform/flame/FlamePackExportTask.h index f00696788..7f27e0d04 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.h +++ b/launcher/modplatform/flame/FlamePackExportTask.h @@ -32,6 +32,7 @@ class FlamePackExportTask : public Task { const QString& version, const QString& author, const QVariant& projectID, + const bool generateModList, InstancePtr instance, const QString& output, MMCZip::FilterFunction filter); @@ -51,12 +52,17 @@ class FlamePackExportTask : public Task { const QDir gameRoot; const QString output; const MMCZip::FilterFunction filter; + const bool generateModList; typedef std::optional BuildZipResult; struct ResolvedFile { int addonId; int version; bool enabled; + + QString name; + QString slug; + QString authors; }; FlameAPI api; @@ -71,6 +77,7 @@ class FlamePackExportTask : public Task { void collectFiles(); void collectHashes(); void makeApiRequest(); + void getProjectsInfo(); void buildZip(); void finish(); diff --git a/launcher/modplatform/helpers/ExportModsToStringTask.cpp b/launcher/modplatform/helpers/ExportModsToStringTask.cpp index e7be5ce13..03e1f4baf 100644 --- a/launcher/modplatform/helpers/ExportModsToStringTask.cpp +++ b/launcher/modplatform/helpers/ExportModsToStringTask.cpp @@ -19,6 +19,7 @@ #include "modplatform/ModIndex.h" namespace ExportToString { + QString ExportModsToStringTask(QList mods, Formats format, OptionalData extraData) { switch (format) { @@ -28,12 +29,7 @@ QString ExportModsToStringTask(QList mods, Formats format, OptionalData ex auto meta = mod->metadata(); auto modName = mod->name(); if (extraData & Url) { - auto url = mod->homeurl(); - if (meta != nullptr) { - url = (meta->provider == ModPlatform::ResourceProvider::FLAME ? "https://www.curseforge.com/minecraft/mc-mods/" - : "https://modrinth.com/mod/") + - meta->slug.remove(".pw.toml"); - } + auto url = mod->metaurl(); if (!url.isEmpty()) modName = QString("%2").arg(url, modName); } @@ -57,12 +53,7 @@ QString ExportModsToStringTask(QList mods, Formats format, OptionalData ex auto meta = mod->metadata(); auto modName = mod->name(); if (extraData & Url) { - auto url = mod->homeurl(); - if (meta != nullptr) { - url = (meta->provider == ModPlatform::ResourceProvider::FLAME ? "https://www.curseforge.com/minecraft/mc-mods/" - : "https://modrinth.com/mod/") + - meta->slug.remove(".pw.toml"); - } + auto url = mod->metaurl(); if (!url.isEmpty()) modName = QString("[%1](%2)").arg(modName, url); } @@ -93,12 +84,7 @@ QString ExportModsToStringTask(QList mods, QString lineTemplate) auto meta = mod->metadata(); auto modName = mod->name(); - auto url = mod->homeurl(); - if (meta != nullptr) { - url = (meta->provider == ModPlatform::ResourceProvider::FLAME ? "https://www.curseforge.com/minecraft/mc-mods/" - : "https://modrinth.com/mod/") + - meta->slug.remove(".pw.toml"); - } + auto url = mod->metaurl(); auto ver = mod->version(); if (ver.isEmpty() && meta != nullptr) ver = meta->version().toString(); diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp index 0027d1804..eb09efbc3 100644 --- a/launcher/ui/MainWindow.cpp +++ b/launcher/ui/MainWindow.cpp @@ -1420,8 +1420,17 @@ void MainWindow::on_actionExportInstanceMrPack_triggered() void MainWindow::on_actionExportInstanceFlamePack_triggered() { if (m_selectedInstance) { - ExportMrPackDialog dlg(m_selectedInstance, this, ModPlatform::ResourceProvider::FLAME); - dlg.exec(); + auto instance = dynamic_cast(m_selectedInstance.get()); + if (instance) { + if (instance->getPackProfile()->getComponent("org.quiltmc.quilt-loader")) { + QMessageBox msgBox; + msgBox.setText(tr("Quilt is not yet supported by curseforge.")); + msgBox.exec(); + return; + } + ExportMrPackDialog dlg(m_selectedInstance, this, ModPlatform::ResourceProvider::FLAME); + dlg.exec(); + } } } diff --git a/launcher/ui/dialogs/ExportMrPackDialog.cpp b/launcher/ui/dialogs/ExportMrPackDialog.cpp index 3711bb8fb..edd2148a2 100644 --- a/launcher/ui/dialogs/ExportMrPackDialog.cpp +++ b/launcher/ui/dialogs/ExportMrPackDialog.cpp @@ -43,6 +43,7 @@ ExportMrPackDialog::ExportMrPackDialog(InstancePtr instance, QWidget* parent, Mo ui->summary->setText(instance->notes().split(QRegularExpression("\\r?\\n"))[0]); ui->author->hide(); ui->authorLabel->hide(); + ui->gnerateModlist->hide(); } else { setWindowTitle("Export CurseForge Pack"); ui->version->setText(""); @@ -117,7 +118,8 @@ void ExportMrPackDialog::done(int result) task = new ModrinthPackExportTask(ui->name->text(), ui->version->text(), ui->summary->text(), instance, output, [this](const QString& path) { return proxy->blockedPaths().covers(path); }); else - task = new FlamePackExportTask(ui->name->text(), ui->version->text(), ui->author->text(), ui->summary->text(), instance, output, + task = new FlamePackExportTask(ui->name->text(), ui->version->text(), ui->author->text(), ui->summary->text(), + ui->gnerateModlist->isChecked(), instance, output, [this](const QString& path) { return proxy->blockedPaths().covers(path); }); connect(task, &Task::failed, diff --git a/launcher/ui/dialogs/ExportMrPackDialog.ui b/launcher/ui/dialogs/ExportMrPackDialog.ui index 59ecb17c0..1b137eb4b 100644 --- a/launcher/ui/dialogs/ExportMrPackDialog.ui +++ b/launcher/ui/dialogs/ExportMrPackDialog.ui @@ -67,6 +67,13 @@ + + + + Generate modlist + + + From 42bc04a0d2af26e97829e6b1afd87d550b9b44da Mon Sep 17 00:00:00 2001 From: Alexandru Ionut Tripon Date: Sat, 24 Jun 2023 11:01:23 +0300 Subject: [PATCH 042/216] Update launcher/ui/MainWindow.cpp Co-authored-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com> Signed-off-by: Alexandru Ionut Tripon --- launcher/ui/MainWindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp index eb09efbc3..89c78539c 100644 --- a/launcher/ui/MainWindow.cpp +++ b/launcher/ui/MainWindow.cpp @@ -1424,7 +1424,7 @@ void MainWindow::on_actionExportInstanceFlamePack_triggered() if (instance) { if (instance->getPackProfile()->getComponent("org.quiltmc.quilt-loader")) { QMessageBox msgBox; - msgBox.setText(tr("Quilt is not yet supported by curseforge.")); + msgBox.setText(tr("Quilt is currently not supported by CurseForge modpacks.")); msgBox.exec(); return; } From cd1e8dc8cc87acf905ab3140efc48ef482973c7e Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sat, 24 Jun 2023 11:12:23 +0300 Subject: [PATCH 043/216] Removed modlist checkbox Signed-off-by: Trial97 --- .../modplatform/flame/FlamePackExportTask.cpp | 36 ++++++++----------- .../modplatform/flame/FlamePackExportTask.h | 2 -- launcher/ui/dialogs/ExportMrPackDialog.cpp | 4 +-- launcher/ui/dialogs/ExportMrPackDialog.ui | 7 ---- 4 files changed, 15 insertions(+), 34 deletions(-) diff --git a/launcher/modplatform/flame/FlamePackExportTask.cpp b/launcher/modplatform/flame/FlamePackExportTask.cpp index 2f1201e11..927b2e461 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.cpp +++ b/launcher/modplatform/flame/FlamePackExportTask.cpp @@ -41,7 +41,6 @@ FlamePackExportTask::FlamePackExportTask(const QString& name, const QString& version, const QString& author, const QVariant& projectID, - const bool generateModList, InstancePtr instance, const QString& output, MMCZip::FilterFunction filter) @@ -54,7 +53,6 @@ FlamePackExportTask::FlamePackExportTask(const QString& name, , gameRoot(instance->gameRoot()) , output(output) , filter(filter) - , generateModList(generateModList) {} void FlamePackExportTask::executeTask() @@ -218,10 +216,6 @@ void FlamePackExportTask::makeApiRequest() void FlamePackExportTask::getProjectsInfo() { - if (!generateModList) { - buildZip(); - return; - } setStatus(tr("Find project info from curseforge...")); QList addonIds; for (auto resolved : resolvedFiles) { @@ -319,23 +313,21 @@ void FlamePackExportTask::buildZip() } indexFile.write(generateIndex()); - if (generateModList) { - QuaZipFile modlist(&zip); - if (!modlist.open(QIODevice::WriteOnly, QuaZipNewInfo("modlist.html"))) { - QFile::remove(output); - return BuildZipResult(tr("Could not create index")); - } - QString content = ""; - for (auto mod : resolvedFiles) { - content += QString(TEMPLATE) - .replace("{name}", mod.name) - .replace("{url}", ModPlatform::getMetaURL(ModPlatform::ResourceProvider::FLAME, mod.slug)) - .replace("{authors}", mod.authors) + - "\n"; - } - content = "
      " + content + "
    "; - modlist.write(content.toUtf8()); + QuaZipFile modlist(&zip); + if (!modlist.open(QIODevice::WriteOnly, QuaZipNewInfo("modlist.html"))) { + QFile::remove(output); + return BuildZipResult(tr("Could not create index")); } + QString content = ""; + for (auto mod : resolvedFiles) { + content += QString(TEMPLATE) + .replace("{name}", mod.name) + .replace("{url}", ModPlatform::getMetaURL(ModPlatform::ResourceProvider::FLAME, mod.slug)) + .replace("{authors}", mod.authors) + + "\n"; + } + content = "
      " + content + "
    "; + modlist.write(content.toUtf8()); size_t progress = 0; for (const QFileInfo& file : files) { diff --git a/launcher/modplatform/flame/FlamePackExportTask.h b/launcher/modplatform/flame/FlamePackExportTask.h index 7f27e0d04..9ec9a2308 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.h +++ b/launcher/modplatform/flame/FlamePackExportTask.h @@ -32,7 +32,6 @@ class FlamePackExportTask : public Task { const QString& version, const QString& author, const QVariant& projectID, - const bool generateModList, InstancePtr instance, const QString& output, MMCZip::FilterFunction filter); @@ -52,7 +51,6 @@ class FlamePackExportTask : public Task { const QDir gameRoot; const QString output; const MMCZip::FilterFunction filter; - const bool generateModList; typedef std::optional BuildZipResult; struct ResolvedFile { diff --git a/launcher/ui/dialogs/ExportMrPackDialog.cpp b/launcher/ui/dialogs/ExportMrPackDialog.cpp index 3c593d205..8a95997be 100644 --- a/launcher/ui/dialogs/ExportMrPackDialog.cpp +++ b/launcher/ui/dialogs/ExportMrPackDialog.cpp @@ -43,7 +43,6 @@ ExportMrPackDialog::ExportMrPackDialog(InstancePtr instance, QWidget* parent, Mo ui->summary->setText(instance->notes().split(QRegularExpression("\\r?\\n"))[0]); ui->author->hide(); ui->authorLabel->hide(); - ui->gnerateModlist->hide(); } else { setWindowTitle("Export CurseForge Pack"); ui->version->setText(""); @@ -118,8 +117,7 @@ void ExportMrPackDialog::done(int result) task = new ModrinthPackExportTask(ui->name->text(), ui->version->text(), ui->summary->text(), instance, output, [this](const QString& path) { return proxy->blockedPaths().covers(path); }); else - task = new FlamePackExportTask(ui->name->text(), ui->version->text(), ui->author->text(), ui->summary->text(), - ui->gnerateModlist->isChecked(), instance, output, + task = new FlamePackExportTask(ui->name->text(), ui->version->text(), ui->author->text(), ui->summary->text(), instance, output, [this](const QString& path) { return proxy->blockedPaths().covers(path); }); connect(task, &Task::failed, diff --git a/launcher/ui/dialogs/ExportMrPackDialog.ui b/launcher/ui/dialogs/ExportMrPackDialog.ui index 1b137eb4b..59ecb17c0 100644 --- a/launcher/ui/dialogs/ExportMrPackDialog.ui +++ b/launcher/ui/dialogs/ExportMrPackDialog.ui @@ -67,13 +67,6 @@ - - - - Generate modlist - - - From a325d814e242ee450141088513d9cd282d79141f Mon Sep 17 00:00:00 2001 From: Alexandru Ionut Tripon Date: Sat, 24 Jun 2023 11:13:08 +0300 Subject: [PATCH 044/216] Update launcher/modplatform/flame/FlamePackExportTask.cpp Co-authored-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com> Signed-off-by: Alexandru Ionut Tripon --- launcher/modplatform/flame/FlamePackExportTask.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/modplatform/flame/FlamePackExportTask.cpp b/launcher/modplatform/flame/FlamePackExportTask.cpp index 927b2e461..cd2424912 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.cpp +++ b/launcher/modplatform/flame/FlamePackExportTask.cpp @@ -35,7 +35,7 @@ #include "modplatform/helpers/HashUtils.h" #include "tasks/Task.h" -const QString FlamePackExportTask::TEMPLATE = "
  • {name}({authors})
  • "; +const QString FlamePackExportTask::TEMPLATE = "
  • {name} (by {authors})
  • "; FlamePackExportTask::FlamePackExportTask(const QString& name, const QString& version, From 8939096db659d1df5c75b938fc011a24af36e488 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sat, 24 Jun 2023 13:24:40 +0300 Subject: [PATCH 045/216] Fixed windows build Signed-off-by: Trial97 --- launcher/modplatform/flame/FlamePackExportTask.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/modplatform/flame/FlamePackExportTask.cpp b/launcher/modplatform/flame/FlamePackExportTask.cpp index 927b2e461..2920cb86a 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.cpp +++ b/launcher/modplatform/flame/FlamePackExportTask.cpp @@ -197,7 +197,7 @@ void FlamePackExportTask::makeApiRequest() } setStatus(tr("Parsing API response from CurseForge for '%1'...").arg((*mod)->name())); - if (Json::ensureBoolean(file_obj, "isAvailable", false)) + if (Json::ensureBoolean(file_obj, "isAvailable", false, "isAvailable")) resolvedFiles.insert( mod.value()->fileinfo().absoluteFilePath(), { Json::requireInteger(file_obj, "modId"), Json::requireInteger(file_obj, "id"), mod.value()->enabled() }); From 9804996db652eb719a0eb40c41157d0813372eb2 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sat, 24 Jun 2023 14:37:02 +0300 Subject: [PATCH 046/216] Added resource packs to export Signed-off-by: Trial97 --- .../modplatform/flame/FlamePackExportTask.cpp | 36 +++++++++++++------ .../modplatform/flame/FlamePackExportTask.h | 7 +++- 2 files changed, 32 insertions(+), 11 deletions(-) diff --git a/launcher/modplatform/flame/FlamePackExportTask.cpp b/launcher/modplatform/flame/FlamePackExportTask.cpp index 0d7abc9f0..45fc2e638 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.cpp +++ b/launcher/modplatform/flame/FlamePackExportTask.cpp @@ -109,25 +109,42 @@ void FlamePackExportTask::collectHashes() auto mods = mcInstance->loaderModList()->allMods(); ConcurrentTask::Ptr hashing_task(new ConcurrentTask(this, "MakeHashesTask", 10)); task.reset(hashing_task); - setProgress(0, mods.count()); + int totalProgres = mods.count(); + setProgress(0, totalProgres); for (auto* mod : mods) { if (!mod || mod->type() == ResourceType::FOLDER) { - setProgress(m_progress + 1, mods.count()); + setProgress(m_progress + 1, totalProgres); continue; } if (mod->metadata() && mod->metadata()->provider == ModPlatform::ResourceProvider::FLAME) { resolvedFiles.insert(mod->fileinfo().absoluteFilePath(), { mod->metadata()->project_id.toInt(), mod->metadata()->file_id.toInt(), mod->enabled(), mod->metadata()->name, mod->metadata()->slug, mod->authors().join(", ") }); - setProgress(m_progress + 1, mods.count()); + setProgress(m_progress + 1, totalProgres); continue; } auto hash_task = Hashing::createFlameHasher(mod->fileinfo().absoluteFilePath()); - connect(hash_task.get(), &Hashing::Hasher::resultsReady, [this, mod, mods](QString hash) { + connect(hash_task.get(), &Hashing::Hasher::resultsReady, [this, mod, totalProgres](QString hash) { if (m_state == Task::State::Running) { - setProgress(m_progress + 1, mods.count()); - pendingHashes.insert(hash, mod); + setProgress(m_progress + 1, totalProgres); + pendingHashes.insert(hash, { mod->name(), mod->fileinfo().absoluteFilePath(), mod->enabled() }); + } + }); + connect(hash_task.get(), &Task::failed, this, &FlamePackExportTask::emitFailed); + hashing_task->addTask(hash_task); + } + + for (const QFileInfo& file : files) { + const QString relative = gameRoot.relativeFilePath(file.absoluteFilePath()); + if (!relative.endsWith(".zip") || !relative.startsWith("resourcepacks/")) + continue; + totalProgres++; + auto hash_task = Hashing::createFlameHasher(file.absoluteFilePath()); + connect(hash_task.get(), &Hashing::Hasher::resultsReady, [this, relative, file, totalProgres](QString hash) { + if (m_state == Task::State::Running) { + setProgress(m_progress + 1, totalProgres); + pendingHashes.insert(hash, { relative, file.absoluteFilePath(), true }); } }); connect(hash_task.get(), &Task::failed, this, &FlamePackExportTask::emitFailed); @@ -196,11 +213,10 @@ void FlamePackExportTask::makeApiRequest() continue; } - setStatus(tr("Parsing API response from CurseForge for '%1'...").arg((*mod)->name())); + setStatus(tr("Parsing API response from CurseForge for '%1'...").arg(mod->name)); if (Json::ensureBoolean(file_obj, "isAvailable", false, "isAvailable")) - resolvedFiles.insert( - mod.value()->fileinfo().absoluteFilePath(), - { Json::requireInteger(file_obj, "modId"), Json::requireInteger(file_obj, "id"), mod.value()->enabled() }); + resolvedFiles.insert(mod->path, + { Json::requireInteger(file_obj, "modId"), Json::requireInteger(file_obj, "id"), mod->enabled }); } } catch (Json::JsonException& e) { diff --git a/launcher/modplatform/flame/FlamePackExportTask.h b/launcher/modplatform/flame/FlamePackExportTask.h index 9ec9a2308..629493d86 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.h +++ b/launcher/modplatform/flame/FlamePackExportTask.h @@ -62,11 +62,16 @@ class FlamePackExportTask : public Task { QString slug; QString authors; }; + struct HashInfo { + QString name; + QString path; + bool enabled; + }; FlameAPI api; QFileInfoList files; - QMap pendingHashes{}; + QMap pendingHashes{}; QMap resolvedFiles{}; Task::Ptr task; QFuture buildZipFuture; From 30ef5475c75514c08a4d1b2c8e4c6ec5abba41ea Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sat, 24 Jun 2023 14:50:05 +0300 Subject: [PATCH 047/216] Made sure CurseForge string is corect Signed-off-by: Trial97 --- launcher/modplatform/flame/FlamePackExportTask.cpp | 2 +- launcher/ui/MainWindow.ui | 2 +- launcher/ui/dialogs/ExportMrPackDialog.cpp | 2 +- launcher/ui/pages/global/LauncherPage.ui | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/launcher/modplatform/flame/FlamePackExportTask.cpp b/launcher/modplatform/flame/FlamePackExportTask.cpp index 45fc2e638..fb5bcc0b2 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.cpp +++ b/launcher/modplatform/flame/FlamePackExportTask.cpp @@ -232,7 +232,7 @@ void FlamePackExportTask::makeApiRequest() void FlamePackExportTask::getProjectsInfo() { - setStatus(tr("Find project info from curseforge...")); + setStatus(tr("Find project info from CurseForge...")); QList addonIds; for (auto resolved : resolvedFiles) { if (resolved.slug.isEmpty()) { diff --git a/launcher/ui/MainWindow.ui b/launcher/ui/MainWindow.ui index 1cfb59cde..190219b9b 100644 --- a/launcher/ui/MainWindow.ui +++ b/launcher/ui/MainWindow.ui @@ -484,7 +484,7 @@ - Curseforge (zip) + CurseForge (zip)
    diff --git a/launcher/ui/dialogs/ExportMrPackDialog.cpp b/launcher/ui/dialogs/ExportMrPackDialog.cpp index 8a95997be..94987c7e6 100644 --- a/launcher/ui/dialogs/ExportMrPackDialog.cpp +++ b/launcher/ui/dialogs/ExportMrPackDialog.cpp @@ -108,7 +108,7 @@ void ExportMrPackDialog::done(int result) nullptr); else output = QFileDialog::getSaveFileName(this, tr("Export %1").arg(ui->name->text()), - FS::PathCombine(QDir::homePath(), filename + ".zip"), "Curseforge pack (*.zip)", nullptr); + FS::PathCombine(QDir::homePath(), filename + ".zip"), "CurseForge pack (*.zip)", nullptr); if (output.isEmpty()) return; diff --git a/launcher/ui/pages/global/LauncherPage.ui b/launcher/ui/pages/global/LauncherPage.ui index d9116bfcf..26408f44f 100644 --- a/launcher/ui/pages/global/LauncherPage.ui +++ b/launcher/ui/pages/global/LauncherPage.ui @@ -169,7 +169,7 @@ - Disable using metadata provided by mod providers (like Modrinth or Curseforge) for mods. + Disable using metadata provided by mod providers (like Modrinth or CurseForge) for mods. Disable using metadata for mods From 59e1e5190310626109018d5aeed4782b347176ec Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sat, 24 Jun 2023 14:51:12 +0300 Subject: [PATCH 048/216] Removed unused files Signed-off-by: Trial97 --- launcher/CMakeLists.txt | 3 - .../helpers/ExportModsToStringTask.cpp | 100 ------------------ .../helpers/ExportModsToStringTask.h | 33 ------ 3 files changed, 136 deletions(-) delete mode 100644 launcher/modplatform/helpers/ExportModsToStringTask.cpp delete mode 100644 launcher/modplatform/helpers/ExportModsToStringTask.h diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index df6c90129..8de616a6c 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -487,9 +487,6 @@ set(API_SOURCES modplatform/helpers/HashUtils.cpp modplatform/helpers/OverrideUtils.h modplatform/helpers/OverrideUtils.cpp - - modplatform/helpers/ExportModsToStringTask.h - modplatform/helpers/ExportModsToStringTask.cpp ) set(FTB_SOURCES diff --git a/launcher/modplatform/helpers/ExportModsToStringTask.cpp b/launcher/modplatform/helpers/ExportModsToStringTask.cpp deleted file mode 100644 index 03e1f4baf..000000000 --- a/launcher/modplatform/helpers/ExportModsToStringTask.cpp +++ /dev/null @@ -1,100 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-only -/* - * Prism Launcher - Minecraft Launcher - * Copyright (c) 2023 Trial97 - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#include "ExportModsToStringTask.h" -#include "modplatform/ModIndex.h" - -namespace ExportToString { - -QString ExportModsToStringTask(QList mods, Formats format, OptionalData extraData) -{ - switch (format) { - case HTML: { - QStringList lines; - for (auto mod : mods) { - auto meta = mod->metadata(); - auto modName = mod->name(); - if (extraData & Url) { - auto url = mod->metaurl(); - if (!url.isEmpty()) - modName = QString("%2").arg(url, modName); - } - auto line = modName; - if (extraData & Version) { - auto ver = mod->version(); - if (ver.isEmpty() && meta != nullptr) - ver = meta->version().toString(); - if (!ver.isEmpty()) - line += QString("[%1]").arg(ver); - } - if (extraData & Authors && !mod->authors().isEmpty()) - line += " by " + mod->authors().join(", "); - lines.append(QString("
      %1
    ").arg(line)); - } - return QString("\n\t%1\n").arg(lines.join("\n\t")); - } - case MARKDOWN: { - QStringList lines; - for (auto mod : mods) { - auto meta = mod->metadata(); - auto modName = mod->name(); - if (extraData & Url) { - auto url = mod->metaurl(); - if (!url.isEmpty()) - modName = QString("[%1](%2)").arg(modName, url); - } - auto line = modName; - if (extraData & Version) { - auto ver = mod->version(); - if (ver.isEmpty() && meta != nullptr) - ver = meta->version().toString(); - if (!ver.isEmpty()) - line += QString("[%1]").arg(ver); - } - if (extraData & Authors && !mod->authors().isEmpty()) - line += " by " + mod->authors().join(", "); - lines << line; - } - return lines.join("\n"); - } - default: { - return QString("unknown format:%1").arg(format); - } - } -} - -QString ExportModsToStringTask(QList mods, QString lineTemplate) -{ - QStringList lines; - for (auto mod : mods) { - auto meta = mod->metadata(); - auto modName = mod->name(); - - auto url = mod->metaurl(); - auto ver = mod->version(); - if (ver.isEmpty() && meta != nullptr) - ver = meta->version().toString(); - auto authors = mod->authors().join(", "); - lines << QString(lineTemplate) - .replace("{name}", modName) - .replace("{url}", url) - .replace("{version}", ver) - .replace("{authors}", authors); - } - return lines.join("\n"); -} -} // namespace ExportToString \ No newline at end of file diff --git a/launcher/modplatform/helpers/ExportModsToStringTask.h b/launcher/modplatform/helpers/ExportModsToStringTask.h deleted file mode 100644 index 756c69f77..000000000 --- a/launcher/modplatform/helpers/ExportModsToStringTask.h +++ /dev/null @@ -1,33 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-only -/* - * Prism Launcher - Minecraft Launcher - * Copyright (c) 2023 Trial97 - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#pragma once -#include -#include -#include "minecraft/mod/Mod.h" - -namespace ExportToString { - -enum Formats { HTML, MARKDOWN }; -enum OptionalData { - Authors = 1 << 0, - Url = 1 << 1, - Version = 1 << 2, -}; -QString ExportModsToStringTask(QList mods, Formats format, OptionalData extraData); -QString ExportModsToStringTask(QList mods, QString lineTemplate); -} // namespace ExportToString From 25579fbedcfac6b36c6b30ad2447d702b601e1d6 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sat, 24 Jun 2023 14:54:39 +0300 Subject: [PATCH 049/216] Renamed ExportMrPackDialog to ExportPackDialog Signed-off-by: Trial97 --- launcher/CMakeLists.txt | 6 +++--- launcher/ui/MainWindow.cpp | 6 +++--- ...portMrPackDialog.cpp => ExportPackDialog.cpp} | 16 ++++++++-------- .../{ExportMrPackDialog.h => ExportPackDialog.h} | 14 +++++++------- ...ExportMrPackDialog.ui => ExportPackDialog.ui} | 8 ++++---- 5 files changed, 25 insertions(+), 25 deletions(-) rename launcher/ui/dialogs/{ExportMrPackDialog.cpp => ExportPackDialog.cpp} (91%) rename launcher/ui/dialogs/{ExportMrPackDialog.h => ExportPackDialog.h} (76%) rename launcher/ui/dialogs/{ExportMrPackDialog.ui => ExportPackDialog.ui} (95%) diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index 8de616a6c..0dc2b80a8 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -908,8 +908,8 @@ SET(LAUNCHER_SOURCES ui/dialogs/EditAccountDialog.h ui/dialogs/ExportInstanceDialog.cpp ui/dialogs/ExportInstanceDialog.h - ui/dialogs/ExportMrPackDialog.cpp - ui/dialogs/ExportMrPackDialog.h + ui/dialogs/ExportPackDialog.cpp + ui/dialogs/ExportPackDialog.h ui/dialogs/IconPickerDialog.cpp ui/dialogs/IconPickerDialog.h ui/dialogs/ImportResourceDialog.cpp @@ -1056,7 +1056,7 @@ qt_wrap_ui(LAUNCHER_UI ui/dialogs/ProfileSelectDialog.ui ui/dialogs/SkinUploadDialog.ui ui/dialogs/ExportInstanceDialog.ui - ui/dialogs/ExportMrPackDialog.ui + ui/dialogs/ExportPackDialog.ui ui/dialogs/IconPickerDialog.ui ui/dialogs/ImportResourceDialog.ui ui/dialogs/MSALoginDialog.ui diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp index 89c78539c..91809c7b3 100644 --- a/launcher/ui/MainWindow.cpp +++ b/launcher/ui/MainWindow.cpp @@ -107,7 +107,7 @@ #include "ui/dialogs/CopyInstanceDialog.h" #include "ui/dialogs/EditAccountDialog.h" #include "ui/dialogs/ExportInstanceDialog.h" -#include "ui/dialogs/ExportMrPackDialog.h" +#include "ui/dialogs/ExportPackDialog.h" #include "ui/dialogs/ImportResourceDialog.h" #include "ui/themes/ITheme.h" #include "ui/themes/ThemeManager.h" @@ -1412,7 +1412,7 @@ void MainWindow::on_actionExportInstanceMrPack_triggered() { if (m_selectedInstance) { - ExportMrPackDialog dlg(m_selectedInstance, this); + ExportPackDialog dlg(m_selectedInstance, this); dlg.exec(); } } @@ -1428,7 +1428,7 @@ void MainWindow::on_actionExportInstanceFlamePack_triggered() msgBox.exec(); return; } - ExportMrPackDialog dlg(m_selectedInstance, this, ModPlatform::ResourceProvider::FLAME); + ExportPackDialog dlg(m_selectedInstance, this, ModPlatform::ResourceProvider::FLAME); dlg.exec(); } } diff --git a/launcher/ui/dialogs/ExportMrPackDialog.cpp b/launcher/ui/dialogs/ExportPackDialog.cpp similarity index 91% rename from launcher/ui/dialogs/ExportMrPackDialog.cpp rename to launcher/ui/dialogs/ExportPackDialog.cpp index 94987c7e6..8e921f89a 100644 --- a/launcher/ui/dialogs/ExportMrPackDialog.cpp +++ b/launcher/ui/dialogs/ExportPackDialog.cpp @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -#include "ExportMrPackDialog.h" +#include "ExportPackDialog.h" #include "minecraft/mod/ModFolderModel.h" #include "modplatform/ModIndex.h" #include "modplatform/flame/FlamePackExportTask.h" @@ -34,8 +34,8 @@ #include "MMCZip.h" #include "modplatform/modrinth/ModrinthPackExportTask.h" -ExportMrPackDialog::ExportMrPackDialog(InstancePtr instance, QWidget* parent, ModPlatform::ResourceProvider provider) - : QDialog(parent), instance(instance), ui(new Ui::ExportMrPackDialog), m_provider(provider) +ExportPackDialog::ExportPackDialog(InstancePtr instance, QWidget* parent, ModPlatform::ResourceProvider provider) + : QDialog(parent), instance(instance), ui(new Ui::ExportPackDialog), m_provider(provider) { ui->setupUi(this); ui->name->setText(instance->name()); @@ -51,8 +51,8 @@ ExportMrPackDialog::ExportMrPackDialog(InstancePtr instance, QWidget* parent, Mo // ensure a valid pack is generated // the name and version fields mustn't be empty - connect(ui->name, &QLineEdit::textEdited, this, &ExportMrPackDialog::validate); - connect(ui->version, &QLineEdit::textEdited, this, &ExportMrPackDialog::validate); + connect(ui->name, &QLineEdit::textEdited, this, &ExportPackDialog::validate); + connect(ui->version, &QLineEdit::textEdited, this, &ExportPackDialog::validate); // the instance name can technically be empty validate(); @@ -92,12 +92,12 @@ ExportMrPackDialog::ExportMrPackDialog(InstancePtr instance, QWidget* parent, Mo headerView->setSectionResizeMode(0, QHeaderView::Stretch); } -ExportMrPackDialog::~ExportMrPackDialog() +ExportPackDialog::~ExportPackDialog() { delete ui; } -void ExportMrPackDialog::done(int result) +void ExportPackDialog::done(int result) { if (result == Accepted) { const QString filename = FS::RemoveInvalidFilenameChars(ui->name->text()); @@ -137,7 +137,7 @@ void ExportMrPackDialog::done(int result) QDialog::done(result); } -void ExportMrPackDialog::validate() +void ExportPackDialog::validate() { const bool invalid = ui->name->text().isEmpty() || ((m_provider == ModPlatform::ResourceProvider::MODRINTH) && ui->version->text().isEmpty()); diff --git a/launcher/ui/dialogs/ExportMrPackDialog.h b/launcher/ui/dialogs/ExportPackDialog.h similarity index 76% rename from launcher/ui/dialogs/ExportMrPackDialog.h rename to launcher/ui/dialogs/ExportPackDialog.h index 858a31bf9..830c24d25 100644 --- a/launcher/ui/dialogs/ExportMrPackDialog.h +++ b/launcher/ui/dialogs/ExportPackDialog.h @@ -25,24 +25,24 @@ #include "modplatform/ModIndex.h" namespace Ui { -class ExportMrPackDialog; +class ExportPackDialog; } -class ExportMrPackDialog : public QDialog { +class ExportPackDialog : public QDialog { Q_OBJECT public: - explicit ExportMrPackDialog(InstancePtr instance, - QWidget* parent = nullptr, - ModPlatform::ResourceProvider provider = ModPlatform::ResourceProvider::MODRINTH); - ~ExportMrPackDialog(); + explicit ExportPackDialog(InstancePtr instance, + QWidget* parent = nullptr, + ModPlatform::ResourceProvider provider = ModPlatform::ResourceProvider::MODRINTH); + ~ExportPackDialog(); void done(int result) override; void validate(); private: const InstancePtr instance; - Ui::ExportMrPackDialog* ui; + Ui::ExportPackDialog* ui; FileIgnoreProxy* proxy; FastFileIconProvider icons; const ModPlatform::ResourceProvider m_provider; diff --git a/launcher/ui/dialogs/ExportMrPackDialog.ui b/launcher/ui/dialogs/ExportPackDialog.ui similarity index 95% rename from launcher/ui/dialogs/ExportMrPackDialog.ui rename to launcher/ui/dialogs/ExportPackDialog.ui index 59ecb17c0..5762508af 100644 --- a/launcher/ui/dialogs/ExportMrPackDialog.ui +++ b/launcher/ui/dialogs/ExportPackDialog.ui @@ -1,7 +1,7 @@ - ExportMrPackDialog - + ExportPackDialog + 0 @@ -113,7 +113,7 @@ buttonBox accepted() - ExportMrPackDialog + ExportPackDialog accept() @@ -129,7 +129,7 @@ buttonBox rejected() - ExportMrPackDialog + ExportPackDialog reject() From 4a84084d9d605ae4fa9a8063f36bfdbcdc4c5c3d Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sat, 24 Jun 2023 15:02:00 +0300 Subject: [PATCH 050/216] Added condition for modlist Signed-off-by: Trial97 --- .../modplatform/flame/FlamePackExportTask.cpp | 20 ++++++++++--------- .../modplatform/flame/FlamePackExportTask.h | 2 ++ launcher/ui/dialogs/ExportPackDialog.cpp | 2 +- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/launcher/modplatform/flame/FlamePackExportTask.cpp b/launcher/modplatform/flame/FlamePackExportTask.cpp index fb5bcc0b2..dc407653b 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.cpp +++ b/launcher/modplatform/flame/FlamePackExportTask.cpp @@ -118,7 +118,7 @@ void FlamePackExportTask::collectHashes() } if (mod->metadata() && mod->metadata()->provider == ModPlatform::ResourceProvider::FLAME) { resolvedFiles.insert(mod->fileinfo().absoluteFilePath(), - { mod->metadata()->project_id.toInt(), mod->metadata()->file_id.toInt(), mod->enabled(), + { mod->metadata()->project_id.toInt(), mod->metadata()->file_id.toInt(), mod->enabled(), true, mod->metadata()->name, mod->metadata()->slug, mod->authors().join(", ") }); setProgress(m_progress + 1, totalProgres); continue; @@ -128,7 +128,7 @@ void FlamePackExportTask::collectHashes() connect(hash_task.get(), &Hashing::Hasher::resultsReady, [this, mod, totalProgres](QString hash) { if (m_state == Task::State::Running) { setProgress(m_progress + 1, totalProgres); - pendingHashes.insert(hash, { mod->name(), mod->fileinfo().absoluteFilePath(), mod->enabled() }); + pendingHashes.insert(hash, { mod->name(), mod->fileinfo().absoluteFilePath(), mod->enabled(), true }); } }); connect(hash_task.get(), &Task::failed, this, &FlamePackExportTask::emitFailed); @@ -215,8 +215,8 @@ void FlamePackExportTask::makeApiRequest() setStatus(tr("Parsing API response from CurseForge for '%1'...").arg(mod->name)); if (Json::ensureBoolean(file_obj, "isAvailable", false, "isAvailable")) - resolvedFiles.insert(mod->path, - { Json::requireInteger(file_obj, "modId"), Json::requireInteger(file_obj, "id"), mod->enabled }); + resolvedFiles.insert(mod->path, { Json::requireInteger(file_obj, "modId"), Json::requireInteger(file_obj, "id"), + mod->enabled, mod->isMod }); } } catch (Json::JsonException& e) { @@ -336,11 +336,13 @@ void FlamePackExportTask::buildZip() } QString content = ""; for (auto mod : resolvedFiles) { - content += QString(TEMPLATE) - .replace("{name}", mod.name) - .replace("{url}", ModPlatform::getMetaURL(ModPlatform::ResourceProvider::FLAME, mod.slug)) - .replace("{authors}", mod.authors) + - "\n"; + if (mod.isMod) { + content += QString(TEMPLATE) + .replace("{name}", mod.name) + .replace("{url}", ModPlatform::getMetaURL(ModPlatform::ResourceProvider::FLAME, mod.slug)) + .replace("{authors}", mod.authors) + + "\n"; + } } content = "
      " + content + "
    "; modlist.write(content.toUtf8()); diff --git a/launcher/modplatform/flame/FlamePackExportTask.h b/launcher/modplatform/flame/FlamePackExportTask.h index 629493d86..ee1f4e8df 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.h +++ b/launcher/modplatform/flame/FlamePackExportTask.h @@ -57,6 +57,7 @@ class FlamePackExportTask : public Task { int addonId; int version; bool enabled; + bool isMod; QString name; QString slug; @@ -66,6 +67,7 @@ class FlamePackExportTask : public Task { QString name; QString path; bool enabled; + bool isMod; }; FlameAPI api; diff --git a/launcher/ui/dialogs/ExportPackDialog.cpp b/launcher/ui/dialogs/ExportPackDialog.cpp index 8e921f89a..fb71f4a5c 100644 --- a/launcher/ui/dialogs/ExportPackDialog.cpp +++ b/launcher/ui/dialogs/ExportPackDialog.cpp @@ -22,7 +22,7 @@ #include "modplatform/flame/FlamePackExportTask.h" #include "ui/dialogs/CustomMessageBox.h" #include "ui/dialogs/ProgressDialog.h" -#include "ui_ExportMrPackDialog.h" +#include "ui_ExportPackDialog.h" #include #include From 19cb6ad5883c59c27f954042025bf89d44bed096 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sat, 24 Jun 2023 15:04:18 +0300 Subject: [PATCH 051/216] Updated Modrinth esport messages Signed-off-by: Trial97 --- launcher/modplatform/flame/FlamePackExportTask.cpp | 2 +- launcher/modplatform/modrinth/ModrinthPackExportTask.cpp | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/launcher/modplatform/flame/FlamePackExportTask.cpp b/launcher/modplatform/flame/FlamePackExportTask.cpp index dc407653b..837ded0fb 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.cpp +++ b/launcher/modplatform/flame/FlamePackExportTask.cpp @@ -157,12 +157,12 @@ void FlamePackExportTask::collectHashes() void FlamePackExportTask::makeApiRequest() { - setStatus(tr("Find versions for hashes...")); if (pendingHashes.isEmpty()) { buildZip(); return; } + setStatus(tr("Find versions for hashes...")); auto response = std::make_shared(); QList fingerprints; diff --git a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp index c607bb89d..dd7486873 100644 --- a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp +++ b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp @@ -64,7 +64,8 @@ bool ModrinthPackExportTask::abort() if (buildZipFuture.isRunning()) { buildZipFuture.cancel(); - // NOTE: Here we don't do `emitAborted()` because it will be done when `buildZipFuture` actually cancels, which may not occur immediately. + // NOTE: Here we don't do `emitAborted()` because it will be done when `buildZipFuture` actually cancels, which may not occur + // immediately. return true; } @@ -94,6 +95,7 @@ void ModrinthPackExportTask::collectFiles() void ModrinthPackExportTask::collectHashes() { + setStatus(tr("Find file hashes...")); for (const QFileInfo& file : files) { QCoreApplication::processEvents(); @@ -157,6 +159,7 @@ void ModrinthPackExportTask::makeApiRequest() if (pendingHashes.isEmpty()) buildZip(); else { + setStatus(tr("Find versions for hashes...")); auto response = std::make_shared(); task = api.currentVersions(pendingHashes.values(), "sha512", response); connect(task.get(), &NetJob::succeeded, [this, response]() { parseApiResponse(response); }); From f825d7753afd6c00111c9ff9deedeee8ded5b27a Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sat, 24 Jun 2023 15:11:15 +0300 Subject: [PATCH 052/216] Updated copyright headers Signed-off-by: Trial97 --- launcher/modplatform/flame/FlamePackExportTask.cpp | 1 + launcher/modplatform/flame/FlamePackExportTask.h | 1 + 2 files changed, 2 insertions(+) diff --git a/launcher/modplatform/flame/FlamePackExportTask.cpp b/launcher/modplatform/flame/FlamePackExportTask.cpp index 837ded0fb..2759ae090 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.cpp +++ b/launcher/modplatform/flame/FlamePackExportTask.cpp @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-only /* * Prism Launcher - Minecraft Launcher + * Copyright (C) 2023 TheKodeToad * Copyright (c) 2023 Trial97 * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/modplatform/flame/FlamePackExportTask.h b/launcher/modplatform/flame/FlamePackExportTask.h index ee1f4e8df..cf67ed5f5 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.h +++ b/launcher/modplatform/flame/FlamePackExportTask.h @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-only /* * Prism Launcher - Minecraft Launcher + * Copyright (C) 2023 TheKodeToad * Copyright (c) 2023 Trial97 * * This program is free software: you can redistribute it and/or modify From df932c65875a20fd95a47c3394a802d131e93993 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sat, 24 Jun 2023 20:22:18 +0300 Subject: [PATCH 053/216] Updated authors string in modlist Signed-off-by: Trial97 --- launcher/modplatform/flame/FlamePackExportTask.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/launcher/modplatform/flame/FlamePackExportTask.cpp b/launcher/modplatform/flame/FlamePackExportTask.cpp index 2759ae090..54294d7b9 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.cpp +++ b/launcher/modplatform/flame/FlamePackExportTask.cpp @@ -36,7 +36,7 @@ #include "modplatform/helpers/HashUtils.h" #include "tasks/Task.h" -const QString FlamePackExportTask::TEMPLATE = "
  • {name} (by {authors})
  • "; +const QString FlamePackExportTask::TEMPLATE = "
  • {name}{authors}
  • "; FlamePackExportTask::FlamePackExportTask(const QString& name, const QString& version, @@ -338,11 +338,12 @@ void FlamePackExportTask::buildZip() QString content = ""; for (auto mod : resolvedFiles) { if (mod.isMod) { - content += QString(TEMPLATE) - .replace("{name}", mod.name) - .replace("{url}", ModPlatform::getMetaURL(ModPlatform::ResourceProvider::FLAME, mod.slug)) - .replace("{authors}", mod.authors) + - "\n"; + auto line = QString(TEMPLATE) + .replace("{name}", mod.name) + .replace("{url}", ModPlatform::getMetaURL(ModPlatform::ResourceProvider::FLAME, mod.slug)); + if (!mod.authors.isEmpty()) + line = line.replace("{authors}", QString(" (by {%1})").arg(mod.authors)); + content += line + "\n"; } } content = "
      " + content + "
    "; From f0e4e07c05bdf68994c9d6a460f4ec4c03a2e627 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sat, 24 Jun 2023 20:43:45 +0300 Subject: [PATCH 054/216] Updated url function Signed-off-by: Trial97 --- launcher/minecraft/mod/Mod.cpp | 2 +- launcher/modplatform/ModIndex.cpp | 7 +++---- launcher/modplatform/ModIndex.h | 2 +- launcher/modplatform/flame/FlamePackExportTask.cpp | 12 +++++------- 4 files changed, 10 insertions(+), 13 deletions(-) diff --git a/launcher/minecraft/mod/Mod.cpp b/launcher/minecraft/mod/Mod.cpp index e93ff8bcc..d5b96badd 100644 --- a/launcher/minecraft/mod/Mod.cpp +++ b/launcher/minecraft/mod/Mod.cpp @@ -170,7 +170,7 @@ auto Mod::metaurl() const -> QString { if (metadata() == nullptr) return homeurl(); - return ModPlatform::getMetaURL(metadata()->provider, metadata()->slug); + return ModPlatform::getMetaURL(metadata()->provider, metadata()->project_id); } auto Mod::description() const -> QString diff --git a/launcher/modplatform/ModIndex.cpp b/launcher/modplatform/ModIndex.cpp index c68333c5d..a1c4d8917 100644 --- a/launcher/modplatform/ModIndex.cpp +++ b/launcher/modplatform/ModIndex.cpp @@ -77,11 +77,10 @@ auto ProviderCapabilities::hash(ResourceProvider p, QIODevice* device, QString t return { hash.result().toHex() }; } -QString getMetaURL(ResourceProvider provider, QString slug) +QString getMetaURL(ResourceProvider provider, QVariant projectID) { - return ((provider == ModPlatform::ResourceProvider::FLAME) ? "https://www.curseforge.com/minecraft/mc-mods/" - : "https://modrinth.com/mod/") + - slug.remove(".pw.toml"); + return ((provider == ModPlatform::ResourceProvider::FLAME) ? "https://www.curseforge.com/projects/" : "https://modrinth.com/mod/") + + projectID.toString(); } } // namespace ModPlatform diff --git a/launcher/modplatform/ModIndex.h b/launcher/modplatform/ModIndex.h index 83412169e..773ee9346 100644 --- a/launcher/modplatform/ModIndex.h +++ b/launcher/modplatform/ModIndex.h @@ -128,7 +128,7 @@ struct IndexedPack { return std::any_of(versions.constBegin(), versions.constEnd(), [](auto const& v) { return v.is_currently_selected; }); } }; -QString getMetaURL(ResourceProvider provider, QString slug); +QString getMetaURL(ResourceProvider provider, QVariant projectID); struct OverrideDep { QString quilt; diff --git a/launcher/modplatform/flame/FlamePackExportTask.cpp b/launcher/modplatform/flame/FlamePackExportTask.cpp index 54294d7b9..d729e977c 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.cpp +++ b/launcher/modplatform/flame/FlamePackExportTask.cpp @@ -36,7 +36,7 @@ #include "modplatform/helpers/HashUtils.h" #include "tasks/Task.h" -const QString FlamePackExportTask::TEMPLATE = "
  • {name}{authors}
  • "; +const QString FlamePackExportTask::TEMPLATE = "
  • {name}{authors}
  • \n"; FlamePackExportTask::FlamePackExportTask(const QString& name, const QString& version, @@ -338,12 +338,10 @@ void FlamePackExportTask::buildZip() QString content = ""; for (auto mod : resolvedFiles) { if (mod.isMod) { - auto line = QString(TEMPLATE) - .replace("{name}", mod.name) - .replace("{url}", ModPlatform::getMetaURL(ModPlatform::ResourceProvider::FLAME, mod.slug)); - if (!mod.authors.isEmpty()) - line = line.replace("{authors}", QString(" (by {%1})").arg(mod.authors)); - content += line + "\n"; + content += QString(TEMPLATE) + .replace("{name}", mod.name) + .replace("{url}", ModPlatform::getMetaURL(ModPlatform::ResourceProvider::FLAME, mod.addonId)) + .replace("{authors}", !mod.authors.isEmpty() ? QString(" (by {%1})").arg(mod.authors) : ""); } } content = "
      " + content + "
    "; From 69c21454ecf683b1794aec55ddad66d53d3afc7c Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sat, 24 Jun 2023 22:15:18 +0300 Subject: [PATCH 055/216] removed projectID Signed-off-by: Trial97 --- launcher/modplatform/flame/FlamePackExportTask.cpp | 6 +----- launcher/modplatform/flame/FlamePackExportTask.h | 2 -- launcher/ui/dialogs/ExportPackDialog.cpp | 6 ++---- launcher/ui/dialogs/ExportPackDialog.ui | 11 +---------- 4 files changed, 4 insertions(+), 21 deletions(-) diff --git a/launcher/modplatform/flame/FlamePackExportTask.cpp b/launcher/modplatform/flame/FlamePackExportTask.cpp index d729e977c..ac85a6287 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.cpp +++ b/launcher/modplatform/flame/FlamePackExportTask.cpp @@ -41,14 +41,12 @@ const QString FlamePackExportTask::TEMPLATE = "
  • {name}{authors} FlamePackExportTask::FlamePackExportTask(const QString& name, const QString& version, const QString& author, - const QVariant& projectID, InstancePtr instance, const QString& output, MMCZip::FilterFunction filter) : name(name) , version(version) , author(author) - , projectID(projectID) , instance(instance) , mcInstance(dynamic_cast(instance.get())) , gameRoot(instance->gameRoot()) @@ -341,7 +339,7 @@ void FlamePackExportTask::buildZip() content += QString(TEMPLATE) .replace("{name}", mod.name) .replace("{url}", ModPlatform::getMetaURL(ModPlatform::ResourceProvider::FLAME, mod.addonId)) - .replace("{authors}", !mod.authors.isEmpty() ? QString(" (by {%1})").arg(mod.authors) : ""); + .replace("{authors}", !mod.authors.isEmpty() ? QString(" (by %1)").arg(mod.authors) : ""); } } content = "
      " + content + "
    "; @@ -398,8 +396,6 @@ QByteArray FlamePackExportTask::generateIndex() obj["name"] = name; obj["version"] = version; obj["author"] = author; - if (projectID.toInt() != 0) - obj["projectID"] = projectID.toInt(); obj["overrides"] = "overrides"; if (mcInstance) { QJsonObject version; diff --git a/launcher/modplatform/flame/FlamePackExportTask.h b/launcher/modplatform/flame/FlamePackExportTask.h index cf67ed5f5..5c8caa458 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.h +++ b/launcher/modplatform/flame/FlamePackExportTask.h @@ -32,7 +32,6 @@ class FlamePackExportTask : public Task { FlamePackExportTask(const QString& name, const QString& version, const QString& author, - const QVariant& projectID, InstancePtr instance, const QString& output, MMCZip::FilterFunction filter); @@ -46,7 +45,6 @@ class FlamePackExportTask : public Task { // inputs const QString name, version, author; - const QVariant projectID; const InstancePtr instance; MinecraftInstance* mcInstance; const QDir gameRoot; diff --git a/launcher/ui/dialogs/ExportPackDialog.cpp b/launcher/ui/dialogs/ExportPackDialog.cpp index fb71f4a5c..ea3649397 100644 --- a/launcher/ui/dialogs/ExportPackDialog.cpp +++ b/launcher/ui/dialogs/ExportPackDialog.cpp @@ -41,12 +41,10 @@ ExportPackDialog::ExportPackDialog(InstancePtr instance, QWidget* parent, ModPla ui->name->setText(instance->name()); if (m_provider == ModPlatform::ResourceProvider::MODRINTH) { ui->summary->setText(instance->notes().split(QRegularExpression("\\r?\\n"))[0]); - ui->author->hide(); - ui->authorLabel->hide(); } else { setWindowTitle("Export CurseForge Pack"); ui->version->setText(""); - ui->summaryLabel->setText("ProjectID"); + ui->summaryLabel->setText("Author"); } // ensure a valid pack is generated @@ -117,7 +115,7 @@ void ExportPackDialog::done(int result) task = new ModrinthPackExportTask(ui->name->text(), ui->version->text(), ui->summary->text(), instance, output, [this](const QString& path) { return proxy->blockedPaths().covers(path); }); else - task = new FlamePackExportTask(ui->name->text(), ui->version->text(), ui->author->text(), ui->summary->text(), instance, output, + task = new FlamePackExportTask(ui->name->text(), ui->version->text(), ui->summary->text(), instance, output, [this](const QString& path) { return proxy->blockedPaths().covers(path); }); connect(task, &Task::failed, diff --git a/launcher/ui/dialogs/ExportPackDialog.ui b/launcher/ui/dialogs/ExportPackDialog.ui index 5762508af..658e21994 100644 --- a/launcher/ui/dialogs/ExportPackDialog.ui +++ b/launcher/ui/dialogs/ExportPackDialog.ui @@ -57,16 +57,7 @@ - - - - Author - - - - - - + From 932531c8ba1197e38dcd66c1ad146aeebc9ca177 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sat, 24 Jun 2023 23:48:18 +0300 Subject: [PATCH 056/216] fixed authors Signed-off-by: Trial97 --- launcher/modplatform/flame/FlamePackExportTask.cpp | 2 +- launcher/ui/dialogs/ExportPackDialog.cpp | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/launcher/modplatform/flame/FlamePackExportTask.cpp b/launcher/modplatform/flame/FlamePackExportTask.cpp index ac85a6287..e73f3de59 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.cpp +++ b/launcher/modplatform/flame/FlamePackExportTask.cpp @@ -95,8 +95,8 @@ void FlamePackExportTask::collectFiles() resolvedFiles.clear(); if (mcInstance != nullptr) { - connect(mcInstance->loaderModList().get(), &ModFolderModel::updateFinished, this, &FlamePackExportTask::collectHashes); mcInstance->loaderModList()->update(); + connect(mcInstance->loaderModList().get(), &ModFolderModel::updateFinished, this, &FlamePackExportTask::collectHashes); } else collectHashes(); } diff --git a/launcher/ui/dialogs/ExportPackDialog.cpp b/launcher/ui/dialogs/ExportPackDialog.cpp index ea3649397..fd374246d 100644 --- a/launcher/ui/dialogs/ExportPackDialog.cpp +++ b/launcher/ui/dialogs/ExportPackDialog.cpp @@ -73,6 +73,7 @@ ExportPackDialog::ExportPackDialog(InstancePtr instance, QWidget* parent, ModPla MinecraftInstance* mcInstance = dynamic_cast(instance.get()); if (mcInstance) { + mcInstance->loaderModList()->update(); const QDir index = mcInstance->loaderModList()->indexDir(); if (index.exists()) proxy->blockedPaths().insert(root.relativeFilePath(index.absolutePath())); From ce4a86fbcd0c891472b842e76066d285de3aef7b Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sun, 25 Jun 2023 10:41:29 +0300 Subject: [PATCH 057/216] Made custom url function Signed-off-by: Trial97 --- launcher/minecraft/mod/Mod.cpp | 7 +++++++ launcher/minecraft/mod/Mod.h | 1 + launcher/modplatform/ModIndex.cpp | 8 +++++++- launcher/modplatform/ModIndex.h | 1 + launcher/ui/pages/instance/ModFolderPage.cpp | 18 +++++------------ launcher/ui/widgets/InfoFrame.cpp | 21 +++----------------- 6 files changed, 24 insertions(+), 32 deletions(-) diff --git a/launcher/minecraft/mod/Mod.cpp b/launcher/minecraft/mod/Mod.cpp index e613ddeb7..d5b96badd 100644 --- a/launcher/minecraft/mod/Mod.cpp +++ b/launcher/minecraft/mod/Mod.cpp @@ -166,6 +166,13 @@ auto Mod::homeurl() const -> QString return details().homeurl; } +auto Mod::metaurl() const -> QString +{ + if (metadata() == nullptr) + return homeurl(); + return ModPlatform::getMetaURL(metadata()->provider, metadata()->project_id); +} + auto Mod::description() const -> QString { return details().description; diff --git a/launcher/minecraft/mod/Mod.h b/launcher/minecraft/mod/Mod.h index d4e419f4f..d6272f4d0 100644 --- a/launcher/minecraft/mod/Mod.h +++ b/launcher/minecraft/mod/Mod.h @@ -70,6 +70,7 @@ public: auto provider() const -> std::optional; auto licenses() const -> const QList&; auto issueTracker() const -> QString; + auto metaurl() const -> QString; /** Get the intneral path to the mod's icon file*/ QString iconPath() const { return m_local_details.icon_file; }; diff --git a/launcher/modplatform/ModIndex.cpp b/launcher/modplatform/ModIndex.cpp index 6a507caf4..a1c4d8917 100644 --- a/launcher/modplatform/ModIndex.cpp +++ b/launcher/modplatform/ModIndex.cpp @@ -70,11 +70,17 @@ auto ProviderCapabilities::hash(ResourceProvider p, QIODevice* device, QString t } QCryptographicHash hash(algo); - if(!hash.addData(device)) + if (!hash.addData(device)) qCritical() << "Failed to read JAR to create hash!"; Q_ASSERT(hash.result().length() == hash.hashLength(algo)); return { hash.result().toHex() }; } +QString getMetaURL(ResourceProvider provider, QVariant projectID) +{ + return ((provider == ModPlatform::ResourceProvider::FLAME) ? "https://www.curseforge.com/projects/" : "https://modrinth.com/mod/") + + projectID.toString(); +} + } // namespace ModPlatform diff --git a/launcher/modplatform/ModIndex.h b/launcher/modplatform/ModIndex.h index 3b0a03a18..3f51e700f 100644 --- a/launcher/modplatform/ModIndex.h +++ b/launcher/modplatform/ModIndex.h @@ -144,6 +144,7 @@ inline auto getOverrideDeps() -> QList { "qvIfYCYJ", "P7dR8mSH", "API", ModPlatform::ResourceProvider::MODRINTH }, { "lwVhp9o5", "Ha28R6CL", "KotlinLibraries", ModPlatform::ResourceProvider::MODRINTH } }; }; +QString getMetaURL(ResourceProvider provider, QVariant projectID); } // namespace ModPlatform diff --git a/launcher/ui/pages/instance/ModFolderPage.cpp b/launcher/ui/pages/instance/ModFolderPage.cpp index 9722d4830..1d31a2925 100644 --- a/launcher/ui/pages/instance/ModFolderPage.cpp +++ b/launcher/ui/pages/instance/ModFolderPage.cpp @@ -298,17 +298,9 @@ bool NilModFolderPage::shouldDisplay() const void ModFolderPage::visitModPages() { auto selection = m_filterModel->mapSelectionToSource(ui->treeView->selectionModel()->selection()).indexes(); - for (auto mod : m_model->selectedMods(selection)) - if (auto meta = mod->metadata(); meta != nullptr) { - auto slug = meta->slug.remove(".pw.toml"); - switch (meta->provider) { - case ModPlatform::ResourceProvider::MODRINTH: - DesktopServices::openUrl(QString("https://modrinth.com/mod/%1").arg(slug)); - break; - case ModPlatform::ResourceProvider::FLAME: - DesktopServices::openUrl(QString("https://www.curseforge.com/minecraft/mc-mods/%1").arg(slug)); - break; - } - } else if (mod->homeurl().size() != 0) - DesktopServices::openUrl(mod->homeurl()); + for (auto mod : m_model->selectedMods(selection)) { + auto url = mod->metaurl(); + if (!url.isEmpty()) + DesktopServices::openUrl(url); + } } \ No newline at end of file diff --git a/launcher/ui/widgets/InfoFrame.cpp b/launcher/ui/widgets/InfoFrame.cpp index 52e79dc01..57562a931 100644 --- a/launcher/ui/widgets/InfoFrame.cpp +++ b/launcher/ui/widgets/InfoFrame.cpp @@ -41,9 +41,7 @@ #include "ui/dialogs/CustomMessageBox.h" -InfoFrame::InfoFrame(QWidget *parent) : - QFrame(parent), - ui(new Ui::InfoFrame) +InfoFrame::InfoFrame(QWidget* parent) : QFrame(parent), ui(new Ui::InfoFrame) { ui->setupUi(this); ui->descriptionLabel->setHidden(true); @@ -67,31 +65,18 @@ void InfoFrame::updateWithMod(Mod const& m) QString text = ""; QString name = ""; - QString link = ""; + QString link = m.metaurl(); QString toolTip = ""; if (m.name().isEmpty()) name = m.internal_id(); else name = m.name(); - if (auto meta = m.metadata(); meta != nullptr) { - auto slug = meta->slug.remove(".pw.toml"); - switch (meta->provider) { - case ModPlatform::ResourceProvider::MODRINTH: - link = QString("https://modrinth.com/mod/%1").arg(slug); - break; - case ModPlatform::ResourceProvider::FLAME: - link = QString("https://www.curseforge.com/minecraft/mc-mods/%1").arg(slug); - break; - } - } else if (!m.homeurl().isEmpty()) - link = m.homeurl(); - if (link.isEmpty()) text = name; else { text = "
    " + name + ""; - toolTip = tr("Go to mod's home page"); + toolTip = link; } if (!m.authors().isEmpty()) text += " by " + m.authors().join(", "); From 40fbae8ff684b6613ff073ec1992587b38dcdf8c Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sun, 25 Jun 2023 11:36:37 +0300 Subject: [PATCH 058/216] Fixed links tooltip Signed-off-by: Trial97 --- launcher/ui/widgets/InfoFrame.cpp | 36 ++++++++++++++++++++----------- launcher/ui/widgets/InfoFrame.h | 2 +- 2 files changed, 24 insertions(+), 14 deletions(-) diff --git a/launcher/ui/widgets/InfoFrame.cpp b/launcher/ui/widgets/InfoFrame.cpp index 57562a931..243490140 100644 --- a/launcher/ui/widgets/InfoFrame.cpp +++ b/launcher/ui/widgets/InfoFrame.cpp @@ -34,13 +34,24 @@ * limitations under the License. */ +#include #include +#include #include "InfoFrame.h" #include "ui_InfoFrame.h" #include "ui/dialogs/CustomMessageBox.h" +void setupLinkTooTip(QLabel* label) +{ + QObject::connect(label, &QLabel::linkHovered, [label](const QString& link) { + if (!link.isEmpty() && !link.startsWith("http")) + return; + label->setToolTip(link); + }); +} + InfoFrame::InfoFrame(QWidget* parent) : QFrame(parent), ui(new Ui::InfoFrame) { ui->setupUi(this); @@ -48,6 +59,12 @@ InfoFrame::InfoFrame(QWidget* parent) : QFrame(parent), ui(new Ui::InfoFrame) ui->nameLabel->setHidden(true); ui->licenseLabel->setHidden(true); ui->issueTrackerLabel->setHidden(true); + + setupLinkTooTip(ui->iconLabel); + setupLinkTooTip(ui->descriptionLabel); + setupLinkTooTip(ui->nameLabel); + setupLinkTooTip(ui->licenseLabel); + setupLinkTooTip(ui->issueTrackerLabel); updateHiddenState(); } @@ -66,7 +83,6 @@ void InfoFrame::updateWithMod(Mod const& m) QString text = ""; QString name = ""; QString link = m.metaurl(); - QString toolTip = ""; if (m.name().isEmpty()) name = m.internal_id(); else @@ -76,12 +92,11 @@ void InfoFrame::updateWithMod(Mod const& m) text = name; else { text = "" + name + ""; - toolTip = link; } if (!m.authors().isEmpty()) text += " by " + m.authors().join(", "); - setName(text, toolTip); + setName(text); if (m.description().isEmpty()) { setDescription(QString()); @@ -89,14 +104,14 @@ void InfoFrame::updateWithMod(Mod const& m) setDescription(m.description()); } - setImage(m.icon({64,64})); + setImage(m.icon({ 64, 64 })); auto licenses = m.licenses(); QString licenseText = ""; if (!licenses.empty()) { for (auto l : licenses) { if (!licenseText.isEmpty()) { - licenseText += "\n"; // add newline between licenses + licenseText += "\n"; // add newline between licenses } if (!l.name.isEmpty()) { if (l.url.isEmpty()) { @@ -226,29 +241,24 @@ void InfoFrame::updateHiddenState() } } -void InfoFrame::setName(QString text, QString toolTip) +void InfoFrame::setName(QString text) { if (text.isEmpty()) { ui->nameLabel->setHidden(true); - ui->nameLabel->setToolTip({}); } else { ui->nameLabel->setText(text); ui->nameLabel->setHidden(false); - ui->nameLabel->setToolTip(toolTip); } updateHiddenState(); } void InfoFrame::setDescription(QString text) { - if(text.isEmpty()) - { + if (text.isEmpty()) { ui->descriptionLabel->setHidden(true); updateHiddenState(); return; - } - else - { + } else { ui->descriptionLabel->setHidden(false); updateHiddenState(); } diff --git a/launcher/ui/widgets/InfoFrame.h b/launcher/ui/widgets/InfoFrame.h index b8c7e9a0b..d6764baa2 100644 --- a/launcher/ui/widgets/InfoFrame.h +++ b/launcher/ui/widgets/InfoFrame.h @@ -52,7 +52,7 @@ class InfoFrame : public QFrame { InfoFrame(QWidget* parent = nullptr); ~InfoFrame() override; - void setName(QString text = {}, QString toolTip = {}); + void setName(QString text = {}); void setDescription(QString text = {}); void setImage(QPixmap img = {}); void setLicense(QString text = {}); From fd5b155ee7d796015c84c8b348f384bf21d8328d Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sun, 25 Jun 2023 12:24:59 +0300 Subject: [PATCH 059/216] Added error message when exporting snapshots with curseforge Signed-off-by: Trial97 --- .../modplatform/flame/FlamePackExportTask.cpp | 18 +++++++++++------- launcher/ui/MainWindow.cpp | 9 ++++++++- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/launcher/modplatform/flame/FlamePackExportTask.cpp b/launcher/modplatform/flame/FlamePackExportTask.cpp index e73f3de59..e5eeb0980 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.cpp +++ b/launcher/modplatform/flame/FlamePackExportTask.cpp @@ -409,16 +409,20 @@ QByteArray FlamePackExportTask::generateIndex() // convert all available components to mrpack dependencies if (minecraft != nullptr) version["version"] = minecraft->m_version; - - QJsonObject loader; + QString id; if (quilt != nullptr) - loader["id"] = "quilt-" + quilt->getVersion(); + id = "quilt-" + quilt->getVersion(); else if (fabric != nullptr) - loader["id"] = "fabric-" + fabric->getVersion(); + id = "fabric-" + fabric->getVersion(); else if (forge != nullptr) - loader["id"] = "forge-" + forge->getVersion(); - loader["primary"] = true; - version["modLoaders"] = QJsonArray({ loader }); + id = "forge-" + forge->getVersion(); + version["modLoaders"] = QJsonArray(); + if (!id.isEmpty()) { + QJsonObject loader; + loader["id"] = id; + loader["primary"] = true; + version["modLoaders"] = QJsonArray({ loader }); + } obj["minecraft"] = version; } diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp index 91809c7b3..50eb9e64f 100644 --- a/launcher/ui/MainWindow.cpp +++ b/launcher/ui/MainWindow.cpp @@ -1422,9 +1422,16 @@ void MainWindow::on_actionExportInstanceFlamePack_triggered() if (m_selectedInstance) { auto instance = dynamic_cast(m_selectedInstance.get()); if (instance) { + QString errorMsg; if (instance->getPackProfile()->getComponent("org.quiltmc.quilt-loader")) { + errorMsg = tr("Quilt is currently not supported by CurseForge modpacks."); + } else if (auto cmp = instance->getPackProfile()->getComponent("net.minecraft"); + cmp && cmp->getVersionFile() && cmp->getVersionFile()->type == "snapshot") { + errorMsg = tr("Snapshots are currently not supported by CurseForge modpacks."); + } + if (!errorMsg.isEmpty()) { QMessageBox msgBox; - msgBox.setText(tr("Quilt is currently not supported by CurseForge modpacks.")); + msgBox.setText(errorMsg); msgBox.exec(); return; } From 84c63f4f017324b42c2470fb2e7a1ac5858fcaa0 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sun, 25 Jun 2023 14:11:41 +0300 Subject: [PATCH 060/216] Added plantxt export Signed-off-by: Trial97 --- launcher/CMakeLists.txt | 10 +- launcher/minecraft/mod/Mod.cpp | 7 + launcher/minecraft/mod/Mod.h | 1 + launcher/modplatform/ModIndex.cpp | 8 +- launcher/modplatform/ModIndex.h | 1 + ...dsToStringTask.cpp => ExportToModList.cpp} | 60 +++--- ...rtModsToStringTask.h => ExportToModList.h} | 10 +- launcher/ui/MainWindow.cpp | 8 +- launcher/ui/MainWindow.h | 2 +- launcher/ui/MainWindow.ui | 4 +- .../ui/dialogs/ExportModsToStringDialog.cpp | 122 ------------- launcher/ui/dialogs/ExportToModListDialog.cpp | 171 ++++++++++++++++++ ...StringDialog.h => ExportToModListDialog.h} | 16 +- ...ringDialog.ui => ExportToModListDialog.ui} | 38 +++- 14 files changed, 282 insertions(+), 176 deletions(-) rename launcher/modplatform/helpers/{ExportModsToStringTask.cpp => ExportToModList.cpp} (67%) rename launcher/modplatform/helpers/{ExportModsToStringTask.h => ExportToModList.h} (77%) delete mode 100644 launcher/ui/dialogs/ExportModsToStringDialog.cpp create mode 100644 launcher/ui/dialogs/ExportToModListDialog.cpp rename launcher/ui/dialogs/{ExportModsToStringDialog.h => ExportToModListDialog.h} (71%) rename launcher/ui/dialogs/{ExportModsToStringDialog.ui => ExportToModListDialog.ui} (82%) diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index aab7e90d1..a4e82576f 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -490,8 +490,8 @@ set(API_SOURCES modplatform/helpers/OverrideUtils.h modplatform/helpers/OverrideUtils.cpp - modplatform/helpers/ExportModsToStringTask.h - modplatform/helpers/ExportModsToStringTask.cpp + modplatform/helpers/ExportToModList.h + modplatform/helpers/ExportToModList.cpp ) set(FTB_SOURCES @@ -913,8 +913,8 @@ SET(LAUNCHER_SOURCES ui/dialogs/ExportInstanceDialog.h ui/dialogs/ExportMrPackDialog.cpp ui/dialogs/ExportMrPackDialog.h - ui/dialogs/ExportModsToStringDialog.cpp - ui/dialogs/ExportModsToStringDialog.h + ui/dialogs/ExportToModListDialog.cpp + ui/dialogs/ExportToModListDialog.h ui/dialogs/IconPickerDialog.cpp ui/dialogs/IconPickerDialog.h ui/dialogs/ImportResourceDialog.cpp @@ -1062,7 +1062,7 @@ qt_wrap_ui(LAUNCHER_UI ui/dialogs/SkinUploadDialog.ui ui/dialogs/ExportInstanceDialog.ui ui/dialogs/ExportMrPackDialog.ui - ui/dialogs/ExportModsToStringDialog.ui + ui/dialogs/ExportToModListDialog.ui ui/dialogs/IconPickerDialog.ui ui/dialogs/ImportResourceDialog.ui ui/dialogs/MSALoginDialog.ui diff --git a/launcher/minecraft/mod/Mod.cpp b/launcher/minecraft/mod/Mod.cpp index e613ddeb7..d5b96badd 100644 --- a/launcher/minecraft/mod/Mod.cpp +++ b/launcher/minecraft/mod/Mod.cpp @@ -166,6 +166,13 @@ auto Mod::homeurl() const -> QString return details().homeurl; } +auto Mod::metaurl() const -> QString +{ + if (metadata() == nullptr) + return homeurl(); + return ModPlatform::getMetaURL(metadata()->provider, metadata()->project_id); +} + auto Mod::description() const -> QString { return details().description; diff --git a/launcher/minecraft/mod/Mod.h b/launcher/minecraft/mod/Mod.h index d4e419f4f..d6272f4d0 100644 --- a/launcher/minecraft/mod/Mod.h +++ b/launcher/minecraft/mod/Mod.h @@ -70,6 +70,7 @@ public: auto provider() const -> std::optional; auto licenses() const -> const QList&; auto issueTracker() const -> QString; + auto metaurl() const -> QString; /** Get the intneral path to the mod's icon file*/ QString iconPath() const { return m_local_details.icon_file; }; diff --git a/launcher/modplatform/ModIndex.cpp b/launcher/modplatform/ModIndex.cpp index 6a507caf4..a1c4d8917 100644 --- a/launcher/modplatform/ModIndex.cpp +++ b/launcher/modplatform/ModIndex.cpp @@ -70,11 +70,17 @@ auto ProviderCapabilities::hash(ResourceProvider p, QIODevice* device, QString t } QCryptographicHash hash(algo); - if(!hash.addData(device)) + if (!hash.addData(device)) qCritical() << "Failed to read JAR to create hash!"; Q_ASSERT(hash.result().length() == hash.hashLength(algo)); return { hash.result().toHex() }; } +QString getMetaURL(ResourceProvider provider, QVariant projectID) +{ + return ((provider == ModPlatform::ResourceProvider::FLAME) ? "https://www.curseforge.com/projects/" : "https://modrinth.com/mod/") + + projectID.toString(); +} + } // namespace ModPlatform diff --git a/launcher/modplatform/ModIndex.h b/launcher/modplatform/ModIndex.h index 3b0a03a18..3f51e700f 100644 --- a/launcher/modplatform/ModIndex.h +++ b/launcher/modplatform/ModIndex.h @@ -144,6 +144,7 @@ inline auto getOverrideDeps() -> QList { "qvIfYCYJ", "P7dR8mSH", "API", ModPlatform::ResourceProvider::MODRINTH }, { "lwVhp9o5", "Ha28R6CL", "KotlinLibraries", ModPlatform::ResourceProvider::MODRINTH } }; }; +QString getMetaURL(ResourceProvider provider, QVariant projectID); } // namespace ModPlatform diff --git a/launcher/modplatform/helpers/ExportModsToStringTask.cpp b/launcher/modplatform/helpers/ExportToModList.cpp similarity index 67% rename from launcher/modplatform/helpers/ExportModsToStringTask.cpp rename to launcher/modplatform/helpers/ExportToModList.cpp index e7be5ce13..5e01367f9 100644 --- a/launcher/modplatform/helpers/ExportModsToStringTask.cpp +++ b/launcher/modplatform/helpers/ExportToModList.cpp @@ -15,11 +15,10 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -#include "ExportModsToStringTask.h" -#include "modplatform/ModIndex.h" +#include "ExportToModList.h" -namespace ExportToString { -QString ExportModsToStringTask(QList mods, Formats format, OptionalData extraData) +namespace ExportToModList { +QString ExportToModList(QList mods, Formats format, OptionalData extraData) { switch (format) { case HTML: { @@ -28,12 +27,7 @@ QString ExportModsToStringTask(QList mods, Formats format, OptionalData ex auto meta = mod->metadata(); auto modName = mod->name(); if (extraData & Url) { - auto url = mod->homeurl(); - if (meta != nullptr) { - url = (meta->provider == ModPlatform::ResourceProvider::FLAME ? "https://www.curseforge.com/minecraft/mc-mods/" - : "https://modrinth.com/mod/") + - meta->slug.remove(".pw.toml"); - } + auto url = mod->metaurl(); if (!url.isEmpty()) modName = QString("%2").arg(url, modName); } @@ -49,7 +43,7 @@ QString ExportModsToStringTask(QList mods, Formats format, OptionalData ex line += " by " + mod->authors().join(", "); lines.append(QString("
      %1
    ").arg(line)); } - return QString("\n\t%1\n").arg(lines.join("\n\t")); + return QString("
  • \n\t%1\n
  • ").arg(lines.join("\n\t")); } case MARKDOWN: { QStringList lines; @@ -57,12 +51,7 @@ QString ExportModsToStringTask(QList mods, Formats format, OptionalData ex auto meta = mod->metadata(); auto modName = mod->name(); if (extraData & Url) { - auto url = mod->homeurl(); - if (meta != nullptr) { - url = (meta->provider == ModPlatform::ResourceProvider::FLAME ? "https://www.curseforge.com/minecraft/mc-mods/" - : "https://modrinth.com/mod/") + - meta->slug.remove(".pw.toml"); - } + auto url = mod->metaurl(); if (!url.isEmpty()) modName = QString("[%1](%2)").arg(modName, url); } @@ -76,6 +65,31 @@ QString ExportModsToStringTask(QList mods, Formats format, OptionalData ex } if (extraData & Authors && !mod->authors().isEmpty()) line += " by " + mod->authors().join(", "); + lines << "- " + line; + } + return lines.join("\n"); + } + case PLAINTXT: { + QStringList lines; + for (auto mod : mods) { + auto meta = mod->metadata(); + auto modName = mod->name(); + + auto line = "name: " + modName + ";"; + if (extraData & Url) { + auto url = mod->metaurl(); + if (!url.isEmpty()) + line += " url: " + url + ";"; + } + if (extraData & Version) { + auto ver = mod->version(); + if (ver.isEmpty() && meta != nullptr) + ver = meta->version().toString(); + if (!ver.isEmpty()) + line += " version: " + QString("[%1]").arg(ver) + ";"; + } + if (extraData & Authors && !mod->authors().isEmpty()) + line += " authors " + mod->authors().join(", ") + ";"; lines << line; } return lines.join("\n"); @@ -86,19 +100,13 @@ QString ExportModsToStringTask(QList mods, Formats format, OptionalData ex } } -QString ExportModsToStringTask(QList mods, QString lineTemplate) +QString ExportToModList(QList mods, QString lineTemplate) { QStringList lines; for (auto mod : mods) { auto meta = mod->metadata(); auto modName = mod->name(); - - auto url = mod->homeurl(); - if (meta != nullptr) { - url = (meta->provider == ModPlatform::ResourceProvider::FLAME ? "https://www.curseforge.com/minecraft/mc-mods/" - : "https://modrinth.com/mod/") + - meta->slug.remove(".pw.toml"); - } + auto url = mod->metaurl(); auto ver = mod->version(); if (ver.isEmpty() && meta != nullptr) ver = meta->version().toString(); @@ -111,4 +119,4 @@ QString ExportModsToStringTask(QList mods, QString lineTemplate) } return lines.join("\n"); } -} // namespace ExportToString \ No newline at end of file +} // namespace ExportToModList \ No newline at end of file diff --git a/launcher/modplatform/helpers/ExportModsToStringTask.h b/launcher/modplatform/helpers/ExportToModList.h similarity index 77% rename from launcher/modplatform/helpers/ExportModsToStringTask.h rename to launcher/modplatform/helpers/ExportToModList.h index 756c69f77..9ff8d25a1 100644 --- a/launcher/modplatform/helpers/ExportModsToStringTask.h +++ b/launcher/modplatform/helpers/ExportToModList.h @@ -20,14 +20,14 @@ #include #include "minecraft/mod/Mod.h" -namespace ExportToString { +namespace ExportToModList { -enum Formats { HTML, MARKDOWN }; +enum Formats { HTML, MARKDOWN, PLAINTXT, CUSTOM }; enum OptionalData { Authors = 1 << 0, Url = 1 << 1, Version = 1 << 2, }; -QString ExportModsToStringTask(QList mods, Formats format, OptionalData extraData); -QString ExportModsToStringTask(QList mods, QString lineTemplate); -} // namespace ExportToString +QString ExportToModList(QList mods, Formats format, OptionalData extraData); +QString ExportToModList(QList mods, QString lineTemplate); +} // namespace ExportToModList diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp index 02ea30c36..37f4d4ed5 100644 --- a/launcher/ui/MainWindow.cpp +++ b/launcher/ui/MainWindow.cpp @@ -43,7 +43,7 @@ #include "FileSystem.h" #include "MainWindow.h" -#include "ui/dialogs/ExportModsToStringDialog.h" +#include "ui/dialogs/ExportToModListDialog.h" #include "ui_MainWindow.h" #include @@ -206,7 +206,7 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi auto exportInstanceMenu = new QMenu(this); exportInstanceMenu->addAction(ui->actionExportInstanceZip); exportInstanceMenu->addAction(ui->actionExportInstanceMrPack); - exportInstanceMenu->addAction(ui->actionExportInstanceToString); + exportInstanceMenu->addAction(ui->actionExportInstanceToModList); ui->actionExportInstance->setMenu(exportInstanceMenu); } @@ -1418,10 +1418,10 @@ void MainWindow::on_actionExportInstanceMrPack_triggered() } } -void MainWindow::on_actionExportInstanceToString_triggered() +void MainWindow::on_actionExportInstanceToModList_triggered() { if (m_selectedInstance) { - ExportModsToStringDialog dlg(m_selectedInstance, this); + ExportToModListDialog dlg(m_selectedInstance, this); dlg.exec(); } } diff --git a/launcher/ui/MainWindow.h b/launcher/ui/MainWindow.h index 9b38810f0..f62e39e15 100644 --- a/launcher/ui/MainWindow.h +++ b/launcher/ui/MainWindow.h @@ -157,7 +157,7 @@ private slots: inline void on_actionExportInstance_triggered() { on_actionExportInstanceZip_triggered(); } void on_actionExportInstanceZip_triggered(); void on_actionExportInstanceMrPack_triggered(); - void on_actionExportInstanceToString_triggered(); + void on_actionExportInstanceToModList_triggered(); void on_actionRenameInstance_triggered(); diff --git a/launcher/ui/MainWindow.ui b/launcher/ui/MainWindow.ui index ecc7e2362..027742ba4 100644 --- a/launcher/ui/MainWindow.ui +++ b/launcher/ui/MainWindow.ui @@ -479,12 +479,12 @@ Modrinth (mrpack)
    - + - Text + ModList (txt) diff --git a/launcher/ui/dialogs/ExportModsToStringDialog.cpp b/launcher/ui/dialogs/ExportModsToStringDialog.cpp deleted file mode 100644 index 29d69918e..000000000 --- a/launcher/ui/dialogs/ExportModsToStringDialog.cpp +++ /dev/null @@ -1,122 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-only -/* - * Prism Launcher - Minecraft Launcher - * Copyright (c) 2023 Trial97 - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "ExportModsToStringDialog.h" -#include -#include -#include -#include "minecraft/MinecraftInstance.h" -#include "minecraft/mod/ModFolderModel.h" -#include "modplatform/helpers/ExportModsToStringTask.h" -#include "ui_ExportModsToStringDialog.h" - -#include -#include -#include -#include -#include - -ExportModsToStringDialog::ExportModsToStringDialog(InstancePtr instance, QWidget* parent) - : QDialog(parent), m_template_selected(false), ui(new Ui::ExportModsToStringDialog) -{ - ui->setupUi(this); - ui->templateGroup->setDisabled(true); - - MinecraftInstance* mcInstance = dynamic_cast(instance.get()); - if (mcInstance) { - mcInstance->loaderModList()->update(); - connect(mcInstance->loaderModList().get(), &ModFolderModel::updateFinished, this, [this, mcInstance]() { - m_allMods = mcInstance->loaderModList()->allMods(); - triggerImp(); - }); - } - - connect(ui->formatComboBox, QOverload::of(&QComboBox::currentIndexChanged), this, &ExportModsToStringDialog::formatChanged); - connect(ui->authorsCheckBox, &QCheckBox::stateChanged, this, &ExportModsToStringDialog::trigger); - connect(ui->versionCheckBox, &QCheckBox::stateChanged, this, &ExportModsToStringDialog::trigger); - connect(ui->urlCheckBox, &QCheckBox::stateChanged, this, &ExportModsToStringDialog::trigger); - connect(ui->templateText, &QTextEdit::textChanged, this, &ExportModsToStringDialog::triggerImp); - connect(ui->copyButton, &QPushButton::clicked, this, [this](bool) { - this->ui->finalText->selectAll(); - this->ui->finalText->copy(); - }); -} - -ExportModsToStringDialog::~ExportModsToStringDialog() -{ - delete ui; -} - -void ExportModsToStringDialog::formatChanged(int index) -{ - switch (index) { - case 0: { - ui->templateGroup->setDisabled(true); - ui->optionsGroup->setDisabled(false); - break; - } - case 1: { - ui->templateGroup->setDisabled(true); - ui->optionsGroup->setDisabled(false); - break; - } - case 2: { - ui->templateGroup->setDisabled(false); - ui->optionsGroup->setDisabled(true); - break; - } - } - triggerImp(); -} - -void ExportModsToStringDialog::triggerImp() -{ - auto format = ExportToString::HTML; - switch (ui->formatComboBox->currentIndex()) { - case 2: { - m_template_selected = true; - ui->finalText->setPlainText(ExportToString::ExportModsToStringTask(m_allMods, ui->templateText->toPlainText())); - return; - } - case 0: { - format = ExportToString::HTML; - break; - } - case 1: { - format = ExportToString::MARKDOWN; - break; - } - default: { - return; - } - } - auto opt = 0; - if (ui->authorsCheckBox->isChecked()) - opt |= ExportToString::Authors; - if (ui->versionCheckBox->isChecked()) - opt |= ExportToString::Version; - if (ui->urlCheckBox->isChecked()) - opt |= ExportToString::Url; - ui->finalText->setPlainText(ExportToString::ExportModsToStringTask(m_allMods, format, static_cast(opt))); - if (!m_template_selected) { - auto exampleLine = format == ExportToString::HTML ? "
      {name}[{version}] by {authors}
    " - : "[{name}]({url})[{version}] by {authors}"; - if (ui->templateText->toPlainText() != exampleLine) - ui->templateText->setPlainText(exampleLine); - } -} diff --git a/launcher/ui/dialogs/ExportToModListDialog.cpp b/launcher/ui/dialogs/ExportToModListDialog.cpp new file mode 100644 index 000000000..0550725f6 --- /dev/null +++ b/launcher/ui/dialogs/ExportToModListDialog.cpp @@ -0,0 +1,171 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (c) 2023 Trial97 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "ExportToModListDialog.h" +#include +#include +#include +#include "FileSystem.h" +#include "minecraft/MinecraftInstance.h" +#include "minecraft/mod/ModFolderModel.h" +#include "modplatform/helpers/ExportToModList.h" +#include "ui_ExportToModListDialog.h" + +#include +#include +#include +#include +#include + +ExportToModListDialog::ExportToModListDialog(InstancePtr instance, QWidget* parent) + : QDialog(parent), m_template_selected(false), name(instance->name()), ui(new Ui::ExportToModListDialog) +{ + ui->setupUi(this); + ui->templateGroup->setDisabled(true); + + MinecraftInstance* mcInstance = dynamic_cast(instance.get()); + if (mcInstance) { + mcInstance->loaderModList()->update(); + connect(mcInstance->loaderModList().get(), &ModFolderModel::updateFinished, this, [this, mcInstance]() { + m_allMods = mcInstance->loaderModList()->allMods(); + triggerImp(); + }); + } + + connect(ui->formatComboBox, QOverload::of(&QComboBox::currentIndexChanged), this, &ExportToModListDialog::formatChanged); + connect(ui->authorsCheckBox, &QCheckBox::stateChanged, this, &ExportToModListDialog::trigger); + connect(ui->versionCheckBox, &QCheckBox::stateChanged, this, &ExportToModListDialog::trigger); + connect(ui->urlCheckBox, &QCheckBox::stateChanged, this, &ExportToModListDialog::trigger); + connect(ui->templateText, &QTextEdit::textChanged, this, &ExportToModListDialog::triggerImp); + connect(ui->copyButton, &QPushButton::clicked, this, [this](bool) { + this->ui->finalText->selectAll(); + this->ui->finalText->copy(); + }); +} + +ExportToModListDialog::~ExportToModListDialog() +{ + delete ui; +} + +void ExportToModListDialog::formatChanged(int index) +{ + switch (index) { + case 0: { + ui->templateGroup->setDisabled(true); + ui->optionsGroup->setDisabled(false); + ui->resultText->show(); + format = ExportToModList::HTML; + break; + } + case 1: { + ui->templateGroup->setDisabled(true); + ui->optionsGroup->setDisabled(false); + ui->resultText->show(); + format = ExportToModList::MARKDOWN; + break; + } + case 2: { + ui->templateGroup->setDisabled(true); + ui->optionsGroup->setDisabled(false); + ui->resultText->hide(); + format = ExportToModList::PLAINTXT; + break; + } + case 3: { + ui->templateGroup->setDisabled(false); + ui->optionsGroup->setDisabled(true); + ui->resultText->hide(); + format = ExportToModList::CUSTOM; + break; + } + } + triggerImp(); +} + +void ExportToModListDialog::triggerImp() +{ + if (format == ExportToModList::CUSTOM) { + m_template_selected = true; + ui->finalText->setPlainText(ExportToModList::ExportToModList(m_allMods, ui->templateText->toPlainText())); + return; + } + auto opt = 0; + if (ui->authorsCheckBox->isChecked()) + opt |= ExportToModList::Authors; + if (ui->versionCheckBox->isChecked()) + opt |= ExportToModList::Version; + if (ui->urlCheckBox->isChecked()) + opt |= ExportToModList::Url; + auto txt = ExportToModList::ExportToModList(m_allMods, format, static_cast(opt)); + ui->finalText->setPlainText(txt); + QString exampleLine; + switch (format) { + case ExportToModList::HTML: { + exampleLine = "
      {name}[{version}] by {authors}
    "; + ui->resultText->setHtml(txt); + break; + } + case ExportToModList::MARKDOWN: { + exampleLine = "[{name}]({url})[{version}] by {authors}"; + ui->resultText->setMarkdown(txt); + break; + } + case ExportToModList::PLAINTXT: { + exampleLine = "name: {name}; url: {url}; version: {version}; authors: {authors};"; + break; + } + case ExportToModList::CUSTOM: + return; + } + if (!m_template_selected) { + if (ui->templateText->toPlainText() != exampleLine) + ui->templateText->setPlainText(exampleLine); + } +} + +void ExportToModListDialog::done(int result) +{ + if (result == Accepted) { + const QString filename = FS::RemoveInvalidFilenameChars(name); + const QString output = + QFileDialog::getSaveFileName(this, tr("Export %1").arg(name), FS::PathCombine(QDir::homePath(), filename + extension()), + "File (*.txt *.html *.md)", nullptr); + + if (output.isEmpty()) + return; + FS::write(output, ui->finalText->toPlainText().toUtf8()); + } + + QDialog::done(result); +} + +QString ExportToModListDialog::extension() +{ + switch (format) { + case ExportToModList::HTML: + return ".html"; + case ExportToModList::MARKDOWN: + return ".md"; + case ExportToModList::PLAINTXT: + return ".txt"; + case ExportToModList::CUSTOM: + return ".txt"; + } + return ".txt"; +} diff --git a/launcher/ui/dialogs/ExportModsToStringDialog.h b/launcher/ui/dialogs/ExportToModListDialog.h similarity index 71% rename from launcher/ui/dialogs/ExportModsToStringDialog.h rename to launcher/ui/dialogs/ExportToModListDialog.h index d195d1cec..a7a6bcdce 100644 --- a/launcher/ui/dialogs/ExportModsToStringDialog.h +++ b/launcher/ui/dialogs/ExportToModListDialog.h @@ -22,17 +22,20 @@ #include #include "BaseInstance.h" #include "minecraft/mod/Mod.h" +#include "modplatform/helpers/ExportToModList.h" namespace Ui { -class ExportModsToStringDialog; +class ExportToModListDialog; } -class ExportModsToStringDialog : public QDialog { +class ExportToModListDialog : public QDialog { Q_OBJECT public: - explicit ExportModsToStringDialog(InstancePtr instance, QWidget* parent = nullptr); - ~ExportModsToStringDialog(); + explicit ExportToModListDialog(InstancePtr instance, QWidget* parent = nullptr); + ~ExportToModListDialog(); + + void done(int result) override; protected slots: void formatChanged(int index); @@ -40,7 +43,10 @@ class ExportModsToStringDialog : public QDialog { void trigger(int) { triggerImp(); }; private: + QString extension(); QList m_allMods; bool m_template_selected; - Ui::ExportModsToStringDialog* ui; + QString name; + ExportToModList::Formats format = ExportToModList::Formats::HTML; + Ui::ExportToModListDialog* ui; }; diff --git a/launcher/ui/dialogs/ExportModsToStringDialog.ui b/launcher/ui/dialogs/ExportToModListDialog.ui similarity index 82% rename from launcher/ui/dialogs/ExportModsToStringDialog.ui rename to launcher/ui/dialogs/ExportToModListDialog.ui index 4451a2785..640b17665 100644 --- a/launcher/ui/dialogs/ExportModsToStringDialog.ui +++ b/launcher/ui/dialogs/ExportToModListDialog.ui @@ -1,7 +1,7 @@ - ExportModsToStringDialog - + ExportToModListDialog + 0 @@ -11,7 +11,7 @@ - Export Modrinth Pack + Export Pack to ModList true @@ -53,6 +53,11 @@ Markdown + + + Plaintext + + Custom @@ -124,6 +129,13 @@ + + + + true + + + @@ -141,7 +153,7 @@ - QDialogButtonBox::Ok + QDialogButtonBox::Cancel|QDialogButtonBox::Save @@ -154,7 +166,7 @@ buttonBox accepted() - ExportModsToStringDialog + ExportToModListDialog accept() @@ -167,5 +179,21 @@ + + buttonBox + rejected() + ExportToModListDialog + reject() + + + 324 + 390 + + + 324 + 206 + + + From d1603f19459a499e5278f38b69222e3f4e0875b4 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sun, 25 Jun 2023 14:43:11 +0300 Subject: [PATCH 061/216] Made it more similar to mrpack export Signed-off-by: Trial97 --- .../modplatform/flame/FlamePackExportTask.cpp | 67 ++++++++++++++----- .../modplatform/flame/FlamePackExportTask.h | 2 + 2 files changed, 51 insertions(+), 18 deletions(-) diff --git a/launcher/modplatform/flame/FlamePackExportTask.cpp b/launcher/modplatform/flame/FlamePackExportTask.cpp index e5eeb0980..b14c6eb4b 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.cpp +++ b/launcher/modplatform/flame/FlamePackExportTask.cpp @@ -37,6 +37,8 @@ #include "tasks/Task.h" const QString FlamePackExportTask::TEMPLATE = "
  • {name}{authors}
  • \n"; +const QStringList FlamePackExportTask::PREFIXES({ "mods/", "resourcepacks/" }); +const QStringList FlamePackExportTask::FILE_EXTENSIONS({ "jar", "zip" }); FlamePackExportTask::FlamePackExportTask(const QString& name, const QString& version, @@ -105,33 +107,62 @@ void FlamePackExportTask::collectHashes() { setAbortable(true); setStatus(tr("Find file hashes...")); - auto mods = mcInstance->loaderModList()->allMods(); + auto allMods = mcInstance->loaderModList()->allMods(); ConcurrentTask::Ptr hashing_task(new ConcurrentTask(this, "MakeHashesTask", 10)); task.reset(hashing_task); - int totalProgres = mods.count(); + int totalProgres = allMods.count(); setProgress(0, totalProgres); - for (auto* mod : mods) { - if (!mod || mod->type() == ResourceType::FOLDER) { - setProgress(m_progress + 1, totalProgres); + + for (const QFileInfo& file : files) { + const QString relative = gameRoot.relativeFilePath(file.absoluteFilePath()); + // require sensible file types + if (!std::any_of(PREFIXES.begin(), PREFIXES.end(), [&relative](const QString& prefix) { return relative.startsWith(prefix); })) continue; - } - if (mod->metadata() && mod->metadata()->provider == ModPlatform::ResourceProvider::FLAME) { - resolvedFiles.insert(mod->fileinfo().absoluteFilePath(), - { mod->metadata()->project_id.toInt(), mod->metadata()->file_id.toInt(), mod->enabled(), true, - mod->metadata()->name, mod->metadata()->slug, mod->authors().join(", ") }); - setProgress(m_progress + 1, totalProgres); + if (!std::any_of(FILE_EXTENSIONS.begin(), FILE_EXTENSIONS.end(), [&relative](const QString& extension) { + return relative.endsWith('.' + extension) || relative.endsWith('.' + extension + ".disabled"); + })) + continue; + + if (relative.startsWith("resourcepacks/") && + (relative.endsWith(".zip") || relative.endsWith(".zip.disabled"))) { // is resourcepack + totalProgres++; + auto hash_task = Hashing::createFlameHasher(file.absoluteFilePath()); + connect(hash_task.get(), &Hashing::Hasher::resultsReady, [this, relative, file, totalProgres](QString hash) { + if (m_state == Task::State::Running) { + setProgress(m_progress + 1, totalProgres); + pendingHashes.insert(hash, { relative, file.absoluteFilePath(), relative.endsWith(".zip") }); + } + }); + connect(hash_task.get(), &Task::failed, this, &FlamePackExportTask::emitFailed); + hashing_task->addTask(hash_task); continue; } - auto hash_task = Hashing::createFlameHasher(mod->fileinfo().absoluteFilePath()); - connect(hash_task.get(), &Hashing::Hasher::resultsReady, [this, mod, totalProgres](QString hash) { - if (m_state == Task::State::Running) { + if (auto modIter = std::find_if(allMods.begin(), allMods.end(), [&file](Mod* mod) { return mod->fileinfo() == file; }); + modIter != allMods.end()) { + const Mod* mod = *modIter; + if (!mod || mod->type() == ResourceType::FOLDER) { setProgress(m_progress + 1, totalProgres); - pendingHashes.insert(hash, { mod->name(), mod->fileinfo().absoluteFilePath(), mod->enabled(), true }); + continue; } - }); - connect(hash_task.get(), &Task::failed, this, &FlamePackExportTask::emitFailed); - hashing_task->addTask(hash_task); + if (mod->metadata() && mod->metadata()->provider == ModPlatform::ResourceProvider::FLAME) { + resolvedFiles.insert(mod->fileinfo().absoluteFilePath(), + { mod->metadata()->project_id.toInt(), mod->metadata()->file_id.toInt(), mod->enabled(), true, + mod->metadata()->name, mod->metadata()->slug, mod->authors().join(", ") }); + setProgress(m_progress + 1, totalProgres); + continue; + } + + auto hash_task = Hashing::createFlameHasher(mod->fileinfo().absoluteFilePath()); + connect(hash_task.get(), &Hashing::Hasher::resultsReady, [this, mod, totalProgres](QString hash) { + if (m_state == Task::State::Running) { + setProgress(m_progress + 1, totalProgres); + pendingHashes.insert(hash, { mod->name(), mod->fileinfo().absoluteFilePath(), mod->enabled(), true }); + } + }); + connect(hash_task.get(), &Task::failed, this, &FlamePackExportTask::emitFailed); + hashing_task->addTask(hash_task); + } } for (const QFileInfo& file : files) { diff --git a/launcher/modplatform/flame/FlamePackExportTask.h b/launcher/modplatform/flame/FlamePackExportTask.h index 5c8caa458..b6a6c3529 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.h +++ b/launcher/modplatform/flame/FlamePackExportTask.h @@ -42,6 +42,8 @@ class FlamePackExportTask : public Task { private: static const QString TEMPLATE; + static const QStringList PREFIXES; + static const QStringList FILE_EXTENSIONS; // inputs const QString name, version, author; From 8d3bc6b6b94ff5fb2dba0c06bf6d108794af7d8f Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sun, 25 Jun 2023 14:58:54 +0300 Subject: [PATCH 062/216] Added markdown QT version check Signed-off-by: Trial97 --- launcher/ui/dialogs/ExportToModListDialog.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/launcher/ui/dialogs/ExportToModListDialog.cpp b/launcher/ui/dialogs/ExportToModListDialog.cpp index 0550725f6..715a62c34 100644 --- a/launcher/ui/dialogs/ExportToModListDialog.cpp +++ b/launcher/ui/dialogs/ExportToModListDialog.cpp @@ -76,7 +76,11 @@ void ExportToModListDialog::formatChanged(int index) case 1: { ui->templateGroup->setDisabled(true); ui->optionsGroup->setDisabled(false); +#if QT_VERSION >= QT_VERSION_CHECK(6, 1, 0) ui->resultText->show(); +#else + ui->resultText->hide(); +#endif format = ExportToModList::MARKDOWN; break; } @@ -123,7 +127,9 @@ void ExportToModListDialog::triggerImp() } case ExportToModList::MARKDOWN: { exampleLine = "[{name}]({url})[{version}] by {authors}"; +#if QT_VERSION >= QT_VERSION_CHECK(6, 1, 0) ui->resultText->setMarkdown(txt); +#endif break; } case ExportToModList::PLAINTXT: { From 3546f57a42eb23053772eb5b84cb864f9c83b166 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sun, 25 Jun 2023 15:17:09 +0300 Subject: [PATCH 063/216] Use internal markdown implementation Signed-off-by: Trial97 --- launcher/ui/dialogs/ExportToModListDialog.cpp | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/launcher/ui/dialogs/ExportToModListDialog.cpp b/launcher/ui/dialogs/ExportToModListDialog.cpp index 715a62c34..57ee44537 100644 --- a/launcher/ui/dialogs/ExportToModListDialog.cpp +++ b/launcher/ui/dialogs/ExportToModListDialog.cpp @@ -21,6 +21,7 @@ #include #include #include "FileSystem.h" +#include "Markdown.h" #include "minecraft/MinecraftInstance.h" #include "minecraft/mod/ModFolderModel.h" #include "modplatform/helpers/ExportToModList.h" @@ -76,11 +77,7 @@ void ExportToModListDialog::formatChanged(int index) case 1: { ui->templateGroup->setDisabled(true); ui->optionsGroup->setDisabled(false); -#if QT_VERSION >= QT_VERSION_CHECK(6, 1, 0) ui->resultText->show(); -#else - ui->resultText->hide(); -#endif format = ExportToModList::MARKDOWN; break; } @@ -127,9 +124,7 @@ void ExportToModListDialog::triggerImp() } case ExportToModList::MARKDOWN: { exampleLine = "[{name}]({url})[{version}] by {authors}"; -#if QT_VERSION >= QT_VERSION_CHECK(6, 1, 0) - ui->resultText->setMarkdown(txt); -#endif + ui->resultText->setHtml(markdownToHTML(txt)); break; } case ExportToModList::PLAINTXT: { From fa3a46498f7fe4a7d6e26558c03b0485126b377c Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sun, 25 Jun 2023 16:23:50 +0300 Subject: [PATCH 064/216] Removed dupliacte code Signed-off-by: Trial97 --- .../modplatform/flame/FlamePackExportTask.cpp | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/launcher/modplatform/flame/FlamePackExportTask.cpp b/launcher/modplatform/flame/FlamePackExportTask.cpp index b14c6eb4b..cbb57afa6 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.cpp +++ b/launcher/modplatform/flame/FlamePackExportTask.cpp @@ -165,21 +165,6 @@ void FlamePackExportTask::collectHashes() } } - for (const QFileInfo& file : files) { - const QString relative = gameRoot.relativeFilePath(file.absoluteFilePath()); - if (!relative.endsWith(".zip") || !relative.startsWith("resourcepacks/")) - continue; - totalProgres++; - auto hash_task = Hashing::createFlameHasher(file.absoluteFilePath()); - connect(hash_task.get(), &Hashing::Hasher::resultsReady, [this, relative, file, totalProgres](QString hash) { - if (m_state == Task::State::Running) { - setProgress(m_progress + 1, totalProgres); - pendingHashes.insert(hash, { relative, file.absoluteFilePath(), true }); - } - }); - connect(hash_task.get(), &Task::failed, this, &FlamePackExportTask::emitFailed); - hashing_task->addTask(hash_task); - } connect(hashing_task.get(), &Task::succeeded, this, &FlamePackExportTask::makeApiRequest); connect(hashing_task.get(), &Task::failed, this, &FlamePackExportTask::emitFailed); hashing_task->start(); From 8ade44c9a3b186fb5ab19d9802a4d7b4187b7258 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Sun, 25 Jun 2023 14:39:45 +0100 Subject: [PATCH 065/216] Simplify Signed-off-by: TheKodeToad --- launcher/modplatform/flame/FlamePackExportTask.cpp | 3 --- launcher/modplatform/flame/FlamePackExportTask.h | 1 - 2 files changed, 4 deletions(-) diff --git a/launcher/modplatform/flame/FlamePackExportTask.cpp b/launcher/modplatform/flame/FlamePackExportTask.cpp index cbb57afa6..1460a4c3b 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.cpp +++ b/launcher/modplatform/flame/FlamePackExportTask.cpp @@ -37,7 +37,6 @@ #include "tasks/Task.h" const QString FlamePackExportTask::TEMPLATE = "
  • {name}{authors}
  • \n"; -const QStringList FlamePackExportTask::PREFIXES({ "mods/", "resourcepacks/" }); const QStringList FlamePackExportTask::FILE_EXTENSIONS({ "jar", "zip" }); FlamePackExportTask::FlamePackExportTask(const QString& name, @@ -116,8 +115,6 @@ void FlamePackExportTask::collectHashes() for (const QFileInfo& file : files) { const QString relative = gameRoot.relativeFilePath(file.absoluteFilePath()); // require sensible file types - if (!std::any_of(PREFIXES.begin(), PREFIXES.end(), [&relative](const QString& prefix) { return relative.startsWith(prefix); })) - continue; if (!std::any_of(FILE_EXTENSIONS.begin(), FILE_EXTENSIONS.end(), [&relative](const QString& extension) { return relative.endsWith('.' + extension) || relative.endsWith('.' + extension + ".disabled"); })) diff --git a/launcher/modplatform/flame/FlamePackExportTask.h b/launcher/modplatform/flame/FlamePackExportTask.h index b6a6c3529..3dee0a7ea 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.h +++ b/launcher/modplatform/flame/FlamePackExportTask.h @@ -42,7 +42,6 @@ class FlamePackExportTask : public Task { private: static const QString TEMPLATE; - static const QStringList PREFIXES; static const QStringList FILE_EXTENSIONS; // inputs From 288ea3d19b6edbd2b4570408e71e635df0d7abfe Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Sun, 25 Jun 2023 14:52:33 +0100 Subject: [PATCH 066/216] Remove metaurl function Signed-off-by: TheKodeToad --- launcher/minecraft/mod/Mod.cpp | 7 ------- launcher/minecraft/mod/Mod.h | 1 - 2 files changed, 8 deletions(-) diff --git a/launcher/minecraft/mod/Mod.cpp b/launcher/minecraft/mod/Mod.cpp index d5b96badd..e613ddeb7 100644 --- a/launcher/minecraft/mod/Mod.cpp +++ b/launcher/minecraft/mod/Mod.cpp @@ -166,13 +166,6 @@ auto Mod::homeurl() const -> QString return details().homeurl; } -auto Mod::metaurl() const -> QString -{ - if (metadata() == nullptr) - return homeurl(); - return ModPlatform::getMetaURL(metadata()->provider, metadata()->project_id); -} - auto Mod::description() const -> QString { return details().description; diff --git a/launcher/minecraft/mod/Mod.h b/launcher/minecraft/mod/Mod.h index d6272f4d0..d4e419f4f 100644 --- a/launcher/minecraft/mod/Mod.h +++ b/launcher/minecraft/mod/Mod.h @@ -70,7 +70,6 @@ public: auto provider() const -> std::optional; auto licenses() const -> const QList&; auto issueTracker() const -> QString; - auto metaurl() const -> QString; /** Get the intneral path to the mod's icon file*/ QString iconPath() const { return m_local_details.icon_file; }; From d344ffe37047037bd3bca070557a49fbfadcb361 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sun, 25 Jun 2023 17:50:56 +0300 Subject: [PATCH 067/216] Removed some setProgress calls Signed-off-by: Trial97 --- launcher/modplatform/flame/FlamePackExportTask.cpp | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/launcher/modplatform/flame/FlamePackExportTask.cpp b/launcher/modplatform/flame/FlamePackExportTask.cpp index cbb57afa6..c781ece5b 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.cpp +++ b/launcher/modplatform/flame/FlamePackExportTask.cpp @@ -110,8 +110,7 @@ void FlamePackExportTask::collectHashes() auto allMods = mcInstance->loaderModList()->allMods(); ConcurrentTask::Ptr hashing_task(new ConcurrentTask(this, "MakeHashesTask", 10)); task.reset(hashing_task); - int totalProgres = allMods.count(); - setProgress(0, totalProgres); + int totalProgres = 0; for (const QFileInfo& file : files) { const QString relative = gameRoot.relativeFilePath(file.absoluteFilePath()); @@ -142,17 +141,16 @@ void FlamePackExportTask::collectHashes() modIter != allMods.end()) { const Mod* mod = *modIter; if (!mod || mod->type() == ResourceType::FOLDER) { - setProgress(m_progress + 1, totalProgres); continue; } if (mod->metadata() && mod->metadata()->provider == ModPlatform::ResourceProvider::FLAME) { resolvedFiles.insert(mod->fileinfo().absoluteFilePath(), { mod->metadata()->project_id.toInt(), mod->metadata()->file_id.toInt(), mod->enabled(), true, mod->metadata()->name, mod->metadata()->slug, mod->authors().join(", ") }); - setProgress(m_progress + 1, totalProgres); continue; } + totalProgres++; auto hash_task = Hashing::createFlameHasher(mod->fileinfo().absoluteFilePath()); connect(hash_task.get(), &Hashing::Hasher::resultsReady, [this, mod, totalProgres](QString hash) { if (m_state == Task::State::Running) { @@ -209,9 +207,7 @@ void FlamePackExportTask::makeApiRequest() return; } - size_t progress = 0; for (auto match : data_arr) { - setProgress(progress++, data_arr.count()); auto match_obj = Json::ensureObject(match, {}); auto file_obj = Json::ensureObject(match_obj, "file", {}); @@ -284,9 +280,7 @@ void FlamePackExportTask::getProjectsInfo() else entries = Json::requireArray(Json::requireObject(doc), "data"); - size_t progress = 0; for (auto entry : entries) { - setProgress(progress++, entries.count()); auto entry_obj = Json::requireObject(entry); try { From 87155e346c33288fccb68c3b9029a11b658395b2 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sun, 25 Jun 2023 19:44:18 +0300 Subject: [PATCH 068/216] Complicated a little task progress Signed-off-by: Trial97 --- .../modplatform/flame/FlamePackExportTask.cpp | 54 ++++++++++++++----- 1 file changed, 40 insertions(+), 14 deletions(-) diff --git a/launcher/modplatform/flame/FlamePackExportTask.cpp b/launcher/modplatform/flame/FlamePackExportTask.cpp index dfad364f3..13308b50a 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.cpp +++ b/launcher/modplatform/flame/FlamePackExportTask.cpp @@ -58,7 +58,7 @@ FlamePackExportTask::FlamePackExportTask(const QString& name, void FlamePackExportTask::executeTask() { setStatus(tr("Searching for files...")); - setProgress(0, 0); + setProgress(0, 5); collectFiles(); } @@ -106,11 +106,10 @@ void FlamePackExportTask::collectHashes() { setAbortable(true); setStatus(tr("Find file hashes...")); + setProgress(1, 5); auto allMods = mcInstance->loaderModList()->allMods(); ConcurrentTask::Ptr hashing_task(new ConcurrentTask(this, "MakeHashesTask", 10)); task.reset(hashing_task); - int totalProgres = 0; - for (const QFileInfo& file : files) { const QString relative = gameRoot.relativeFilePath(file.absoluteFilePath()); // require sensible file types @@ -121,11 +120,9 @@ void FlamePackExportTask::collectHashes() if (relative.startsWith("resourcepacks/") && (relative.endsWith(".zip") || relative.endsWith(".zip.disabled"))) { // is resourcepack - totalProgres++; auto hash_task = Hashing::createFlameHasher(file.absoluteFilePath()); - connect(hash_task.get(), &Hashing::Hasher::resultsReady, [this, relative, file, totalProgres](QString hash) { + connect(hash_task.get(), &Hashing::Hasher::resultsReady, [this, relative, file](QString hash) { if (m_state == Task::State::Running) { - setProgress(m_progress + 1, totalProgres); pendingHashes.insert(hash, { relative, file.absoluteFilePath(), relative.endsWith(".zip") }); } }); @@ -147,11 +144,9 @@ void FlamePackExportTask::collectHashes() continue; } - totalProgres++; auto hash_task = Hashing::createFlameHasher(mod->fileinfo().absoluteFilePath()); - connect(hash_task.get(), &Hashing::Hasher::resultsReady, [this, mod, totalProgres](QString hash) { + connect(hash_task.get(), &Hashing::Hasher::resultsReady, [this, mod](QString hash) { if (m_state == Task::State::Running) { - setProgress(m_progress + 1, totalProgres); pendingHashes.insert(hash, { mod->name(), mod->fileinfo().absoluteFilePath(), mod->enabled(), true }); } }); @@ -159,9 +154,28 @@ void FlamePackExportTask::collectHashes() hashing_task->addTask(hash_task); } } + auto step_progress = std::make_shared(); + connect(hashing_task.get(), &Task::finished, this, [this, step_progress] { + step_progress->state = TaskStepState::Succeeded; + stepProgress(*step_progress); + }); connect(hashing_task.get(), &Task::succeeded, this, &FlamePackExportTask::makeApiRequest); - connect(hashing_task.get(), &Task::failed, this, &FlamePackExportTask::emitFailed); + connect(hashing_task.get(), &Task::failed, this, [this, step_progress](QString reason) { + step_progress->state = TaskStepState::Failed; + stepProgress(*step_progress); + emitFailed(reason); + }); + connect(hashing_task.get(), &Task::stepProgress, this, &FlamePackExportTask::propogateStepProgress); + + connect(hashing_task.get(), &Task::progress, this, [this, step_progress](qint64 current, qint64 total) { + step_progress->update(current, total); + stepProgress(*step_progress); + }); + connect(hashing_task.get(), &Task::status, this, [this, step_progress](QString status) { + step_progress->status = status; + stepProgress(*step_progress); + }); hashing_task->start(); } @@ -173,6 +187,7 @@ void FlamePackExportTask::makeApiRequest() } setStatus(tr("Find versions for hashes...")); + setProgress(2, 5); auto response = std::make_shared(); QList fingerprints; @@ -186,7 +201,7 @@ void FlamePackExportTask::makeApiRequest() QJsonParseError parse_error{}; QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error); if (parse_error.error != QJsonParseError::NoError) { - qWarning() << "Error while parsing JSON response from Modrinth::CurrentVersions at " << parse_error.offset + qWarning() << "Error while parsing JSON response from CurseForge::CurrentVersions at " << parse_error.offset << " reason: " << parse_error.errorString(); qWarning() << *response; @@ -241,6 +256,7 @@ void FlamePackExportTask::makeApiRequest() void FlamePackExportTask::getProjectsInfo() { setStatus(tr("Find project info from CurseForge...")); + setProgress(3, 5); QList addonIds; for (auto resolved : resolvedFiles) { if (resolved.slug.isEmpty()) { @@ -264,9 +280,10 @@ void FlamePackExportTask::getProjectsInfo() QJsonParseError parse_error{}; auto doc = QJsonDocument::fromJson(*response, &parse_error); if (parse_error.error != QJsonParseError::NoError) { - qWarning() << "Error while parsing JSON response from Modrinth projects task at " << parse_error.offset + qWarning() << "Error while parsing JSON response from CurseForge projects task at " << parse_error.offset << " reason: " << parse_error.errorString(); qWarning() << *response; + failed(parse_error.errorString()); return; } @@ -317,6 +334,7 @@ void FlamePackExportTask::getProjectsInfo() void FlamePackExportTask::buildZip() { setStatus(tr("Adding files...")); + setProgress(4, 5); buildZipFuture = QtConcurrent::run(QThreadPool::globalInstance(), [this]() { QuaZip zip(output); @@ -352,14 +370,19 @@ void FlamePackExportTask::buildZip() content = "
      " + content + "
    "; modlist.write(content.toUtf8()); + auto step_progress = std::make_shared(); + size_t progress = 0; for (const QFileInfo& file : files) { if (buildZipFuture.isCanceled()) { QFile::remove(output); + step_progress->state = TaskStepState::Failed; + stepProgress(*step_progress); return BuildZipResult(); } + step_progress->update(progress, files.length()); + stepProgress(*step_progress); - setProgress(progress, files.length()); const QString relative = gameRoot.relativeFilePath(file.absoluteFilePath()); if (!resolvedFiles.contains(file.absoluteFilePath()) && !JlCompress::compressFile(&zip, file.absoluteFilePath(), "overrides/" + relative)) { @@ -373,9 +396,12 @@ void FlamePackExportTask::buildZip() if (zip.getZipError() != 0) { QFile::remove(output); + step_progress->state = TaskStepState::Failed; + stepProgress(*step_progress); return BuildZipResult(tr("A zip error occurred")); } - + step_progress->state = TaskStepState::Succeeded; + stepProgress(*step_progress); return BuildZipResult(); }); connect(&buildZipWatcher, &QFutureWatcher::finished, this, &FlamePackExportTask::finish); From f2015eee8059fa68af4ca9415cc8a11f13b65922 Mon Sep 17 00:00:00 2001 From: Alexandru Ionut Tripon Date: Mon, 26 Jun 2023 11:44:47 +0300 Subject: [PATCH 069/216] Update launcher/ui/MainWindow.ui Co-authored-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com> Signed-off-by: Alexandru Ionut Tripon --- launcher/ui/MainWindow.ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/ui/MainWindow.ui b/launcher/ui/MainWindow.ui index 027742ba4..22721fcdb 100644 --- a/launcher/ui/MainWindow.ui +++ b/launcher/ui/MainWindow.ui @@ -484,7 +484,7 @@ - ModList (txt) + Mod List
    From cf5c01a5b1a9a91d41fb343d2d2abc9bac07f1ec Mon Sep 17 00:00:00 2001 From: Alexandru Ionut Tripon Date: Mon, 26 Jun 2023 11:44:55 +0300 Subject: [PATCH 070/216] Update launcher/ui/dialogs/ExportToModListDialog.cpp Co-authored-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com> Signed-off-by: Alexandru Ionut Tripon --- launcher/ui/dialogs/ExportToModListDialog.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/ui/dialogs/ExportToModListDialog.cpp b/launcher/ui/dialogs/ExportToModListDialog.cpp index 57ee44537..d53e8db3a 100644 --- a/launcher/ui/dialogs/ExportToModListDialog.cpp +++ b/launcher/ui/dialogs/ExportToModListDialog.cpp @@ -118,7 +118,7 @@ void ExportToModListDialog::triggerImp() QString exampleLine; switch (format) { case ExportToModList::HTML: { - exampleLine = "
      {name}[{version}] by {authors}
    "; + exampleLine = "
      {name} [{version}] by {authors}
    "; ui->resultText->setHtml(txt); break; } From d82ae31fc1dc75693e3a6270f0b733fcf7bdaadd Mon Sep 17 00:00:00 2001 From: Alexandru Ionut Tripon Date: Mon, 26 Jun 2023 11:45:05 +0300 Subject: [PATCH 071/216] Update launcher/ui/dialogs/ExportToModListDialog.cpp Co-authored-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com> Signed-off-by: Alexandru Ionut Tripon --- launcher/ui/dialogs/ExportToModListDialog.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/ui/dialogs/ExportToModListDialog.cpp b/launcher/ui/dialogs/ExportToModListDialog.cpp index d53e8db3a..b399dc178 100644 --- a/launcher/ui/dialogs/ExportToModListDialog.cpp +++ b/launcher/ui/dialogs/ExportToModListDialog.cpp @@ -123,7 +123,7 @@ void ExportToModListDialog::triggerImp() break; } case ExportToModList::MARKDOWN: { - exampleLine = "[{name}]({url})[{version}] by {authors}"; + exampleLine = "[{name}]({url}) [{version}] by {authors}"; ui->resultText->setHtml(markdownToHTML(txt)); break; } From 22bb260ae3ccdc17840047cbef49f0af09b809bd Mon Sep 17 00:00:00 2001 From: Alexandru Ionut Tripon Date: Mon, 26 Jun 2023 11:45:26 +0300 Subject: [PATCH 072/216] Update launcher/ui/dialogs/ExportToModListDialog.cpp Co-authored-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com> Signed-off-by: Alexandru Ionut Tripon --- launcher/ui/dialogs/ExportToModListDialog.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/ui/dialogs/ExportToModListDialog.cpp b/launcher/ui/dialogs/ExportToModListDialog.cpp index b399dc178..149f6b358 100644 --- a/launcher/ui/dialogs/ExportToModListDialog.cpp +++ b/launcher/ui/dialogs/ExportToModListDialog.cpp @@ -128,7 +128,7 @@ void ExportToModListDialog::triggerImp() break; } case ExportToModList::PLAINTXT: { - exampleLine = "name: {name}; url: {url}; version: {version}; authors: {authors};"; + exampleLine = "{name} ({url}) [{version}] by {authors}"; break; } case ExportToModList::CUSTOM: From 0aaec9ae4fb8a2f9e00d81acf85ab66e60ad2639 Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Mon, 26 Jun 2023 11:53:14 +0200 Subject: [PATCH 073/216] chore: remove obsolete macOS warning We don't support that macOS version. This check also never worked, as we never set the platform to that value. Signed-off-by: Sefa Eyeoglu --- buildconfig/BuildConfig.cpp.in | 2 +- buildconfig/BuildConfig.h | 2 +- launcher/ui/pages/global/AccountListPage.cpp | 13 ------------- 3 files changed, 2 insertions(+), 15 deletions(-) diff --git a/buildconfig/BuildConfig.cpp.in b/buildconfig/BuildConfig.cpp.in index 8a412b7ff..140731fe0 100644 --- a/buildconfig/BuildConfig.cpp.in +++ b/buildconfig/BuildConfig.cpp.in @@ -65,7 +65,7 @@ Config::Config() MAC_SPARKLE_PUB_KEY = "@MACOSX_SPARKLE_UPDATE_PUBLIC_KEY@"; MAC_SPARKLE_APPCAST_URL = "@MACOSX_SPARKLE_UPDATE_FEED_URL@"; - if (BUILD_PLATFORM == "macOS" && !MAC_SPARKLE_PUB_KEY.isEmpty() && !MAC_SPARKLE_APPCAST_URL.isEmpty()) + if (!MAC_SPARKLE_PUB_KEY.isEmpty() && !MAC_SPARKLE_APPCAST_URL.isEmpty()) { UPDATER_ENABLED = true; } diff --git a/buildconfig/BuildConfig.h b/buildconfig/BuildConfig.h index 8543d7241..11773d887 100644 --- a/buildconfig/BuildConfig.h +++ b/buildconfig/BuildConfig.h @@ -68,7 +68,7 @@ class Config { bool UPDATER_ENABLED = false; - /// A short string identifying this build's platform. For example, "lin64" or "win32". + /// A short string identifying this build's platform or distribution. QString BUILD_PLATFORM; /// A string containing the build timestamp diff --git a/launcher/ui/pages/global/AccountListPage.cpp b/launcher/ui/pages/global/AccountListPage.cpp index 278f45c49..fced5ff4a 100644 --- a/launcher/ui/pages/global/AccountListPage.cpp +++ b/launcher/ui/pages/global/AccountListPage.cpp @@ -159,19 +159,6 @@ void AccountListPage::on_actionAddMojang_triggered() void AccountListPage::on_actionAddMicrosoft_triggered() { - if(BuildConfig.BUILD_PLATFORM == "osx64") { - CustomMessageBox::selectable( - this, - tr("Microsoft Accounts not available"), - //: %1 refers to the launcher itself - tr( - "Microsoft accounts are only usable on macOS 10.13 or newer, with fully updated %1.\n\n" - "Please update both your operating system and %1." - ).arg(BuildConfig.LAUNCHER_DISPLAYNAME), - QMessageBox::Warning - )->exec(); - return; - } MinecraftAccountPtr account = MSALoginDialog::newAccount( this, tr("Please enter your Mojang account email and password to add your account.") From f5e4171df4f8990955b10d538809730abded32f8 Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Mon, 26 Jun 2023 11:54:22 +0200 Subject: [PATCH 074/216] feat: print build platform in log Signed-off-by: Sefa Eyeoglu --- launcher/LaunchController.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/launcher/LaunchController.cpp b/launcher/LaunchController.cpp index 070ee283c..8fadf446c 100644 --- a/launcher/LaunchController.cpp +++ b/launcher/LaunchController.cpp @@ -390,7 +390,10 @@ void LaunchController::launchInstance() m_launcher->prependStep(makeShared(m_launcher.get(), "Launched instance in " + online_mode + " mode\n", MessageLevel::Launcher)); // Prepend Version - m_launcher->prependStep(makeShared(m_launcher.get(), BuildConfig.LAUNCHER_DISPLAYNAME + " version: " + BuildConfig.printableVersionString() + "\n\n", MessageLevel::Launcher)); + { + auto versionString = QString("%1 version: %2 (%3)").arg(BuildConfig.LAUNCHER_DISPLAYNAME, BuildConfig.printableVersionString(), BuildConfig.BUILD_PLATFORM); + m_launcher->prependStep(makeShared(m_launcher.get(), versionString + "\n\n", MessageLevel::Launcher)); + } m_launcher->start(); } From fce000206f9a866b70c50f2b6ea860bded19383b Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Mon, 26 Jun 2023 11:55:23 +0200 Subject: [PATCH 075/216] feat: print build platform in application log Signed-off-by: Sefa Eyeoglu --- launcher/Application.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/launcher/Application.cpp b/launcher/Application.cpp index 1d97a5f2e..45e340260 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -471,6 +471,7 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) qDebug() << BuildConfig.LAUNCHER_DISPLAYNAME << ", (c) 2013-2021 " << BuildConfig.LAUNCHER_COPYRIGHT; qDebug() << "Version : " << BuildConfig.printableVersionString(); + qDebug() << "Platform : " << BuildConfig.BUILD_PLATFORM; qDebug() << "Git commit : " << BuildConfig.GIT_COMMIT; qDebug() << "Git refspec : " << BuildConfig.GIT_REFSPEC; if (adjustedBy.size()) From 63acf0a7b4492334ad2d5b8c623a5ae6a54bb13d Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Mon, 26 Jun 2023 11:55:48 +0200 Subject: [PATCH 076/216] fix: set default platform to "unknown" Signed-off-by: Sefa Eyeoglu --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 70a553190..48995bedf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -146,7 +146,7 @@ set(Launcher_VERSION_NAME4 "${Launcher_VERSION_MAJOR}.${Launcher_VERSION_MINOR}. set(Launcher_VERSION_NAME4_COMMA "${Launcher_VERSION_MAJOR},${Launcher_VERSION_MINOR},0,0") # Build platform. -set(Launcher_BUILD_PLATFORM "" CACHE STRING "A short string identifying the platform that this build was built for. Only used to display in the about dialog.") +set(Launcher_BUILD_PLATFORM "unknown" CACHE STRING "A short string identifying the platform that this build was built for. Only used to display in the about dialog.") # Channel list URL set(Launcher_UPDATER_BASE "" CACHE STRING "Base URL for the updater.") From 40fb387185527db5eb03be34ea35f24d3e7bedcd Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Mon, 26 Jun 2023 11:58:47 +0200 Subject: [PATCH 077/216] fix(actions): set all build platforms to official Signed-off-by: Sefa Eyeoglu --- .github/workflows/build.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c2966abe7..bbfe4ab44 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -264,23 +264,23 @@ jobs: - name: Configure CMake (macOS) if: runner.os == 'macOS' && matrix.qt_ver == 6 run: | - cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_DIR }} -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DLauncher_BUILD_PLATFORM=${{ matrix.name }} -DCMAKE_C_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DCMAKE_CXX_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DLauncher_QT_VERSION_MAJOR=${{ matrix.qt_ver }} -DCMAKE_OSX_ARCHITECTURES="x86_64;arm64" -G Ninja + cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_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 }} -DCMAKE_OSX_ARCHITECTURES="x86_64;arm64" -G Ninja - name: Configure CMake (macOS-Legacy) if: runner.os == 'macOS' && matrix.qt_ver == 5 run: | - cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_DIR }} -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DLauncher_BUILD_PLATFORM=${{ matrix.name }} -DCMAKE_C_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DCMAKE_CXX_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DLauncher_QT_VERSION_MAJOR=${{ matrix.qt_ver }} -DMACOSX_SPARKLE_UPDATE_PUBLIC_KEY="" -DMACOSX_SPARKLE_UPDATE_FEED_URL="" -G Ninja + cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_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 }} -DMACOSX_SPARKLE_UPDATE_PUBLIC_KEY="" -DMACOSX_SPARKLE_UPDATE_FEED_URL="" -G Ninja - name: Configure CMake (Windows MinGW-w64) if: runner.os == 'Windows' && matrix.msystem != '' shell: msys2 {0} run: | - cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_DIR }} -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DLauncher_BUILD_PLATFORM=${{ matrix.name }} -DCMAKE_C_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DCMAKE_CXX_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DLauncher_QT_VERSION_MAJOR=6 -DCMAKE_OBJDUMP=/mingw64/bin/objdump.exe -G Ninja + cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_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=6 -DCMAKE_OBJDUMP=/mingw64/bin/objdump.exe -G Ninja - name: Configure CMake (Windows MSVC) if: runner.os == 'Windows' && matrix.msystem == '' run: | - cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_DIR }} -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DLauncher_BUILD_PLATFORM=${{ matrix.name }} -DLauncher_QT_VERSION_MAJOR=${{ matrix.qt_ver }} -DCMAKE_MSVC_RUNTIME_LIBRARY="MultiThreadedDLL" -A${{ matrix.architecture}} -DLauncher_FORCE_BUNDLED_LIBS=ON + cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_DIR }} -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DLauncher_BUILD_PLATFORM=official -DLauncher_QT_VERSION_MAJOR=${{ matrix.qt_ver }} -DCMAKE_MSVC_RUNTIME_LIBRARY="MultiThreadedDLL" -A${{ matrix.architecture}} -DLauncher_FORCE_BUNDLED_LIBS=ON # https://github.com/ccache/ccache/wiki/MS-Visual-Studio (I coudn't figure out the compiler prefix) if ("${{ env.CCACHE_VAR }}") { @@ -295,7 +295,7 @@ jobs: - name: Configure CMake (Linux) if: runner.os == 'Linux' run: | - cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DLauncher_BUILD_PLATFORM=Linux -DCMAKE_C_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DCMAKE_CXX_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DLauncher_QT_VERSION_MAJOR=${{ matrix.qt_ver }} -G Ninja + cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=/usr -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 }} -G Ninja ## # BUILD From 23b3711f96bd93171eebc401f983ccf0fb862772 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Tue, 27 Jun 2023 12:41:36 -0700 Subject: [PATCH 078/216] fix(filesystem): track failed copies and clones Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/FileSystem.cpp | 9 +++++++++ launcher/FileSystem.h | 9 +++++++++ 2 files changed, 18 insertions(+) diff --git a/launcher/FileSystem.cpp b/launcher/FileSystem.cpp index 835ad925d..0554cab86 100644 --- a/launcher/FileSystem.cpp +++ b/launcher/FileSystem.cpp @@ -36,6 +36,7 @@ */ #include "FileSystem.h" +#include #include "BuildConfig.h" @@ -246,6 +247,7 @@ bool copy::operator()(const QString& offset, bool dryRun) { using copy_opts = fs::copy_options; m_copied = 0; // reset counter + m_failedPaths.clear(); // NOTE always deep copy on windows. the alternatives are too messy. #if defined Q_OS_WIN32 @@ -277,6 +279,9 @@ bool copy::operator()(const QString& offset, bool dryRun) qWarning() << "Failed to copy files:" << QString::fromStdString(err.message()); qDebug() << "Source file:" << src_path; qDebug() << "Destination file:" << dst_path; + m_failedPaths.append(dst_path); + emit copyFailed(relative_dst_path); + return; } m_copied++; emit fileCopied(relative_dst_path); @@ -1072,6 +1077,7 @@ bool clone::operator()(const QString& offset, bool dryRun) } m_cloned = 0; // reset counter + m_failedClones.clear(); auto src = PathCombine(m_src.absolutePath(), offset); auto dst = PathCombine(m_dst.absolutePath(), offset); @@ -1092,6 +1098,9 @@ bool clone::operator()(const QString& offset, bool dryRun) qDebug() << "Failed to clone files: error" << err.value() << "message" << QString::fromStdString(err.message()); qDebug() << "Source file:" << src_path; qDebug() << "Destination file:" << dst_path; + m_failedClones.append(qMakePair(src_path, dst_path)); + emit cloneFailed(src_path, dst_path); + return; } m_cloned++; emit fileCloned(src_path, dst_path); diff --git a/launcher/FileSystem.h b/launcher/FileSystem.h index cb581d0c5..f8a82baef 100644 --- a/launcher/FileSystem.h +++ b/launcher/FileSystem.h @@ -43,6 +43,7 @@ #include #include +#include #include #include #include @@ -112,9 +113,12 @@ class copy : public QObject { bool operator()(bool dryRun = false) { return operator()(QString(), dryRun); } int totalCopied() { return m_copied; } + int totalFailed() { return m_failedPaths.length(); } + QStringList failed() { return m_failedPaths; } signals: void fileCopied(const QString& relativeName); + void copyFailed(const QString& relativeName); // TODO: maybe add a "shouldCopy" signal in the future? private: @@ -127,6 +131,7 @@ class copy : public QObject { QDir m_src; QDir m_dst; int m_copied; + QStringList m_failedPaths; }; struct LinkPair { @@ -471,6 +476,9 @@ class clone : public QObject { bool operator()(bool dryRun = false) { return operator()(QString(), dryRun); } int totalCloned() { return m_cloned; } + int totalFailed() { return m_failedClones.length(); } + + QList> failed() { return m_failedClones; } signals: void fileCloned(const QString& src, const QString& dst); @@ -485,6 +493,7 @@ class clone : public QObject { QDir m_src; QDir m_dst; int m_cloned; + QList> m_failedClones; }; /** From 00be211169134022813562cd09c69f831d0e400e Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Tue, 27 Jun 2023 13:01:28 -0700 Subject: [PATCH 079/216] Update launcher/FileSystem.cpp Co-authored-by: TheKodeToad Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/FileSystem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/FileSystem.cpp b/launcher/FileSystem.cpp index 0554cab86..8a417831b 100644 --- a/launcher/FileSystem.cpp +++ b/launcher/FileSystem.cpp @@ -36,7 +36,7 @@ */ #include "FileSystem.h" -#include +#include #include "BuildConfig.h" From 0f64ee6a5f6d157e493d474b74004a4ebd0dae43 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Wed, 28 Jun 2023 18:28:25 +0300 Subject: [PATCH 080/216] Added warnings for running instances Signed-off-by: Trial97 --- .../minecraft/mod/ResourceFolderModel.cpp | 18 +++++++++++++++-- .../pages/instance/ExternalResourcesPage.cpp | 20 +++++++++++++++++++ launcher/ui/pages/instance/ModFolderPage.cpp | 10 ++++++++++ 3 files changed, 46 insertions(+), 2 deletions(-) diff --git a/launcher/minecraft/mod/ResourceFolderModel.cpp b/launcher/minecraft/mod/ResourceFolderModel.cpp index 1a56b6793..c2c0d1785 100644 --- a/launcher/minecraft/mod/ResourceFolderModel.cpp +++ b/launcher/minecraft/mod/ResourceFolderModel.cpp @@ -1,14 +1,15 @@ #include "ResourceFolderModel.h" +#include #include #include #include #include +#include #include #include #include #include -#include #include "Application.h" #include "FileSystem.h" @@ -18,6 +19,7 @@ #include "settings/Setting.h" #include "tasks/Task.h" +#include "ui/dialogs/CustomMessageBox.h" ResourceFolderModel::ResourceFolderModel(QDir dir, BaseInstance* instance, QObject* parent, bool create_dir) : QAbstractListModel(parent), m_dir(dir), m_instance(instance), m_watcher(this) @@ -451,8 +453,20 @@ bool ResourceFolderModel::setData(const QModelIndex& index, const QVariant& valu if (row < 0 || row >= rowCount(index.parent()) || !index.isValid()) return false; - if (role == Qt::CheckStateRole) + if (role == Qt::CheckStateRole) { + if (m_instance != nullptr && m_instance->isRunning()) { + auto response = + CustomMessageBox::selectable(nullptr, "Confirm toggle", + "If you enable/disable this resource while the game is running it may crash your game.\n" + "Are you sure you want to do this?", + QMessageBox::Warning, QMessageBox::Yes | QMessageBox::No, QMessageBox::No) + ->exec(); + + if (response != QMessageBox::Yes) + return false; + } return setResourceEnabled({ index }, EnableAction::TOGGLE); + } return false; } diff --git a/launcher/ui/pages/instance/ExternalResourcesPage.cpp b/launcher/ui/pages/instance/ExternalResourcesPage.cpp index 87a3df102..12038f88f 100644 --- a/launcher/ui/pages/instance/ExternalResourcesPage.cpp +++ b/launcher/ui/pages/instance/ExternalResourcesPage.cpp @@ -250,6 +250,16 @@ void ExternalResourcesPage::removeItem() void ExternalResourcesPage::removeItems(const QItemSelection& selection) { + if (m_instance != nullptr && m_instance->isRunning()) { + auto response = CustomMessageBox::selectable(this, "Confirm Delete", + "If you remove this resource while the game is running it may crash your game.\n" + "Are you sure you want to do this?", + QMessageBox::Warning, QMessageBox::Yes | QMessageBox::No, QMessageBox::No) + ->exec(); + + if (response != QMessageBox::Yes) + return; + } m_model->deleteResources(selection.indexes()); } @@ -261,6 +271,16 @@ void ExternalResourcesPage::enableItem() void ExternalResourcesPage::disableItem() { + if (m_instance != nullptr && m_instance->isRunning()) { + auto response = CustomMessageBox::selectable(this, "Confirm disable", + "If you disable this resource while the game is running it may crash your game.\n" + "Are you sure you want to do this?", + QMessageBox::Warning, QMessageBox::Yes | QMessageBox::No, QMessageBox::No) + ->exec(); + + if (response != QMessageBox::Yes) + return; + } auto selection = m_filterModel->mapSelectionToSource(ui->treeView->selectionModel()->selection()); m_model->setResourceEnabled(selection.indexes(), EnableAction::DISABLE); } diff --git a/launcher/ui/pages/instance/ModFolderPage.cpp b/launcher/ui/pages/instance/ModFolderPage.cpp index 9812bbe93..3176396f8 100644 --- a/launcher/ui/pages/instance/ModFolderPage.cpp +++ b/launcher/ui/pages/instance/ModFolderPage.cpp @@ -120,6 +120,16 @@ bool ModFolderPage::onSelectionChanged(const QModelIndex& current, const QModelI void ModFolderPage::removeItems(const QItemSelection& selection) { + if (m_instance != nullptr && m_instance->isRunning()) { + auto response = CustomMessageBox::selectable(this, "Confirm Delete", + "If you remove mods while the game is running it may crash your game.\n" + "Are you sure you want to do this?", + QMessageBox::Warning, QMessageBox::Yes | QMessageBox::No, QMessageBox::No) + ->exec(); + + if (response != QMessageBox::Yes) + return; + } m_model->deleteMods(selection.indexes()); } From 0008b22d8b352e3591ee7ba7c6d9313ed23cbd4a Mon Sep 17 00:00:00 2001 From: Trial97 Date: Wed, 28 Jun 2023 18:41:47 +0300 Subject: [PATCH 081/216] Renamed function Signed-off-by: Trial97 --- launcher/ui/MainWindow.cpp | 2 +- launcher/ui/instanceview/InstanceView.cpp | 9 ++++++--- launcher/ui/instanceview/InstanceView.h | 2 +- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp index 26fcb3a3c..515abf070 100644 --- a/launcher/ui/MainWindow.cpp +++ b/launcher/ui/MainWindow.cpp @@ -927,7 +927,7 @@ void MainWindow::onCatToggled(bool state) void MainWindow::setCatBackground(bool enabled) { - view->setCatVisible(enabled); + view->setPaintCat(enabled); view->viewport()->repaint(); } diff --git a/launcher/ui/instanceview/InstanceView.cpp b/launcher/ui/instanceview/InstanceView.cpp index 4c83e94a0..1911dd59a 100644 --- a/launcher/ui/instanceview/InstanceView.cpp +++ b/launcher/ui/instanceview/InstanceView.cpp @@ -74,7 +74,7 @@ InstanceView::InstanceView(QWidget *parent) setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); setAcceptDrops(true); setAutoScroll(true); - setCatVisible(APPLICATION->settings()->get("TheCat").toBool()); + setPaintCat(APPLICATION->settings()->get("TheCat").toBool()); } InstanceView::~InstanceView() @@ -500,10 +500,13 @@ void InstanceView::mouseDoubleClickEvent(QMouseEvent *event) } } -void InstanceView::setCatVisible(bool visible) +void InstanceView::setPaintCat(bool visible) { m_catVisible = visible; - m_catPixmap.load(QString(":/backgrounds/%1").arg(ThemeManager::getCatImage())); + if (visible) + m_catPixmap.load(QString(":/backgrounds/%1").arg(ThemeManager::getCatImage())); + else + m_catPixmap = QPixmap(); } void InstanceView::paintEvent(QPaintEvent* event) diff --git a/launcher/ui/instanceview/InstanceView.h b/launcher/ui/instanceview/InstanceView.h index a9bd0bd7e..364056751 100644 --- a/launcher/ui/instanceview/InstanceView.h +++ b/launcher/ui/instanceview/InstanceView.h @@ -86,7 +86,7 @@ public: virtual QRegion visualRegionForSelection(const QItemSelection &selection) const override; int spacing() const { return m_spacing; }; - void setCatVisible(bool visible); + void setPaintCat(bool visible); public slots: virtual void updateGeometries() override; From 7033e2857268a314971ea9a29a5dbc83d3b2d978 Mon Sep 17 00:00:00 2001 From: Tayou Date: Wed, 28 Jun 2023 18:00:40 +0200 Subject: [PATCH 082/216] update instance group header to more modern style Signed-off-by: Tayou --- launcher/ui/instanceview/VisualGroup.cpp | 136 ++++++----------------- 1 file changed, 34 insertions(+), 102 deletions(-) diff --git a/launcher/ui/instanceview/VisualGroup.cpp b/launcher/ui/instanceview/VisualGroup.cpp index e6bca17d6..f2d1ca14a 100644 --- a/launcher/ui/instanceview/VisualGroup.cpp +++ b/launcher/ui/instanceview/VisualGroup.cpp @@ -157,133 +157,65 @@ VisualGroup::HitResults VisualGroup::hitScan(const QPoint &pos) const void VisualGroup::drawHeader(QPainter *painter, const QStyleOptionViewItem &option) { - painter->setRenderHint(QPainter::Antialiasing); - const QRect optRect = option.rect; QFont font(QApplication::font()); font.setBold(true); const QFontMetrics fontMetrics = QFontMetrics(font); - QColor outlineColor = option.palette.text().color(); - outlineColor.setAlphaF(0.35); + int centerHeight = option.rect.top() + fontMetrics.height()/2; - //BEGIN: top left corner - { - painter->save(); - painter->setPen(outlineColor); - const QPointF topLeft(optRect.topLeft()); - QRectF arc(topLeft, QSizeF(4, 4)); - arc.translate(0.5, 0.5); - painter->drawArc(arc, 1440, 1440); - painter->restore(); - } - //END: top left corner + QPen pen; + pen.setWidth(2); + QColor penColor = option.palette.text().color(); + penColor.setAlphaF(0.6); + pen.setColor(penColor); + painter->setPen(pen); - //BEGIN: left vertical line + //BEGIN: arrow { - QPoint start(optRect.topLeft()); - start.ry() += 3; - QPoint verticalGradBottom(optRect.topLeft()); - verticalGradBottom.ry() += fontMetrics.height() + 5; - QLinearGradient gradient(start, verticalGradBottom); - gradient.setColorAt(0, outlineColor); - gradient.setColorAt(1, Qt::transparent); - painter->fillRect(QRect(start, QSize(1, fontMetrics.height() + 5)), gradient); - } - //END: left vertical line - - //BEGIN: horizontal line - { - QPoint start(optRect.topLeft()); - start.rx() += 3; - QPoint horizontalGradTop(optRect.topLeft()); - horizontalGradTop.rx() += optRect.width() - 6; - painter->fillRect(QRect(start, QSize(optRect.width() - 6, 1)), outlineColor); - } - //END: horizontal line - - //BEGIN: top right corner - { - painter->save(); - painter->setPen(outlineColor); - QPointF topRight(optRect.topRight()); - topRight.rx() -= 4; - QRectF arc(topRight, QSizeF(4, 4)); - arc.translate(0.5, 0.5); - painter->drawArc(arc, 0, 1440); - painter->restore(); - } - //END: top right corner - - //BEGIN: right vertical line - { - QPoint start(optRect.topRight()); - start.ry() += 3; - QPoint verticalGradBottom(optRect.topRight()); - verticalGradBottom.ry() += fontMetrics.height() + 5; - QLinearGradient gradient(start, verticalGradBottom); - gradient.setColorAt(0, outlineColor); - gradient.setColorAt(1, Qt::transparent); - painter->fillRect(QRect(start, QSize(1, fontMetrics.height() + 5)), gradient); - } - //END: right vertical line - - //BEGIN: checkboxy thing - { - painter->save(); painter->setRenderHint(QPainter::Antialiasing, false); - painter->setFont(font); - QColor penColor(option.palette.text().color()); - penColor.setAlphaF(0.6); - painter->setPen(penColor); - QRect iconSubRect(option.rect); - iconSubRect.setTop(iconSubRect.top() + 7); - iconSubRect.setLeft(iconSubRect.left() + 7); + painter->save(); - int sizing = fontMetrics.height(); - int even = ( (sizing - 1) % 2 ); + int offsetLeft = fontMetrics.height()/2; + int offsetTop = centerHeight; + int arrowSize = 6; - iconSubRect.setHeight(sizing - even); - iconSubRect.setWidth(sizing - even); - painter->drawRect(iconSubRect); - - - /* - if(collapsed) - painter->drawText(iconSubRect, Qt::AlignHCenter | Qt::AlignVCenter, "+"); - else - painter->drawText(iconSubRect, Qt::AlignHCenter | Qt::AlignVCenter, "-"); - */ - painter->setBrush(option.palette.text()); - painter->fillRect(iconSubRect.x(), iconSubRect.y() + iconSubRect.height() / 2, - iconSubRect.width(), 2, penColor); - if (collapsed) - { - painter->fillRect(iconSubRect.x() + iconSubRect.width() / 2, iconSubRect.y(), 2, - iconSubRect.height(), penColor); + QPolygon polygon; + if (collapsed) { + polygon << QPoint(offsetLeft - arrowSize/2, offsetTop - arrowSize) << QPoint(offsetLeft + arrowSize/2, offsetTop) << QPoint(offsetLeft - arrowSize/2, offsetTop + arrowSize); + painter->drawPolyline(polygon); + } else { + polygon << QPoint(offsetLeft - arrowSize, offsetTop - arrowSize/2) << QPoint(offsetLeft, offsetTop + arrowSize/2) << QPoint(offsetLeft + arrowSize, offsetTop - arrowSize/2); + painter->drawPolyline(polygon); } - - painter->restore(); } - //END: checkboxy thing + //END: arrow //BEGIN: text { + painter->setRenderHint(QPainter::Antialiasing); QRect textRect(option.rect); - textRect.setTop(textRect.top() + 7); - textRect.setLeft(textRect.left() + 7 + fontMetrics.height() + 7); + textRect.setTop(textRect.top()); + textRect.setLeft(textRect.left() + fontMetrics.height()); textRect.setHeight(fontMetrics.height()); textRect.setRight(textRect.right() - 7); painter->save(); painter->setFont(font); - QColor penColor(option.palette.text().color()); - penColor.setAlphaF(0.6); - painter->setPen(penColor); painter->drawText(textRect, Qt::AlignLeft | Qt::AlignVCenter, text); - painter->restore(); } //END: text + + //BEGIN: horizontal line + { + // startPoint is left + arrow + text + space + int startPoint = optRect.left() + fontMetrics.height() + fontMetrics.size(Qt::AlignLeft | Qt::AlignVCenter, text).width() + 7; + painter->setRenderHint(QPainter::Antialiasing, false); + QPolygon polygon; + polygon << QPoint(startPoint, centerHeight) << QPoint(optRect.right() - 3, centerHeight); + painter->drawPolyline(polygon); + } + //END: horizontal line } int VisualGroup::totalHeight() const From 66461ac500ded75d1d3f4df580296936b85e08b2 Mon Sep 17 00:00:00 2001 From: Tayou Date: Wed, 28 Jun 2023 18:42:49 +0200 Subject: [PATCH 083/216] some positioning adjustments, deleted the line Signed-off-by: Tayou --- launcher/ui/instanceview/VisualGroup.cpp | 34 +++++++++--------------- 1 file changed, 12 insertions(+), 22 deletions(-) diff --git a/launcher/ui/instanceview/VisualGroup.cpp b/launcher/ui/instanceview/VisualGroup.cpp index f2d1ca14a..f544c3dc7 100644 --- a/launcher/ui/instanceview/VisualGroup.cpp +++ b/launcher/ui/instanceview/VisualGroup.cpp @@ -157,12 +157,13 @@ VisualGroup::HitResults VisualGroup::hitScan(const QPoint &pos) const void VisualGroup::drawHeader(QPainter *painter, const QStyleOptionViewItem &option) { - const QRect optRect = option.rect; + QRect optRect = option.rect; + optRect.setTop(optRect.top() + 7); QFont font(QApplication::font()); font.setBold(true); const QFontMetrics fontMetrics = QFontMetrics(font); - int centerHeight = option.rect.top() + fontMetrics.height()/2; + int centerHeight = optRect.top() + fontMetrics.height()/2; QPen pen; pen.setWidth(2); @@ -171,21 +172,21 @@ void VisualGroup::drawHeader(QPainter *painter, const QStyleOptionViewItem &opti pen.setColor(penColor); painter->setPen(pen); + int arrowOffsetLeft = fontMetrics.height()/2 + 7; + int textOffsetLeft = arrowOffsetLeft *2; + int arrowSize = 6; + //BEGIN: arrow { painter->setRenderHint(QPainter::Antialiasing, false); painter->save(); - int offsetLeft = fontMetrics.height()/2; - int offsetTop = centerHeight; - int arrowSize = 6; - QPolygon polygon; if (collapsed) { - polygon << QPoint(offsetLeft - arrowSize/2, offsetTop - arrowSize) << QPoint(offsetLeft + arrowSize/2, offsetTop) << QPoint(offsetLeft - arrowSize/2, offsetTop + arrowSize); + polygon << QPoint(arrowOffsetLeft - arrowSize/2, centerHeight - arrowSize) << QPoint(arrowOffsetLeft + arrowSize/2, centerHeight) << QPoint(arrowOffsetLeft - arrowSize/2, centerHeight + arrowSize); painter->drawPolyline(polygon); } else { - polygon << QPoint(offsetLeft - arrowSize, offsetTop - arrowSize/2) << QPoint(offsetLeft, offsetTop + arrowSize/2) << QPoint(offsetLeft + arrowSize, offsetTop - arrowSize/2); + polygon << QPoint(arrowOffsetLeft - arrowSize, centerHeight - arrowSize/2) << QPoint(arrowOffsetLeft, centerHeight + arrowSize/2) << QPoint(arrowOffsetLeft + arrowSize, centerHeight - arrowSize/2); painter->drawPolyline(polygon); } } @@ -194,9 +195,9 @@ void VisualGroup::drawHeader(QPainter *painter, const QStyleOptionViewItem &opti //BEGIN: text { painter->setRenderHint(QPainter::Antialiasing); - QRect textRect(option.rect); + QRect textRect(optRect); textRect.setTop(textRect.top()); - textRect.setLeft(textRect.left() + fontMetrics.height()); + textRect.setLeft(textOffsetLeft); textRect.setHeight(fontMetrics.height()); textRect.setRight(textRect.right() - 7); @@ -205,22 +206,11 @@ void VisualGroup::drawHeader(QPainter *painter, const QStyleOptionViewItem &opti painter->drawText(textRect, Qt::AlignLeft | Qt::AlignVCenter, text); } //END: text - - //BEGIN: horizontal line - { - // startPoint is left + arrow + text + space - int startPoint = optRect.left() + fontMetrics.height() + fontMetrics.size(Qt::AlignLeft | Qt::AlignVCenter, text).width() + 7; - painter->setRenderHint(QPainter::Antialiasing, false); - QPolygon polygon; - polygon << QPoint(startPoint, centerHeight) << QPoint(optRect.right() - 3, centerHeight); - painter->drawPolyline(polygon); - } - //END: horizontal line } int VisualGroup::totalHeight() const { - return headerHeight() + 5 + contentHeight(); // FIXME: wtf is that '5'? + return headerHeight() + contentHeight(); } int VisualGroup::headerHeight() const From 6b3b119db07b229e22e33313a92a0c81a530f45c Mon Sep 17 00:00:00 2001 From: Tayou Date: Wed, 28 Jun 2023 18:50:44 +0200 Subject: [PATCH 084/216] give ungrouped instances a group header Signed-off-by: Tayou --- launcher/ui/instanceview/VisualGroup.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/launcher/ui/instanceview/VisualGroup.cpp b/launcher/ui/instanceview/VisualGroup.cpp index f544c3dc7..9d8dd2b9e 100644 --- a/launcher/ui/instanceview/VisualGroup.cpp +++ b/launcher/ui/instanceview/VisualGroup.cpp @@ -189,6 +189,7 @@ void VisualGroup::drawHeader(QPainter *painter, const QStyleOptionViewItem &opti polygon << QPoint(arrowOffsetLeft - arrowSize, centerHeight - arrowSize/2) << QPoint(arrowOffsetLeft, centerHeight + arrowSize/2) << QPoint(arrowOffsetLeft + arrowSize, centerHeight - arrowSize/2); painter->drawPolyline(polygon); } + painter->restore(); } //END: arrow @@ -203,7 +204,8 @@ void VisualGroup::drawHeader(QPainter *painter, const QStyleOptionViewItem &opti painter->save(); painter->setFont(font); - painter->drawText(textRect, Qt::AlignLeft | Qt::AlignVCenter, text); + painter->drawText(textRect, Qt::AlignLeft | Qt::AlignVCenter, text != "" ? text : QObject::tr("Ungrouped")); + painter->restore(); } //END: text } From 54d88e4dbf058fe32e92becb5af7eab8c1eb051c Mon Sep 17 00:00:00 2001 From: Tayou Date: Wed, 28 Jun 2023 18:57:10 +0200 Subject: [PATCH 085/216] use QString.isEmpty() oops Signed-off-by: Tayou --- launcher/ui/instanceview/VisualGroup.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/ui/instanceview/VisualGroup.cpp b/launcher/ui/instanceview/VisualGroup.cpp index 9d8dd2b9e..edf487f19 100644 --- a/launcher/ui/instanceview/VisualGroup.cpp +++ b/launcher/ui/instanceview/VisualGroup.cpp @@ -204,7 +204,7 @@ void VisualGroup::drawHeader(QPainter *painter, const QStyleOptionViewItem &opti painter->save(); painter->setFont(font); - painter->drawText(textRect, Qt::AlignLeft | Qt::AlignVCenter, text != "" ? text : QObject::tr("Ungrouped")); + painter->drawText(textRect, Qt::AlignLeft | Qt::AlignVCenter, !text.isEmpty() ? text : QObject::tr("Ungrouped")); painter->restore(); } //END: text From 534d156b1239aed19c9d36a88ff23d84127ac002 Mon Sep 17 00:00:00 2001 From: Tayou Date: Wed, 28 Jun 2023 20:06:17 +0200 Subject: [PATCH 086/216] format VisualGroup.cpp file Signed-off-by: Tayou --- launcher/ui/instanceview/VisualGroup.cpp | 94 ++++++++++-------------- 1 file changed, 39 insertions(+), 55 deletions(-) diff --git a/launcher/ui/instanceview/VisualGroup.cpp b/launcher/ui/instanceview/VisualGroup.cpp index edf487f19..9b2189b85 100644 --- a/launcher/ui/instanceview/VisualGroup.cpp +++ b/launcher/ui/instanceview/VisualGroup.cpp @@ -35,22 +35,17 @@ #include "VisualGroup.h" +#include +#include #include #include #include -#include -#include #include "InstanceView.h" -VisualGroup::VisualGroup(const QString &text, InstanceView *view) : view(view), text(text), collapsed(false) -{ -} +VisualGroup::VisualGroup(const QString& text, InstanceView* view) : view(view), text(text), collapsed(false) {} -VisualGroup::VisualGroup(const VisualGroup *other) - : view(other->view), text(other->text), collapsed(other->collapsed) -{ -} +VisualGroup::VisualGroup(const VisualGroup* other) : view(other->view), text(other->text), collapsed(other->collapsed) {} void VisualGroup::update() { @@ -64,13 +59,11 @@ void VisualGroup::update() int positionInRow = 0; int currentRow = 0; int offsetFromTop = 0; - for (auto item: temp_items) - { - if(positionInRow == itemsPerRow) - { + for (auto item : temp_items) { + if (positionInRow == itemsPerRow) { rows[currentRow].height = maxRowHeight; rows[currentRow].top = offsetFromTop; - currentRow ++; + currentRow++; offsetFromTop += maxRowHeight + 5; positionInRow = 0; maxRowHeight = 0; @@ -83,8 +76,7 @@ void VisualGroup::update() #endif auto itemHeight = view->itemDelegate()->sizeHint(viewItemOption, item).height(); - if(itemHeight > maxRowHeight) - { + if (itemHeight > maxRowHeight) { maxRowHeight = itemHeight; } rows[currentRow].items.append(item); @@ -94,16 +86,13 @@ void VisualGroup::update() rows[currentRow].top = offsetFromTop; } -QPair VisualGroup::positionOf(const QModelIndex &index) const +QPair VisualGroup::positionOf(const QModelIndex& index) const { int y = 0; - for (auto & row: rows) - { - for(auto x = 0; x < row.items.size(); x++) - { - if(row.items[x] == index) - { - return qMakePair(x,y); + for (auto& row : rows) { + for (auto x = 0; x < row.items.size(); x++) { + if (row.items[x] == index) { + return qMakePair(x, y); } } y++; @@ -112,50 +101,44 @@ QPair VisualGroup::positionOf(const QModelIndex &index) const return qMakePair(0, 0); } -int VisualGroup::rowTopOf(const QModelIndex &index) const +int VisualGroup::rowTopOf(const QModelIndex& index) const { auto position = positionOf(index); return rows[position.second].top; } -int VisualGroup::rowHeightOf(const QModelIndex &index) const +int VisualGroup::rowHeightOf(const QModelIndex& index) const { auto position = positionOf(index); return rows[position.second].height; } -VisualGroup::HitResults VisualGroup::hitScan(const QPoint &pos) const +VisualGroup::HitResults VisualGroup::hitScan(const QPoint& pos) const { VisualGroup::HitResults results = VisualGroup::NoHit; int y_start = verticalPosition(); int body_start = y_start + headerHeight(); - int body_end = body_start + contentHeight() + 5; // FIXME: wtf is this 5? + int body_end = body_start + contentHeight() + 5; // FIXME: wtf is this 5? int y = pos.y(); // int x = pos.x(); - if (y < y_start) - { + if (y < y_start) { results = VisualGroup::NoHit; - } - else if (y < body_start) - { + } else if (y < body_start) { results = VisualGroup::HeaderHit; int collapseSize = headerHeight() - 4; // the icon QRect iconRect = QRect(view->m_leftMargin + 2, 2 + y_start, collapseSize, collapseSize); - if (iconRect.contains(pos)) - { + if (iconRect.contains(pos)) { results |= VisualGroup::CheckboxHit; } - } - else if (y < body_end) - { + } else if (y < body_end) { results |= VisualGroup::BodyHit; } return results; } -void VisualGroup::drawHeader(QPainter *painter, const QStyleOptionViewItem &option) +void VisualGroup::drawHeader(QPainter* painter, const QStyleOptionViewItem& option) { QRect optRect = option.rect; optRect.setTop(optRect.top() + 7); @@ -163,7 +146,7 @@ void VisualGroup::drawHeader(QPainter *painter, const QStyleOptionViewItem &opti font.setBold(true); const QFontMetrics fontMetrics = QFontMetrics(font); - int centerHeight = optRect.top() + fontMetrics.height()/2; + int centerHeight = optRect.top() + fontMetrics.height() / 2; QPen pen; pen.setWidth(2); @@ -172,28 +155,32 @@ void VisualGroup::drawHeader(QPainter *painter, const QStyleOptionViewItem &opti pen.setColor(penColor); painter->setPen(pen); - int arrowOffsetLeft = fontMetrics.height()/2 + 7; - int textOffsetLeft = arrowOffsetLeft *2; + int arrowOffsetLeft = fontMetrics.height() / 2 + 7; + int textOffsetLeft = arrowOffsetLeft * 2; int arrowSize = 6; - //BEGIN: arrow + // BEGIN: arrow { painter->setRenderHint(QPainter::Antialiasing, false); painter->save(); QPolygon polygon; if (collapsed) { - polygon << QPoint(arrowOffsetLeft - arrowSize/2, centerHeight - arrowSize) << QPoint(arrowOffsetLeft + arrowSize/2, centerHeight) << QPoint(arrowOffsetLeft - arrowSize/2, centerHeight + arrowSize); + polygon << QPoint(arrowOffsetLeft - arrowSize / 2, centerHeight - arrowSize) + << QPoint(arrowOffsetLeft + arrowSize / 2, centerHeight) + << QPoint(arrowOffsetLeft - arrowSize / 2, centerHeight + arrowSize); painter->drawPolyline(polygon); } else { - polygon << QPoint(arrowOffsetLeft - arrowSize, centerHeight - arrowSize/2) << QPoint(arrowOffsetLeft, centerHeight + arrowSize/2) << QPoint(arrowOffsetLeft + arrowSize, centerHeight - arrowSize/2); + polygon << QPoint(arrowOffsetLeft - arrowSize, centerHeight - arrowSize / 2) + << QPoint(arrowOffsetLeft, centerHeight + arrowSize / 2) + << QPoint(arrowOffsetLeft + arrowSize, centerHeight - arrowSize / 2); painter->drawPolyline(polygon); } painter->restore(); } - //END: arrow + // END: arrow - //BEGIN: text + // BEGIN: text { painter->setRenderHint(QPainter::Antialiasing); QRect textRect(optRect); @@ -207,7 +194,7 @@ void VisualGroup::drawHeader(QPainter *painter, const QStyleOptionViewItem &opti painter->drawText(textRect, Qt::AlignLeft | Qt::AlignVCenter, !text.isEmpty() ? text : QObject::tr("Ungrouped")); painter->restore(); } - //END: text + // END: text } int VisualGroup::totalHeight() const @@ -222,7 +209,7 @@ int VisualGroup::headerHeight() const QFontMetrics fontMetrics(font); const int height = fontMetrics.height() + 1 /* 1 pixel-width gradient */ - + 11 /* top and bottom separation */; + + 11 /* top and bottom separation */; return height; /* int raw = view->viewport()->fontMetrics().height() + 4; @@ -235,8 +222,7 @@ int VisualGroup::headerHeight() const int VisualGroup::contentHeight() const { - if (collapsed) - { + if (collapsed) { return 0; } auto last = rows[numRows() - 1]; @@ -256,11 +242,9 @@ int VisualGroup::verticalPosition() const QList VisualGroup::items() const { QList indices; - for (int i = 0; i < view->model()->rowCount(); ++i) - { + for (int i = 0; i < view->model()->rowCount(); ++i) { const QModelIndex index = view->model()->index(i, 0); - if (index.data(InstanceViewRoles::GroupRole).toString() == text) - { + if (index.data(InstanceViewRoles::GroupRole).toString() == text) { indices.append(index); } } From 1dc7f800347d6b4e179a12de14af7f4ad87b7f27 Mon Sep 17 00:00:00 2001 From: Tayou Date: Wed, 28 Jun 2023 23:02:34 +0200 Subject: [PATCH 087/216] 4 clang-tidy changes, update copyright info while already at it I updated all my emails to use one from my domain Signed-off-by: Tayou --- launcher/Application.cpp | 2 +- launcher/Application.h | 2 +- launcher/ui/instanceview/VisualGroup.cpp | 12 +++-- launcher/ui/instanceview/VisualGroup.h | 48 +++++++++++++------ launcher/ui/pages/global/LauncherPage.cpp | 2 +- launcher/ui/setupwizard/ThemeWizardPage.cpp | 2 +- launcher/ui/setupwizard/ThemeWizardPage.h | 2 +- launcher/ui/themes/CustomTheme.cpp | 2 +- launcher/ui/themes/CustomTheme.h | 2 +- launcher/ui/themes/ITheme.cpp | 2 +- launcher/ui/themes/ITheme.h | 2 +- launcher/ui/themes/SystemTheme.cpp | 2 +- launcher/ui/themes/SystemTheme.h | 2 +- launcher/ui/themes/ThemeManager.cpp | 2 +- launcher/ui/themes/ThemeManager.h | 2 +- .../ui/widgets/ThemeCustomizationWidget.cpp | 2 +- .../ui/widgets/ThemeCustomizationWidget.h | 2 +- 17 files changed, 56 insertions(+), 34 deletions(-) diff --git a/launcher/Application.cpp b/launcher/Application.cpp index 1d97a5f2e..8e1d0cbdd 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -6,7 +6,7 @@ * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * Copyright (C) 2022 Lenny McLennington - * Copyright (C) 2022 Tayou + * Copyright (C) 2022 Tayou * Copyright (C) 2023 TheKodeToad * Copyright (C) 2023 Rachel Powers <508861+Ryex@users.noreply.github.com> * diff --git a/launcher/Application.h b/launcher/Application.h index ced0af17d..527c536b3 100644 --- a/launcher/Application.h +++ b/launcher/Application.h @@ -2,7 +2,7 @@ /* * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu - * Copyright (C) 2022 Tayou + * Copyright (C) 2022 Tayou * Copyright (C) 2023 TheKodeToad * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/ui/instanceview/VisualGroup.cpp b/launcher/ui/instanceview/VisualGroup.cpp index 9b2189b85..8663633b4 100644 --- a/launcher/ui/instanceview/VisualGroup.cpp +++ b/launcher/ui/instanceview/VisualGroup.cpp @@ -1,7 +1,8 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu + * Copyright (C) 2023 Tayou * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -40,10 +41,11 @@ #include #include #include +#include #include "InstanceView.h" -VisualGroup::VisualGroup(const QString& text, InstanceView* view) : view(view), text(text), collapsed(false) {} +VisualGroup::VisualGroup(QString text, InstanceView* view) : view(view), text(std::move(text)), collapsed(false) {} VisualGroup::VisualGroup(const VisualGroup* other) : view(other->view), text(other->text), collapsed(other->collapsed) {} @@ -138,7 +140,7 @@ VisualGroup::HitResults VisualGroup::hitScan(const QPoint& pos) const return results; } -void VisualGroup::drawHeader(QPainter* painter, const QStyleOptionViewItem& option) +void VisualGroup::drawHeader(QPainter* painter, const QStyleOptionViewItem& option) const { QRect optRect = option.rect; optRect.setTop(optRect.top() + 7); @@ -202,7 +204,7 @@ int VisualGroup::totalHeight() const return headerHeight() + contentHeight(); } -int VisualGroup::headerHeight() const +int VisualGroup::headerHeight() { QFont font(QApplication::font()); font.setBold(true); @@ -231,7 +233,7 @@ int VisualGroup::contentHeight() const int VisualGroup::numRows() const { - return rows.size(); + return (int)rows.size(); } int VisualGroup::verticalPosition() const diff --git a/launcher/ui/instanceview/VisualGroup.h b/launcher/ui/instanceview/VisualGroup.h index 5a743aa18..697298c2d 100644 --- a/launcher/ui/instanceview/VisualGroup.h +++ b/launcher/ui/instanceview/VisualGroup.h @@ -1,16 +1,36 @@ -/* Copyright 2013-2021 MultiMC Contributors +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (C) 2023 Tayou * - * 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 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * 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. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Copyright 2013-2021 MultiMC Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ #pragma once @@ -42,8 +62,8 @@ struct VisualRow struct VisualGroup { /* constructors */ - VisualGroup(const QString &text, InstanceView *view); - VisualGroup(const VisualGroup *other); + VisualGroup(QString text, InstanceView *view); + explicit VisualGroup(const VisualGroup *other); /* data */ InstanceView *view = nullptr; @@ -58,13 +78,13 @@ struct VisualGroup void update(); /// draw the header at y-position. - void drawHeader(QPainter *painter, const QStyleOptionViewItem &option); + void drawHeader(QPainter *painter, const QStyleOptionViewItem &option) const; /// height of the group, in total. includes a small bit of padding. int totalHeight() const; /// height of the group header, in pixels - int headerHeight() const; + static int headerHeight() ; /// height of the group content, in pixels int contentHeight() const; diff --git a/launcher/ui/pages/global/LauncherPage.cpp b/launcher/ui/pages/global/LauncherPage.cpp index 816dde723..2080b56f0 100644 --- a/launcher/ui/pages/global/LauncherPage.cpp +++ b/launcher/ui/pages/global/LauncherPage.cpp @@ -3,7 +3,7 @@ * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 Jamie Mansfield * Copyright (c) 2022 dada513 - * Copyright (C) 2022 Tayou + * Copyright (C) 2022 Tayou * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/launcher/ui/setupwizard/ThemeWizardPage.cpp b/launcher/ui/setupwizard/ThemeWizardPage.cpp index 42826aba1..c3e0a5241 100644 --- a/launcher/ui/setupwizard/ThemeWizardPage.cpp +++ b/launcher/ui/setupwizard/ThemeWizardPage.cpp @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-only /* * Prism Launcher - Minecraft Launcher - * Copyright (C) 2022 Tayou + * Copyright (C) 2022 Tayou * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/launcher/ui/setupwizard/ThemeWizardPage.h b/launcher/ui/setupwizard/ThemeWizardPage.h index 61a3d0c01..f3d40b6d8 100644 --- a/launcher/ui/setupwizard/ThemeWizardPage.h +++ b/launcher/ui/setupwizard/ThemeWizardPage.h @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-only /* * Prism Launcher - Minecraft Launcher - * Copyright (C) 2022 Tayou + * Copyright (C) 2022 Tayou * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/launcher/ui/themes/CustomTheme.cpp b/launcher/ui/themes/CustomTheme.cpp index 198e76ba1..177edefad 100644 --- a/launcher/ui/themes/CustomTheme.cpp +++ b/launcher/ui/themes/CustomTheme.cpp @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-only /* * Prism Launcher - Minecraft Launcher - * Copyright (C) 2022 Tayou + * Copyright (C) 2022 Tayou * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/launcher/ui/themes/CustomTheme.h b/launcher/ui/themes/CustomTheme.h index f2b1b06ed..3ec4cafa2 100644 --- a/launcher/ui/themes/CustomTheme.h +++ b/launcher/ui/themes/CustomTheme.h @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-only /* * Prism Launcher - Minecraft Launcher - * Copyright (C) 2022 Tayou + * Copyright (C) 2022 Tayou * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/launcher/ui/themes/ITheme.cpp b/launcher/ui/themes/ITheme.cpp index 8f0757e1a..42d63b113 100644 --- a/launcher/ui/themes/ITheme.cpp +++ b/launcher/ui/themes/ITheme.cpp @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-only /* * Prism Launcher - Minecraft Launcher - * Copyright (C) 2022 Tayou + * Copyright (C) 2022 Tayou * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/launcher/ui/themes/ITheme.h b/launcher/ui/themes/ITheme.h index a0a638bd0..d85e7f983 100644 --- a/launcher/ui/themes/ITheme.h +++ b/launcher/ui/themes/ITheme.h @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-only /* * Prism Launcher - Minecraft Launcher - * Copyright (C) 2022 Tayou + * Copyright (C) 2022 Tayou * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/launcher/ui/themes/SystemTheme.cpp b/launcher/ui/themes/SystemTheme.cpp index 3a746d027..3b8cb24a4 100644 --- a/launcher/ui/themes/SystemTheme.cpp +++ b/launcher/ui/themes/SystemTheme.cpp @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-only /* * Prism Launcher - Minecraft Launcher - * Copyright (C) 2022 Tayou + * Copyright (C) 2022 Tayou * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/launcher/ui/themes/SystemTheme.h b/launcher/ui/themes/SystemTheme.h index 05f31233e..4f7d83e57 100644 --- a/launcher/ui/themes/SystemTheme.h +++ b/launcher/ui/themes/SystemTheme.h @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-only /* * Prism Launcher - Minecraft Launcher - * Copyright (C) 2022 Tayou + * Copyright (C) 2022 Tayou * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/launcher/ui/themes/ThemeManager.cpp b/launcher/ui/themes/ThemeManager.cpp index 94ac8a245..b50c6157f 100644 --- a/launcher/ui/themes/ThemeManager.cpp +++ b/launcher/ui/themes/ThemeManager.cpp @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-only /* * Prism Launcher - Minecraft Launcher - * Copyright (C) 2022 Tayou + * Copyright (C) 2022 Tayou * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/launcher/ui/themes/ThemeManager.h b/launcher/ui/themes/ThemeManager.h index 87f36d9c1..d2a6fb70a 100644 --- a/launcher/ui/themes/ThemeManager.h +++ b/launcher/ui/themes/ThemeManager.h @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-only /* * Prism Launcher - Minecraft Launcher - * Copyright (C) 2022 Tayou + * Copyright (C) 2022 Tayou * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/launcher/ui/widgets/ThemeCustomizationWidget.cpp b/launcher/ui/widgets/ThemeCustomizationWidget.cpp index dcf13303c..3bfcd8213 100644 --- a/launcher/ui/widgets/ThemeCustomizationWidget.cpp +++ b/launcher/ui/widgets/ThemeCustomizationWidget.cpp @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-only /* * Prism Launcher - Minecraft Launcher - * Copyright (C) 2022 Tayou + * Copyright (C) 2022 Tayou * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/launcher/ui/widgets/ThemeCustomizationWidget.h b/launcher/ui/widgets/ThemeCustomizationWidget.h index d955a2665..6c33c3c50 100644 --- a/launcher/ui/widgets/ThemeCustomizationWidget.h +++ b/launcher/ui/widgets/ThemeCustomizationWidget.h @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-only /* * Prism Launcher - Minecraft Launcher - * Copyright (C) 2022 Tayou + * Copyright (C) 2022 Tayou * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by From 8211befc29a4a5b05e1ff1bdd3e7fc2dfb90fc82 Mon Sep 17 00:00:00 2001 From: Tayou Date: Wed, 28 Jun 2023 23:24:57 +0200 Subject: [PATCH 088/216] removed magic 5, removed unnecessary QPainter function calls Signed-off-by: Tayou --- launcher/ui/instanceview/VisualGroup.cpp | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/launcher/ui/instanceview/VisualGroup.cpp b/launcher/ui/instanceview/VisualGroup.cpp index 8663633b4..7d52e4ad7 100644 --- a/launcher/ui/instanceview/VisualGroup.cpp +++ b/launcher/ui/instanceview/VisualGroup.cpp @@ -120,7 +120,7 @@ VisualGroup::HitResults VisualGroup::hitScan(const QPoint& pos) const VisualGroup::HitResults results = VisualGroup::NoHit; int y_start = verticalPosition(); int body_start = y_start + headerHeight(); - int body_end = body_start + contentHeight() + 5; // FIXME: wtf is this 5? + int body_end = body_start + contentHeight(); int y = pos.y(); // int x = pos.x(); if (y < y_start) { @@ -147,8 +147,7 @@ void VisualGroup::drawHeader(QPainter* painter, const QStyleOptionViewItem& opti QFont font(QApplication::font()); font.setBold(true); const QFontMetrics fontMetrics = QFontMetrics(font); - - int centerHeight = optRect.top() + fontMetrics.height() / 2; + painter->setFont(font); QPen pen; pen.setWidth(2); @@ -157,14 +156,15 @@ void VisualGroup::drawHeader(QPainter* painter, const QStyleOptionViewItem& opti pen.setColor(penColor); painter->setPen(pen); + // sizes and offsets, to keep things consistent below int arrowOffsetLeft = fontMetrics.height() / 2 + 7; int textOffsetLeft = arrowOffsetLeft * 2; int arrowSize = 6; + int centerHeight = optRect.top() + fontMetrics.height() / 2; // BEGIN: arrow { painter->setRenderHint(QPainter::Antialiasing, false); - painter->save(); QPolygon polygon; if (collapsed) { @@ -178,7 +178,6 @@ void VisualGroup::drawHeader(QPainter* painter, const QStyleOptionViewItem& opti << QPoint(arrowOffsetLeft + arrowSize, centerHeight - arrowSize / 2); painter->drawPolyline(polygon); } - painter->restore(); } // END: arrow @@ -191,10 +190,7 @@ void VisualGroup::drawHeader(QPainter* painter, const QStyleOptionViewItem& opti textRect.setHeight(fontMetrics.height()); textRect.setRight(textRect.right() - 7); - painter->save(); - painter->setFont(font); painter->drawText(textRect, Qt::AlignLeft | Qt::AlignVCenter, !text.isEmpty() ? text : QObject::tr("Ungrouped")); - painter->restore(); } // END: text } From 87efa700ab53148f0555605fa21c683f3a9c3d15 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 30 Jun 2023 00:01:36 +0300 Subject: [PATCH 089/216] Removed logs from instance export Signed-off-by: Trial97 --- launcher/FileIgnoreProxy.cpp | 14 ++++++++++ launcher/FileIgnoreProxy.h | 8 ++++++ launcher/ui/dialogs/ExportInstanceDialog.cpp | 28 +++++++++++--------- launcher/ui/dialogs/ExportMrPackDialog.cpp | 3 ++- 4 files changed, 40 insertions(+), 13 deletions(-) diff --git a/launcher/FileIgnoreProxy.cpp b/launcher/FileIgnoreProxy.cpp index a3b7d5054..1f6b664c2 100644 --- a/launcher/FileIgnoreProxy.cpp +++ b/launcher/FileIgnoreProxy.cpp @@ -40,6 +40,7 @@ #include #include #include +#include #include "FileSystem.h" #include "SeparatorPrefixTree.h" #include "StringUtils.h" @@ -254,3 +255,16 @@ bool FileIgnoreProxy::filterAcceptsColumn(int source_column, const QModelIndex& return true; } + +bool FileIgnoreProxy::filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const +{ + QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent); + QFileSystemModel* fsm = qobject_cast(sourceModel()); + + auto fileInfo = fsm->fileInfo(index); + auto fileName = fileInfo.fileName(); + auto path = relPath(fileInfo.absoluteFilePath()); + return !(path.startsWith("..") || // just in case ignore files outside the gameroot + std::any_of(m_ignoreFiles.cbegin(), m_ignoreFiles.cend(), [fileName](auto iFileName) { return fileName == iFileName; }) || + std::any_of(m_ignoreFilePaths.cbegin(), m_ignoreFilePaths.cend(), [path](auto iPath) { return path == iPath; })); +} diff --git a/launcher/FileIgnoreProxy.h b/launcher/FileIgnoreProxy.h index a5a1153d8..dbd353e0b 100644 --- a/launcher/FileIgnoreProxy.h +++ b/launcher/FileIgnoreProxy.h @@ -63,10 +63,18 @@ class FileIgnoreProxy : public QSortFilterProxyModel { inline const SeparatorPrefixTree<'/'>& blockedPaths() const { return blocked; } inline SeparatorPrefixTree<'/'>& blockedPaths() { return blocked; } + // list of file names that need to be removed completely from model + inline QStringList& ignoreFilesWithName() { return m_ignoreFiles; } + // list of relative paths that need to be removed completely from model + inline QStringList& ignoreFilesWithPath() { return m_ignoreFilePaths; } + protected: bool filterAcceptsColumn(int source_column, const QModelIndex& source_parent) const; + bool filterAcceptsRow(int source_row, const QModelIndex& source_parent) const; private: const QString root; SeparatorPrefixTree<'/'> blocked; + QStringList m_ignoreFiles; + QStringList m_ignoreFilePaths; }; diff --git a/launcher/ui/dialogs/ExportInstanceDialog.cpp b/launcher/ui/dialogs/ExportInstanceDialog.cpp index 8ecd91a90..8d0e05a20 100644 --- a/launcher/ui/dialogs/ExportInstanceDialog.cpp +++ b/launcher/ui/dialogs/ExportInstanceDialog.cpp @@ -35,24 +35,24 @@ */ #include "ExportInstanceDialog.h" -#include "ui_ExportInstanceDialog.h" #include #include #include -#include #include +#include +#include "ui_ExportInstanceDialog.h" -#include -#include -#include -#include -#include -#include "SeparatorPrefixTree.h" -#include "Application.h" -#include #include +#include +#include +#include +#include +#include +#include +#include "Application.h" +#include "SeparatorPrefixTree.h" -ExportInstanceDialog::ExportInstanceDialog(InstancePtr instance, QWidget *parent) +ExportInstanceDialog::ExportInstanceDialog(InstancePtr instance, QWidget* parent) : QDialog(parent), ui(new Ui::ExportInstanceDialog), m_instance(instance) { ui->setupUi(this); @@ -60,8 +60,12 @@ ExportInstanceDialog::ExportInstanceDialog(InstancePtr instance, QWidget *parent model->setIconProvider(&icons); auto root = instance->instanceRoot(); proxyModel = new FileIgnoreProxy(root, this); - loadPackIgnore(); proxyModel->setSourceModel(model); + auto prefix = QDir(instance->instanceRoot()).relativeFilePath(instance->gameRoot()); + proxyModel->ignoreFilesWithPath().append({ FS::PathCombine(prefix, "logs"), FS::PathCombine(prefix, "crash-reports") }); + proxyModel->ignoreFilesWithName().append({ ".DS_Store", "thumbs.db", "Thumbs.db" }); + loadPackIgnore(); + ui->treeView->setModel(proxyModel); ui->treeView->setRootIndex(proxyModel->mapFromSource(model->index(root))); ui->treeView->sortByColumn(0, Qt::AscendingOrder); diff --git a/launcher/ui/dialogs/ExportMrPackDialog.cpp b/launcher/ui/dialogs/ExportMrPackDialog.cpp index 60ecefd5c..f1d2610a6 100644 --- a/launcher/ui/dialogs/ExportMrPackDialog.cpp +++ b/launcher/ui/dialogs/ExportMrPackDialog.cpp @@ -52,8 +52,9 @@ ExportMrPackDialog::ExportMrPackDialog(InstancePtr instance, QWidget* parent) // use the game root - everything outside cannot be exported const QDir root(instance->gameRoot()); proxy = new FileIgnoreProxy(instance->gameRoot(), this); + proxy->ignoreFilesWithPath().append({ "logs", "crash-reports" }); + proxy->ignoreFilesWithName().append({ ".DS_Store", "thumbs.db", "Thumbs.db" }); proxy->setSourceModel(model); - proxy->setFilterRegularExpression("^(?!(\\.DS_Store)|([tT]humbs\\.db)).+$"); const QDir::Filters filter(QDir::AllEntries | QDir::NoDotAndDotDot | QDir::AllDirs | QDir::Hidden); From 81207c65027a35d37394abe3ba6e3ef43777910a Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 30 Jun 2023 10:52:10 +0300 Subject: [PATCH 090/216] Made sure the logs are ignored when collecting files Signed-off-by: Trial97 --- launcher/FileIgnoreProxy.cpp | 16 +++++++++++++--- launcher/FileIgnoreProxy.h | 9 +++++++-- launcher/ui/dialogs/ExportInstanceDialog.cpp | 8 ++++---- launcher/ui/dialogs/ExportMrPackDialog.cpp | 4 ++-- 4 files changed, 26 insertions(+), 11 deletions(-) diff --git a/launcher/FileIgnoreProxy.cpp b/launcher/FileIgnoreProxy.cpp index 1f6b664c2..556e992c2 100644 --- a/launcher/FileIgnoreProxy.cpp +++ b/launcher/FileIgnoreProxy.cpp @@ -262,9 +262,19 @@ bool FileIgnoreProxy::filterAcceptsRow(int sourceRow, const QModelIndex& sourceP QFileSystemModel* fsm = qobject_cast(sourceModel()); auto fileInfo = fsm->fileInfo(index); + return !ignoreFile(fileInfo); +} + +bool FileIgnoreProxy::ignoreFile(QFileInfo fileInfo) const +{ auto fileName = fileInfo.fileName(); auto path = relPath(fileInfo.absoluteFilePath()); - return !(path.startsWith("..") || // just in case ignore files outside the gameroot - std::any_of(m_ignoreFiles.cbegin(), m_ignoreFiles.cend(), [fileName](auto iFileName) { return fileName == iFileName; }) || - std::any_of(m_ignoreFilePaths.cbegin(), m_ignoreFilePaths.cend(), [path](auto iPath) { return path == iPath; })); + return (path.startsWith("..") || // just in case ignore files outside the gameroot + std::any_of(m_ignoreFiles.cbegin(), m_ignoreFiles.cend(), [fileName](auto iFileName) { return fileName == iFileName; }) || + m_ignoreFilePaths.covers(path)); +} + +bool FileIgnoreProxy::filterFile(const QString& fileName) const +{ + return blocked.covers(fileName) || ignoreFile(QFileInfo(QDir(root), fileName)); } diff --git a/launcher/FileIgnoreProxy.h b/launcher/FileIgnoreProxy.h index dbd353e0b..e01a2651e 100644 --- a/launcher/FileIgnoreProxy.h +++ b/launcher/FileIgnoreProxy.h @@ -36,6 +36,7 @@ #pragma once +#include #include #include "SeparatorPrefixTree.h" @@ -66,15 +67,19 @@ class FileIgnoreProxy : public QSortFilterProxyModel { // list of file names that need to be removed completely from model inline QStringList& ignoreFilesWithName() { return m_ignoreFiles; } // list of relative paths that need to be removed completely from model - inline QStringList& ignoreFilesWithPath() { return m_ignoreFilePaths; } + inline SeparatorPrefixTree<'/'>& ignoreFilesWithPath() { return m_ignoreFilePaths; } + + bool filterFile(const QString& fileName) const; protected: bool filterAcceptsColumn(int source_column, const QModelIndex& source_parent) const; bool filterAcceptsRow(int source_row, const QModelIndex& source_parent) const; + bool ignoreFile(QFileInfo file) const; + private: const QString root; SeparatorPrefixTree<'/'> blocked; QStringList m_ignoreFiles; - QStringList m_ignoreFilePaths; + SeparatorPrefixTree<'/'> m_ignoreFilePaths; }; diff --git a/launcher/ui/dialogs/ExportInstanceDialog.cpp b/launcher/ui/dialogs/ExportInstanceDialog.cpp index 8d0e05a20..cc41c394d 100644 --- a/launcher/ui/dialogs/ExportInstanceDialog.cpp +++ b/launcher/ui/dialogs/ExportInstanceDialog.cpp @@ -40,6 +40,7 @@ #include #include #include +#include "FileIgnoreProxy.h" #include "ui_ExportInstanceDialog.h" #include @@ -49,6 +50,7 @@ #include #include #include +#include #include "Application.h" #include "SeparatorPrefixTree.h" @@ -62,7 +64,7 @@ ExportInstanceDialog::ExportInstanceDialog(InstancePtr instance, QWidget* parent proxyModel = new FileIgnoreProxy(root, this); proxyModel->setSourceModel(model); auto prefix = QDir(instance->instanceRoot()).relativeFilePath(instance->gameRoot()); - proxyModel->ignoreFilesWithPath().append({ FS::PathCombine(prefix, "logs"), FS::PathCombine(prefix, "crash-reports") }); + proxyModel->ignoreFilesWithPath().insert({ FS::PathCombine(prefix, "logs"), FS::PathCombine(prefix, "crash-reports") }); proxyModel->ignoreFilesWithName().append({ ".DS_Store", "thumbs.db", "Thumbs.db" }); loadPackIgnore(); @@ -137,11 +139,9 @@ bool ExportInstanceDialog::doExport() SaveIcon(m_instance); - auto & blocked = proxyModel->blockedPaths(); - using std::placeholders::_1; auto files = QFileInfoList(); if (!MMCZip::collectFileListRecursively(m_instance->instanceRoot(), nullptr, &files, - std::bind(&SeparatorPrefixTree<'/'>::covers, blocked, _1))) { + std::bind(&FileIgnoreProxy::filterFile, proxyModel, std::placeholders::_1))) { QMessageBox::warning(this, tr("Error"), tr("Unable to export instance")); return false; } diff --git a/launcher/ui/dialogs/ExportMrPackDialog.cpp b/launcher/ui/dialogs/ExportMrPackDialog.cpp index f1d2610a6..b302f7ba5 100644 --- a/launcher/ui/dialogs/ExportMrPackDialog.cpp +++ b/launcher/ui/dialogs/ExportMrPackDialog.cpp @@ -52,7 +52,7 @@ ExportMrPackDialog::ExportMrPackDialog(InstancePtr instance, QWidget* parent) // use the game root - everything outside cannot be exported const QDir root(instance->gameRoot()); proxy = new FileIgnoreProxy(instance->gameRoot(), this); - proxy->ignoreFilesWithPath().append({ "logs", "crash-reports" }); + proxy->ignoreFilesWithPath().insert({ "logs", "crash-reports" }); proxy->ignoreFilesWithName().append({ ".DS_Store", "thumbs.db", "Thumbs.db" }); proxy->setSourceModel(model); @@ -100,7 +100,7 @@ void ExportMrPackDialog::done(int result) return; ModrinthPackExportTask task(ui->name->text(), ui->version->text(), ui->summary->text(), instance, output, - [this](const QString& path) { return proxy->blockedPaths().covers(path); }); + std::bind(&FileIgnoreProxy::filterFile, proxy, std::placeholders::_1)); connect(&task, &Task::failed, [this](const QString reason) { CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->show(); }); From 18e628e8733df2f49f20cc1989817b2272cdf151 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 30 Jun 2023 12:10:00 +0300 Subject: [PATCH 091/216] removed extra condition Signed-off-by: Trial97 --- launcher/FileIgnoreProxy.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/launcher/FileIgnoreProxy.cpp b/launcher/FileIgnoreProxy.cpp index 556e992c2..4c8c64c72 100644 --- a/launcher/FileIgnoreProxy.cpp +++ b/launcher/FileIgnoreProxy.cpp @@ -269,9 +269,8 @@ bool FileIgnoreProxy::ignoreFile(QFileInfo fileInfo) const { auto fileName = fileInfo.fileName(); auto path = relPath(fileInfo.absoluteFilePath()); - return (path.startsWith("..") || // just in case ignore files outside the gameroot - std::any_of(m_ignoreFiles.cbegin(), m_ignoreFiles.cend(), [fileName](auto iFileName) { return fileName == iFileName; }) || - m_ignoreFilePaths.covers(path)); + return std::any_of(m_ignoreFiles.cbegin(), m_ignoreFiles.cend(), [fileName](auto iFileName) { return fileName == iFileName; }) || + m_ignoreFilePaths.covers(path); } bool FileIgnoreProxy::filterFile(const QString& fileName) const From 3fe518ff2b9ef902ff44b2c8249bafdf61f8e5eb Mon Sep 17 00:00:00 2001 From: Finian Wright Date: Sun, 2 Jul 2023 00:35:37 -0400 Subject: [PATCH 092/216] Fix compiling on OpenBSD Signed-off-by: Finian Wright --- launcher/FileSystem.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/launcher/FileSystem.cpp b/launcher/FileSystem.cpp index 1ea9f755a..3ce8dd2c7 100644 --- a/launcher/FileSystem.cpp +++ b/launcher/FileSystem.cpp @@ -102,7 +102,7 @@ namespace fs = ghc::filesystem; #include #include #include -#elif defined(Q_OS_MACOS) || defined(Q_OS_OPENBSD) +#elif defined(Q_OS_MACOS) #include #include #elif defined(Q_OS_WIN) @@ -1156,7 +1156,7 @@ bool clone_file(const QString& src, const QString& dst, std::error_code& ec) return false; } -#elif defined(Q_OS_MACOS) || defined(Q_OS_OPENBSD) +#elif defined(Q_OS_MACOS) if (!macos_bsd_clonefile(src_path, dst_path, ec)) { qDebug() << "failed macos_bsd_clonefile:"; @@ -1385,7 +1385,7 @@ bool linux_ficlone(const std::string& src_path, const std::string& dst_path, std return true; } -#elif defined(Q_OS_MACOS) || defined(Q_OS_OPENBSD) +#elif defined(Q_OS_MACOS) bool macos_bsd_clonefile(const std::string& src_path, const std::string& dst_path, std::error_code& ec) { From 7579fff532629643384d9b8011e885028ca9a8f0 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sun, 2 Jul 2023 13:34:04 +0300 Subject: [PATCH 093/216] Added more options for variants planing Signed-off-by: Trial97 --- launcher/ui/themes/CatPack.cpp | 10 ++++++---- launcher/ui/themes/CatPack.h | 4 ++-- launcher/ui/themes/ThemeManager.cpp | 2 +- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/launcher/ui/themes/CatPack.cpp b/launcher/ui/themes/CatPack.cpp index 2d5653a67..a0b06a600 100644 --- a/launcher/ui/themes/CatPack.cpp +++ b/launcher/ui/themes/CatPack.cpp @@ -99,11 +99,13 @@ JsonCatPack::JsonCatPack(QFileInfo& manifestInfo) : BasicCatPack(manifestInfo.di QString JsonCatPack::path() { - const QDateTime now = QDateTime::currentDateTime(); + const QDate now = QDate::currentDate(); for (auto var : m_variants) { - QDateTime startDate(QDate(now.date().year(), var.startTime.mounth, var.startTime.day), QTime(0, 0)); - QDateTime endDate(QDate(now.date().year(), var.endTime.mounth, var.endTime.day), QTime(0, 0)); - if (startDate.daysTo(now) > 0 && now.daysTo(endDate) > 0) + QDate startDate(now.year(), var.startTime.month, var.startTime.day); + QDate endDate(now.year(), var.endTime.month, var.endTime.day); + if (startDate.daysTo(endDate) < 0) // in this case end date should be next year + endDate = endDate.addYears(1); + if (startDate.daysTo(now) >= 0 && now.daysTo(endDate) >= 0) return var.path; } return m_defaultPath; diff --git a/launcher/ui/themes/CatPack.h b/launcher/ui/themes/CatPack.h index 9f288d3dd..e22df1f42 100644 --- a/launcher/ui/themes/CatPack.h +++ b/launcher/ui/themes/CatPack.h @@ -79,9 +79,9 @@ class JsonCatPack : public BasicCatPack { auto sp = d.split("-"); day = sp[0].toInt(); if (sp.length() >= 2) - mounth = sp[1].toInt(); + month = sp[1].toInt(); } - int mounth; + int month; int day; }; struct Variant { diff --git a/launcher/ui/themes/ThemeManager.cpp b/launcher/ui/themes/ThemeManager.cpp index bfd0550a8..d00b3a992 100644 --- a/launcher/ui/themes/ThemeManager.cpp +++ b/launcher/ui/themes/ThemeManager.cpp @@ -189,7 +189,7 @@ void ThemeManager::initializeCatPacks() while (ImageFileIterator.hasNext()) { QFile customCatFile(ImageFileIterator.next()); QFileInfo customCatFileInfo(customCatFile); - themeDebugLog() << "Loading QSS Theme from:" << customCatFileInfo.absoluteFilePath(); + themeDebugLog() << "Loading CatPack from:" << customCatFileInfo.absoluteFilePath(); addCatPack(std::unique_ptr(new FileCatPack(customCatFileInfo))); } }; From 81c0a1c4bd3b26c24a506e6d84c878b0786cf14a Mon Sep 17 00:00:00 2001 From: Tayou Date: Sun, 2 Jul 2023 14:01:56 +0200 Subject: [PATCH 094/216] antialiasing for all painting, make hitbox fullwidth Signed-off-by: Tayou --- launcher/ui/instanceview/VisualGroup.cpp | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/launcher/ui/instanceview/VisualGroup.cpp b/launcher/ui/instanceview/VisualGroup.cpp index 7d52e4ad7..aaf31941d 100644 --- a/launcher/ui/instanceview/VisualGroup.cpp +++ b/launcher/ui/instanceview/VisualGroup.cpp @@ -130,7 +130,7 @@ VisualGroup::HitResults VisualGroup::hitScan(const QPoint& pos) const int collapseSize = headerHeight() - 4; // the icon - QRect iconRect = QRect(view->m_leftMargin + 2, 2 + y_start, collapseSize, collapseSize); + QRect iconRect = QRect(view->m_leftMargin + 2, 2 + y_start, view->width() - 4, collapseSize); if (iconRect.contains(pos)) { results |= VisualGroup::CheckboxHit; } @@ -155,6 +155,7 @@ void VisualGroup::drawHeader(QPainter* painter, const QStyleOptionViewItem& opti penColor.setAlphaF(0.6); pen.setColor(penColor); painter->setPen(pen); + painter->setRenderHint(QPainter::Antialiasing); // sizes and offsets, to keep things consistent below int arrowOffsetLeft = fontMetrics.height() / 2 + 7; @@ -164,26 +165,23 @@ void VisualGroup::drawHeader(QPainter* painter, const QStyleOptionViewItem& opti // BEGIN: arrow { - painter->setRenderHint(QPainter::Antialiasing, false); - - QPolygon polygon; + QPolygon arrowPolygon; if (collapsed) { - polygon << QPoint(arrowOffsetLeft - arrowSize / 2, centerHeight - arrowSize) - << QPoint(arrowOffsetLeft + arrowSize / 2, centerHeight) - << QPoint(arrowOffsetLeft - arrowSize / 2, centerHeight + arrowSize); - painter->drawPolyline(polygon); + arrowPolygon << QPoint(arrowOffsetLeft - arrowSize / 2, centerHeight - arrowSize) + << QPoint(arrowOffsetLeft + arrowSize / 2, centerHeight) + << QPoint(arrowOffsetLeft - arrowSize / 2, centerHeight + arrowSize); + painter->drawPolyline(arrowPolygon); } else { - polygon << QPoint(arrowOffsetLeft - arrowSize, centerHeight - arrowSize / 2) - << QPoint(arrowOffsetLeft, centerHeight + arrowSize / 2) - << QPoint(arrowOffsetLeft + arrowSize, centerHeight - arrowSize / 2); - painter->drawPolyline(polygon); + arrowPolygon << QPoint(arrowOffsetLeft - arrowSize, centerHeight - arrowSize / 2) + << QPoint(arrowOffsetLeft, centerHeight + arrowSize / 2) + << QPoint(arrowOffsetLeft + arrowSize, centerHeight - arrowSize / 2); + painter->drawPolyline(arrowPolygon); } } // END: arrow // BEGIN: text { - painter->setRenderHint(QPainter::Antialiasing); QRect textRect(optRect); textRect.setTop(textRect.top()); textRect.setLeft(textOffsetLeft); From aad5ca5474ff015da30809260fe0f9d6cb503d61 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sun, 2 Jul 2023 16:45:15 +0300 Subject: [PATCH 095/216] fixed typos Signed-off-by: Trial97 --- launcher/modplatform/flame/FlamePackExportTask.cpp | 10 +++++----- launcher/ui/dialogs/ExportPackDialog.cpp | 1 + launcher/ui/dialogs/ExportPackDialog.ui | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/launcher/modplatform/flame/FlamePackExportTask.cpp b/launcher/modplatform/flame/FlamePackExportTask.cpp index 13308b50a..927146e1d 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.cpp +++ b/launcher/modplatform/flame/FlamePackExportTask.cpp @@ -105,7 +105,7 @@ void FlamePackExportTask::collectFiles() void FlamePackExportTask::collectHashes() { setAbortable(true); - setStatus(tr("Find file hashes...")); + setStatus(tr("Finding file hashes...")); setProgress(1, 5); auto allMods = mcInstance->loaderModList()->allMods(); ConcurrentTask::Ptr hashing_task(new ConcurrentTask(this, "MakeHashesTask", 10)); @@ -186,7 +186,7 @@ void FlamePackExportTask::makeApiRequest() return; } - setStatus(tr("Find versions for hashes...")); + setStatus(tr("Finding versions for hashes...")); setProgress(2, 5); auto response = std::make_shared(); @@ -255,10 +255,10 @@ void FlamePackExportTask::makeApiRequest() void FlamePackExportTask::getProjectsInfo() { - setStatus(tr("Find project info from CurseForge...")); + setStatus(tr("Finding project info from CurseForge...")); setProgress(3, 5); - QList addonIds; - for (auto resolved : resolvedFiles) { + QStringList addonIds; + for (const auto& resolved : resolvedFiles) { if (resolved.slug.isEmpty()) { addonIds << QString::number(resolved.addonId); } diff --git a/launcher/ui/dialogs/ExportPackDialog.cpp b/launcher/ui/dialogs/ExportPackDialog.cpp index a54a3c86f..2abe2805b 100644 --- a/launcher/ui/dialogs/ExportPackDialog.cpp +++ b/launcher/ui/dialogs/ExportPackDialog.cpp @@ -41,6 +41,7 @@ ExportPackDialog::ExportPackDialog(InstancePtr instance, QWidget* parent, ModPla ui->name->setText(instance->name()); if (m_provider == ModPlatform::ResourceProvider::MODRINTH) { ui->summary->setText(instance->notes().split(QRegularExpression("\\r?\\n"))[0]); + setWindowTitle("Export Modrinth Pack"); } else { setWindowTitle("Export CurseForge Pack"); ui->version->setText(""); diff --git a/launcher/ui/dialogs/ExportPackDialog.ui b/launcher/ui/dialogs/ExportPackDialog.ui index 658e21994..3976e28f8 100644 --- a/launcher/ui/dialogs/ExportPackDialog.ui +++ b/launcher/ui/dialogs/ExportPackDialog.ui @@ -11,7 +11,7 @@ - Export Modrinth Pack + Export Pack true From 5f63c781b400aab29298b1eb2822477e35d87c01 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sun, 2 Jul 2023 18:50:29 +0300 Subject: [PATCH 096/216] resolved local vaiables names Signed-off-by: Trial97 --- .../modplatform/flame/FlamePackExportTask.cpp | 132 +++++++++--------- .../modrinth/ModrinthPackExportTask.cpp | 4 +- 2 files changed, 68 insertions(+), 68 deletions(-) diff --git a/launcher/modplatform/flame/FlamePackExportTask.cpp b/launcher/modplatform/flame/FlamePackExportTask.cpp index 927146e1d..1b75908ad 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.cpp +++ b/launcher/modplatform/flame/FlamePackExportTask.cpp @@ -108,8 +108,8 @@ void FlamePackExportTask::collectHashes() setStatus(tr("Finding file hashes...")); setProgress(1, 5); auto allMods = mcInstance->loaderModList()->allMods(); - ConcurrentTask::Ptr hashing_task(new ConcurrentTask(this, "MakeHashesTask", 10)); - task.reset(hashing_task); + ConcurrentTask::Ptr hashingTask(new ConcurrentTask(this, "MakeHashesTask", 10)); + task.reset(hashingTask); for (const QFileInfo& file : files) { const QString relative = gameRoot.relativeFilePath(file.absoluteFilePath()); // require sensible file types @@ -120,14 +120,14 @@ void FlamePackExportTask::collectHashes() if (relative.startsWith("resourcepacks/") && (relative.endsWith(".zip") || relative.endsWith(".zip.disabled"))) { // is resourcepack - auto hash_task = Hashing::createFlameHasher(file.absoluteFilePath()); - connect(hash_task.get(), &Hashing::Hasher::resultsReady, [this, relative, file](QString hash) { + auto hashTask = Hashing::createFlameHasher(file.absoluteFilePath()); + connect(hashTask.get(), &Hashing::Hasher::resultsReady, [this, relative, file](QString hash) { if (m_state == Task::State::Running) { pendingHashes.insert(hash, { relative, file.absoluteFilePath(), relative.endsWith(".zip") }); } }); - connect(hash_task.get(), &Task::failed, this, &FlamePackExportTask::emitFailed); - hashing_task->addTask(hash_task); + connect(hashTask.get(), &Task::failed, this, &FlamePackExportTask::emitFailed); + hashingTask->addTask(hashTask); continue; } @@ -144,39 +144,39 @@ void FlamePackExportTask::collectHashes() continue; } - auto hash_task = Hashing::createFlameHasher(mod->fileinfo().absoluteFilePath()); - connect(hash_task.get(), &Hashing::Hasher::resultsReady, [this, mod](QString hash) { + auto hashTask = Hashing::createFlameHasher(mod->fileinfo().absoluteFilePath()); + connect(hashTask.get(), &Hashing::Hasher::resultsReady, [this, mod](QString hash) { if (m_state == Task::State::Running) { pendingHashes.insert(hash, { mod->name(), mod->fileinfo().absoluteFilePath(), mod->enabled(), true }); } }); - connect(hash_task.get(), &Task::failed, this, &FlamePackExportTask::emitFailed); - hashing_task->addTask(hash_task); + connect(hashTask.get(), &Task::failed, this, &FlamePackExportTask::emitFailed); + hashingTask->addTask(hashTask); } } - auto step_progress = std::make_shared(); - connect(hashing_task.get(), &Task::finished, this, [this, step_progress] { - step_progress->state = TaskStepState::Succeeded; - stepProgress(*step_progress); + auto progressStep = std::make_shared(); + connect(hashingTask.get(), &Task::finished, this, [this, progressStep] { + progressStep->state = TaskStepState::Succeeded; + stepProgress(*progressStep); }); - connect(hashing_task.get(), &Task::succeeded, this, &FlamePackExportTask::makeApiRequest); - connect(hashing_task.get(), &Task::failed, this, [this, step_progress](QString reason) { - step_progress->state = TaskStepState::Failed; - stepProgress(*step_progress); + connect(hashingTask.get(), &Task::succeeded, this, &FlamePackExportTask::makeApiRequest); + connect(hashingTask.get(), &Task::failed, this, [this, progressStep](QString reason) { + progressStep->state = TaskStepState::Failed; + stepProgress(*progressStep); emitFailed(reason); }); - connect(hashing_task.get(), &Task::stepProgress, this, &FlamePackExportTask::propogateStepProgress); + connect(hashingTask.get(), &Task::stepProgress, this, &FlamePackExportTask::propogateStepProgress); - connect(hashing_task.get(), &Task::progress, this, [this, step_progress](qint64 current, qint64 total) { - step_progress->update(current, total); - stepProgress(*step_progress); + connect(hashingTask.get(), &Task::progress, this, [this, progressStep](qint64 current, qint64 total) { + progressStep->update(current, total); + stepProgress(*progressStep); }); - connect(hashing_task.get(), &Task::status, this, [this, step_progress](QString status) { - step_progress->status = status; - stepProgress(*step_progress); + connect(hashingTask.get(), &Task::status, this, [this, progressStep](QString status) { + progressStep->status = status; + stepProgress(*progressStep); }); - hashing_task->start(); + hashingTask->start(); } void FlamePackExportTask::makeApiRequest() @@ -198,38 +198,38 @@ void FlamePackExportTask::makeApiRequest() task.reset(api.matchFingerprints(fingerprints, response)); connect(task.get(), &Task::succeeded, this, [this, response] { - QJsonParseError parse_error{}; - QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error); - if (parse_error.error != QJsonParseError::NoError) { - qWarning() << "Error while parsing JSON response from CurseForge::CurrentVersions at " << parse_error.offset - << " reason: " << parse_error.errorString(); + QJsonParseError parseError{}; + QJsonDocument doc = QJsonDocument::fromJson(*response, &parseError); + if (parseError.error != QJsonParseError::NoError) { + qWarning() << "Error while parsing JSON response from CurseForge::CurrentVersions at " << parseError.offset + << " reason: " << parseError.errorString(); qWarning() << *response; - failed(parse_error.errorString()); + failed(parseError.errorString()); return; } try { - auto doc_obj = Json::requireObject(doc); - auto data_obj = Json::requireObject(doc_obj, "data"); - auto data_arr = Json::requireArray(data_obj, "exactMatches"); + auto docObj = Json::requireObject(doc); + auto dataObj = Json::requireObject(docObj, "data"); + auto dataArr = Json::requireArray(dataObj, "exactMatches"); - if (data_arr.isEmpty()) { + if (dataArr.isEmpty()) { qWarning() << "No matches found for fingerprint search!"; return; } - for (auto match : data_arr) { - auto match_obj = Json::ensureObject(match, {}); - auto file_obj = Json::ensureObject(match_obj, "file", {}); + for (auto match : dataArr) { + auto matchObj = Json::ensureObject(match, {}); + auto fileObj = Json::ensureObject(matchObj, "file", {}); - if (match_obj.isEmpty() || file_obj.isEmpty()) { + if (matchObj.isEmpty() || fileObj.isEmpty()) { qWarning() << "Fingerprint match is empty!"; return; } - auto fingerprint = QString::number(Json::ensureVariant(file_obj, "fileFingerprint").toUInt()); + auto fingerprint = QString::number(Json::ensureVariant(fileObj, "fileFingerprint").toUInt()); auto mod = pendingHashes.find(fingerprint); if (mod == pendingHashes.end()) { qWarning() << "Invalid fingerprint from the API response."; @@ -237,8 +237,8 @@ void FlamePackExportTask::makeApiRequest() } setStatus(tr("Parsing API response from CurseForge for '%1'...").arg(mod->name)); - if (Json::ensureBoolean(file_obj, "isAvailable", false, "isAvailable")) - resolvedFiles.insert(mod->path, { Json::requireInteger(file_obj, "modId"), Json::requireInteger(file_obj, "id"), + if (Json::ensureBoolean(fileObj, "isAvailable", false, "isAvailable")) + resolvedFiles.insert(mod->path, { Json::requireInteger(fileObj, "modId"), Json::requireInteger(fileObj, "id"), mod->enabled, mod->isMod }); } @@ -265,25 +265,25 @@ void FlamePackExportTask::getProjectsInfo() } auto response = std::make_shared(); - Task::Ptr proj_task; + Task::Ptr projTask; if (addonIds.isEmpty()) { buildZip(); return; } else if (addonIds.size() == 1) { - proj_task = api.getProject(*addonIds.begin(), response); + projTask = api.getProject(*addonIds.begin(), response); } else { - proj_task = api.getProjects(addonIds, response); + projTask = api.getProjects(addonIds, response); } - connect(proj_task.get(), &Task::succeeded, this, [this, response, addonIds] { - QJsonParseError parse_error{}; - auto doc = QJsonDocument::fromJson(*response, &parse_error); - if (parse_error.error != QJsonParseError::NoError) { - qWarning() << "Error while parsing JSON response from CurseForge projects task at " << parse_error.offset - << " reason: " << parse_error.errorString(); + connect(projTask.get(), &Task::succeeded, this, [this, response, addonIds] { + QJsonParseError parseError{}; + auto doc = QJsonDocument::fromJson(*response, &parseError); + if (parseError.error != QJsonParseError::NoError) { + qWarning() << "Error while parsing JSON response from CurseForge projects task at " << parseError.offset + << " reason: " << parseError.errorString(); qWarning() << *response; - failed(parse_error.errorString()); + failed(parseError.errorString()); return; } @@ -295,13 +295,13 @@ void FlamePackExportTask::getProjectsInfo() entries = Json::requireArray(Json::requireObject(doc), "data"); for (auto entry : entries) { - auto entry_obj = Json::requireObject(entry); + auto entryObj = Json::requireObject(entry); try { - setStatus(tr("Parsing API response from CurseForge for '%1'...").arg(Json::requireString(entry_obj, "name"))); + setStatus(tr("Parsing API response from CurseForge for '%1'...").arg(Json::requireString(entryObj, "name"))); ModPlatform::IndexedPack pack; - FlameMod::loadIndexedPack(pack, entry_obj); + FlameMod::loadIndexedPack(pack, entryObj); for (auto key : resolvedFiles.keys()) { auto val = resolvedFiles.value(key); if (val.addonId == pack.addonId) { @@ -327,7 +327,7 @@ void FlamePackExportTask::getProjectsInfo() } buildZip(); }); - task.reset(proj_task); + task.reset(projTask); task->start(); } @@ -370,18 +370,18 @@ void FlamePackExportTask::buildZip() content = "
      " + content + "
    "; modlist.write(content.toUtf8()); - auto step_progress = std::make_shared(); + auto progressStep = std::make_shared(); size_t progress = 0; for (const QFileInfo& file : files) { if (buildZipFuture.isCanceled()) { QFile::remove(output); - step_progress->state = TaskStepState::Failed; - stepProgress(*step_progress); + progressStep->state = TaskStepState::Failed; + stepProgress(*progressStep); return BuildZipResult(); } - step_progress->update(progress, files.length()); - stepProgress(*step_progress); + progressStep->update(progress, files.length()); + stepProgress(*progressStep); const QString relative = gameRoot.relativeFilePath(file.absoluteFilePath()); if (!resolvedFiles.contains(file.absoluteFilePath()) && @@ -396,12 +396,12 @@ void FlamePackExportTask::buildZip() if (zip.getZipError() != 0) { QFile::remove(output); - step_progress->state = TaskStepState::Failed; - stepProgress(*step_progress); + progressStep->state = TaskStepState::Failed; + stepProgress(*progressStep); return BuildZipResult(tr("A zip error occurred")); } - step_progress->state = TaskStepState::Succeeded; - stepProgress(*step_progress); + progressStep->state = TaskStepState::Succeeded; + stepProgress(*progressStep); return BuildZipResult(); }); connect(&buildZipWatcher, &QFutureWatcher::finished, this, &FlamePackExportTask::finish); diff --git a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp index a9a1f1c40..c8206f1e3 100644 --- a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp +++ b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp @@ -95,7 +95,7 @@ void ModrinthPackExportTask::collectFiles() void ModrinthPackExportTask::collectHashes() { - setStatus(tr("Find file hashes...")); + setStatus(tr("Finding file hashes...")); for (const QFileInfo& file : files) { QCoreApplication::processEvents(); @@ -159,7 +159,7 @@ void ModrinthPackExportTask::makeApiRequest() if (pendingHashes.isEmpty()) buildZip(); else { - setStatus(tr("Find versions for hashes...")); + setStatus(tr("Finding versions for hashes...")); auto response = std::make_shared(); task = api.currentVersions(pendingHashes.values(), "sha512", response); connect(task.get(), &NetJob::succeeded, [this, response]() { parseApiResponse(response); }); From 4004e0faeed99b3deb0ffb0b0f469594843ca14b Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Sun, 2 Jul 2023 20:22:25 -0700 Subject: [PATCH 097/216] fix: segfault in progress dialog - dialog tries to resize after unhiding the subtask scroll area - after resize attempts to recenter on parent - `calls parentWidget()->{x|y}()` - what if there is no parent? nullptr->() = segfault - recenter on last pos, don't access parent Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/ui/dialogs/ProgressDialog.cpp | 30 +++++++++++++++++--------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/launcher/ui/dialogs/ProgressDialog.cpp b/launcher/ui/dialogs/ProgressDialog.cpp index 246a0fd49..84f9db7e5 100644 --- a/launcher/ui/dialogs/ProgressDialog.cpp +++ b/launcher/ui/dialogs/ProgressDialog.cpp @@ -34,6 +34,7 @@ */ #include "ProgressDialog.h" +#include #include "ui_ProgressDialog.h" #include @@ -96,21 +97,30 @@ ProgressDialog::~ProgressDialog() void ProgressDialog::updateSize() { QSize lastSize = this->size(); - QSize qSize = QSize(480, minimumSizeHint().height()); + QPoint lastPos = this->pos(); + int minHeight = minimumSizeHint().height(); + if (ui->taskProgressScrollArea->isHidden()) + minHeight -= ui->taskProgressScrollArea->minimumSizeHint().height(); + QSize labelMinSize = ui->globalStatusLabel->minimumSize(); + int labelHeight = ui->globalStatusLabel->height(); + if (labelHeight > labelMinSize.height()) + minHeight += labelHeight - labelMinSize.height(); // account for multiline label + minHeight = std::max(minHeight, 0); + QSize minSize = QSize(480, minHeight); // if the current window is too small - if ((lastSize != qSize) && (lastSize.height() < qSize.height())) + if ((lastSize != minSize) && (lastSize.height() < minSize.height())) { - resize(qSize); - - // keep the dialog in the center after a resize - this->move( - this->parentWidget()->x() + (this->parentWidget()->width() - this->width()) / 2, - this->parentWidget()->y() + (this->parentWidget()->height() - this->height()) / 2 - ); + resize(minSize); + + QSize newSize = this->size(); + QSize sizeDiff = lastSize - newSize; // last size was smaller, the results should be negative + // center on old position after resize + QPoint newPos(lastPos.x() + (sizeDiff.width() / 2), lastPos.y() + (sizeDiff.height() / 2)); + this->move(newPos); } - setMinimumSize(qSize); + setMinimumSize(minSize); } From 3960eb7d32af6ea776634b9f94e12f8df2397627 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Sun, 2 Jul 2023 21:24:43 -0700 Subject: [PATCH 098/216] fix: properly calculate min size for progress dialog, apply it at creation Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/ui/dialogs/ProgressDialog.cpp | 27 +++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/launcher/ui/dialogs/ProgressDialog.cpp b/launcher/ui/dialogs/ProgressDialog.cpp index 84f9db7e5..f70eee49a 100644 --- a/launcher/ui/dialogs/ProgressDialog.cpp +++ b/launcher/ui/dialogs/ProgressDialog.cpp @@ -69,6 +69,7 @@ ProgressDialog::ProgressDialog(QWidget* parent) : QDialog(parent), ui(new Ui::Pr setAttribute(Qt::WidgetAttribute::WA_QuitOnClose, true); setSkipButton(false); changeProgress(0, 100); + updateSize(); } void ProgressDialog::setSkipButton(bool present, QString label) @@ -98,30 +99,28 @@ void ProgressDialog::updateSize() { QSize lastSize = this->size(); QPoint lastPos = this->pos(); - int minHeight = minimumSizeHint().height(); - if (ui->taskProgressScrollArea->isHidden()) - minHeight -= ui->taskProgressScrollArea->minimumSizeHint().height(); - QSize labelMinSize = ui->globalStatusLabel->minimumSize(); - int labelHeight = ui->globalStatusLabel->height(); - if (labelHeight > labelMinSize.height()) - minHeight += labelHeight - labelMinSize.height(); // account for multiline label - minHeight = std::max(minHeight, 0); + int minHeight = ui->globalStatusDetailsLabel->minimumSize().height() + (ui->verticalLayout->spacing() * 2); + minHeight += ui->globalProgressBar->minimumSize().height() + ui->verticalLayout->spacing(); + if (!ui->taskProgressScrollArea->isHidden()) + minHeight += ui->taskProgressScrollArea->minimumSizeHint().height() + ui->verticalLayout->spacing(); + if (ui->skipButton->isVisible()) + minHeight += ui->skipButton->height() + ui->verticalLayout->spacing(); + minHeight = std::max(minHeight, 60); QSize minSize = QSize(480, minHeight); + setMinimumSize(minSize); + adjustSize(); + + QSize newSize = this->size(); // if the current window is too small if ((lastSize != minSize) && (lastSize.height() < minSize.height())) { - resize(minSize); - - QSize newSize = this->size(); QSize sizeDiff = lastSize - newSize; // last size was smaller, the results should be negative // center on old position after resize QPoint newPos(lastPos.x() + (sizeDiff.width() / 2), lastPos.y() + (sizeDiff.height() / 2)); this->move(newPos); } - setMinimumSize(minSize); - } int ProgressDialog::execWithTask(Task* task) @@ -211,7 +210,9 @@ void ProgressDialog::onTaskSucceeded() void ProgressDialog::changeStatus(const QString& status) { ui->globalStatusLabel->setText(task->getStatus()); + ui->globalStatusLabel->adjustSize(); ui->globalStatusDetailsLabel->setText(task->getDetails()); + ui->globalStatusDetailsLabel->adjustSize(); updateSize(); } From 73d83439140377a7ece34e262ca4efab1608a03d Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Sun, 2 Jul 2023 22:27:24 -0700 Subject: [PATCH 099/216] fix: header `` -> `` Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/ui/dialogs/ProgressDialog.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/ui/dialogs/ProgressDialog.cpp b/launcher/ui/dialogs/ProgressDialog.cpp index f70eee49a..c6d8e573f 100644 --- a/launcher/ui/dialogs/ProgressDialog.cpp +++ b/launcher/ui/dialogs/ProgressDialog.cpp @@ -34,7 +34,7 @@ */ #include "ProgressDialog.h" -#include +#include #include "ui_ProgressDialog.h" #include From 8cb8273e67d4770300fdb7c3ce61feb19b1a899b Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Sun, 2 Jul 2023 22:29:45 -0700 Subject: [PATCH 100/216] fix: update if new size is larger Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/ui/dialogs/ProgressDialog.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/ui/dialogs/ProgressDialog.cpp b/launcher/ui/dialogs/ProgressDialog.cpp index c6d8e573f..f422d91e3 100644 --- a/launcher/ui/dialogs/ProgressDialog.cpp +++ b/launcher/ui/dialogs/ProgressDialog.cpp @@ -113,7 +113,7 @@ void ProgressDialog::updateSize() QSize newSize = this->size(); // if the current window is too small - if ((lastSize != minSize) && (lastSize.height() < minSize.height())) + if ((lastSize != minSize) && (lastSize.height() < newSize.height())) { QSize sizeDiff = lastSize - newSize; // last size was smaller, the results should be negative // center on old position after resize From e5b9bfb2e78ca86917d91fd41de1e797e570cf83 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Sun, 2 Jul 2023 22:30:25 -0700 Subject: [PATCH 101/216] fix: update if new size is larger Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/ui/dialogs/ProgressDialog.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/ui/dialogs/ProgressDialog.cpp b/launcher/ui/dialogs/ProgressDialog.cpp index f422d91e3..3368a8c47 100644 --- a/launcher/ui/dialogs/ProgressDialog.cpp +++ b/launcher/ui/dialogs/ProgressDialog.cpp @@ -113,7 +113,7 @@ void ProgressDialog::updateSize() QSize newSize = this->size(); // if the current window is too small - if ((lastSize != minSize) && (lastSize.height() < newSize.height())) + if ((lastSize != newSize) && (lastSize.height() < newSize.height())) { QSize sizeDiff = lastSize - newSize; // last size was smaller, the results should be negative // center on old position after resize From 5d5f1b86fdaa865bf8627acd86163469389ebb83 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Mon, 3 Jul 2023 09:21:25 +0300 Subject: [PATCH 102/216] fixed logic regarding range over multiple years Signed-off-by: Trial97 --- launcher/ui/themes/CatPack.cpp | 29 +++++++++++++++-------------- launcher/ui/themes/CatPack.h | 10 +++++----- 2 files changed, 20 insertions(+), 19 deletions(-) diff --git a/launcher/ui/themes/CatPack.cpp b/launcher/ui/themes/CatPack.cpp index 4170febd7..435ccdb88 100644 --- a/launcher/ui/themes/CatPack.cpp +++ b/launcher/ui/themes/CatPack.cpp @@ -34,11 +34,7 @@ */ #include "ui/themes/CatPack.h" -#include -#include -#include -#include -#include +#include #include #include #include "FileSystem.h" @@ -47,10 +43,10 @@ QString BasicCatPack::path() { - const QDateTime now = QDateTime::currentDateTime(); - const QDateTime birthday(QDate(now.date().year(), 11, 30), QTime(0, 0)); - const QDateTime xmas(QDate(now.date().year(), 12, 25), QTime(0, 0)); - const QDateTime halloween(QDate(now.date().year(), 10, 31), QTime(0, 0)); + const auto now = QDate::currentDate(); + const auto birthday = QDate(now.year(), 11, 30); + const auto xmas = QDate(now.year(), 12, 25); + const auto halloween = QDate(now.year(), 10, 31); QString cat = QString(":/backgrounds/%1").arg(m_id); if (std::abs(now.daysTo(xmas)) <= 4) { @@ -85,8 +81,8 @@ JsonCatPack::JsonCatPack(QFileInfo& manifestInfo) : BasicCatPack(manifestInfo.di for (auto v : variants) { auto variant = Json::ensureObject(v, QJsonObject(), "Cat variant"); m_variants << Variant{ FS::PathCombine(path, Json::requireString(variant, "path", "Variant path")), - date(Json::requireString(variant, "startTime", "Variant startTime")), - date(Json::requireString(variant, "endTime", "Variant endTime")) }; + PartialDate(Json::requireString(variant, "startTime", "Variant startTime")), + PartialDate(Json::requireString(variant, "endTime", "Variant endTime")) }; } } catch (const Exception& e) { @@ -104,9 +100,14 @@ QString JsonCatPack::path() for (auto var : m_variants) { QDate startDate(now.year(), var.startTime.month, var.startTime.day); QDate endDate(now.year(), var.endTime.month, var.endTime.day); - if (startDate.daysTo(endDate) < 0) // in this case end date should be next year - endDate = endDate.addYears(1); - if (startDate.daysTo(now) >= 0 && now.daysTo(endDate) >= 0) + if (startDate > endDate) { // it's spans over multiple years + if (endDate <= now) // end date is in the past so jump one year into the future for endDate + endDate = endDate.addYears(1); + else // end date is in the future so jump one year into the past for startDate + startDate = startDate.addYears(-1); + } + + if (startDate >= now && now >= endDate) return var.path; } return m_defaultPath; diff --git a/launcher/ui/themes/CatPack.h b/launcher/ui/themes/CatPack.h index e22df1f42..20cb8f61e 100644 --- a/launcher/ui/themes/CatPack.h +++ b/launcher/ui/themes/CatPack.h @@ -35,7 +35,7 @@ #pragma once -#include +#include #include #include #include @@ -73,8 +73,8 @@ class FileCatPack : public BasicCatPack { class JsonCatPack : public BasicCatPack { public: - struct date { - date(QString d) + struct PartialDate { + PartialDate(QString d) { auto sp = d.split("-"); day = sp[0].toInt(); @@ -86,8 +86,8 @@ class JsonCatPack : public BasicCatPack { }; struct Variant { QString path; - date startTime; - date endTime; + PartialDate startTime; + PartialDate endTime; }; JsonCatPack(QFileInfo& manifestInfo); virtual QString path(); From 026293f7731181b1198c3c5a9552dd340d13b4b5 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Mon, 3 Jul 2023 14:17:39 +0300 Subject: [PATCH 103/216] updated option text Signed-off-by: Trial97 --- launcher/ui/pages/instance/ExternalResourcesPage.ui | 2 +- launcher/ui/pages/instance/ModFolderPage.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/launcher/ui/pages/instance/ExternalResourcesPage.ui b/launcher/ui/pages/instance/ExternalResourcesPage.ui index 351aaf75c..3c8366917 100644 --- a/launcher/ui/pages/instance/ExternalResourcesPage.ui +++ b/launcher/ui/pages/instance/ExternalResourcesPage.ui @@ -162,7 +162,7 @@ false
    - Visit on mod's page + Visit mod's page Go to mods home page diff --git a/launcher/ui/pages/instance/ModFolderPage.cpp b/launcher/ui/pages/instance/ModFolderPage.cpp index 1d31a2925..ce6968f53 100644 --- a/launcher/ui/pages/instance/ModFolderPage.cpp +++ b/launcher/ui/pages/instance/ModFolderPage.cpp @@ -104,7 +104,7 @@ ModFolderPage::ModFolderPage(BaseInstance* inst, std::shared_ptr auto selected = std::count_if(mods_list.cbegin(), mods_list.cend(), [](Mod* v) { return v->metadata() != nullptr || v->homeurl().size() != 0; }); if (selected <= 1) { - ui->actionVisitItemPage->setText(tr("Visit on mod's page")); + ui->actionVisitItemPage->setText(tr("Visit mod's page")); ui->actionVisitItemPage->setToolTip(tr("Go to mod's home page")); } else { ui->actionVisitItemPage->setText(tr("Visit the pages of the selected mods")); From f0aab541f817347a932c65d3b06d2d4c1e7b90c1 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Mon, 3 Jul 2023 15:09:35 +0300 Subject: [PATCH 104/216] fixed typo Signed-off-by: Trial97 --- launcher/ui/widgets/InfoFrame.cpp | 91 ++++++++++++------------------- 1 file changed, 34 insertions(+), 57 deletions(-) diff --git a/launcher/ui/widgets/InfoFrame.cpp b/launcher/ui/widgets/InfoFrame.cpp index 243490140..b16bc097f 100644 --- a/launcher/ui/widgets/InfoFrame.cpp +++ b/launcher/ui/widgets/InfoFrame.cpp @@ -43,7 +43,7 @@ #include "ui/dialogs/CustomMessageBox.h" -void setupLinkTooTip(QLabel* label) +void setupLinkToolTip(QLabel* label) { QObject::connect(label, &QLabel::linkHovered, [label](const QString& link) { if (!link.isEmpty() && !link.startsWith("http")) @@ -60,11 +60,11 @@ InfoFrame::InfoFrame(QWidget* parent) : QFrame(parent), ui(new Ui::InfoFrame) ui->licenseLabel->setHidden(true); ui->issueTrackerLabel->setHidden(true); - setupLinkTooTip(ui->iconLabel); - setupLinkTooTip(ui->descriptionLabel); - setupLinkTooTip(ui->nameLabel); - setupLinkTooTip(ui->licenseLabel); - setupLinkTooTip(ui->issueTrackerLabel); + setupLinkToolTip(ui->iconLabel); + setupLinkToolTip(ui->descriptionLabel); + setupLinkToolTip(ui->nameLabel); + setupLinkToolTip(ui->licenseLabel); + setupLinkToolTip(ui->issueTrackerLabel); updateHiddenState(); } @@ -123,9 +123,9 @@ void InfoFrame::updateWithMod(Mod const& m) licenseText += "" + l.url + ""; } if (!l.description.isEmpty() && l.description != l.name) { - licenseText += " " + l.description; + licenseText += " " + l.description; } - } + } } if (!licenseText.isEmpty()) { setLicense(tr("License: %1").arg(licenseText)); @@ -137,7 +137,7 @@ void InfoFrame::updateWithMod(Mod const& m) if (!m.issueTracker().isEmpty()) { issueTracker += tr("Report issues to: "); issueTracker += "" + m.issueTracker() + ""; - } + } setIssueTracker(issueTracker); } @@ -147,7 +147,8 @@ void InfoFrame::updateWithResource(const Resource& resource) setImage(); } -QString InfoFrame::renderColorCodes(QString input) { +QString InfoFrame::renderColorCodes(QString input) +{ // We have to manually set the colors for use. // // A color is set using §x, with x = a hex number from 0 to f. @@ -158,16 +159,12 @@ QString InfoFrame::renderColorCodes(QString input) { // TODO: Wrap links inside tags // https://minecraft.fandom.com/wiki/Formatting_codes#Color_codes - const QMap color_codes_map = { - {'0', "#000000"}, {'1', "#0000AA"}, {'2', "#00AA00"}, {'3', "#00AAAA"}, {'4', "#AA0000"}, - {'5', "#AA00AA"}, {'6', "#FFAA00"}, {'7', "#AAAAAA"}, {'8', "#555555"}, {'9', "#5555FF"}, - {'a', "#55FF55"}, {'b', "#55FFFF"}, {'c', "#FF5555"}, {'d', "#FF55FF"}, {'e', "#FFFF55"}, - {'f', "#FFFFFF"} - }; + const QMap color_codes_map = { { '0', "#000000" }, { '1', "#0000AA" }, { '2', "#00AA00" }, { '3', "#00AAAA" }, + { '4', "#AA0000" }, { '5', "#AA00AA" }, { '6', "#FFAA00" }, { '7', "#AAAAAA" }, + { '8', "#555555" }, { '9', "#5555FF" }, { 'a', "#55FF55" }, { 'b', "#55FFFF" }, + { 'c', "#FF5555" }, { 'd', "#FF55FF" }, { 'e', "#FFFF55" }, { 'f', "#FFFFFF" } }; // https://minecraft.fandom.com/wiki/Formatting_codes#Formatting_codes - const QMap formatting_codes_map = { - {'l', "b"}, {'m', "s"}, {'n', "u"}, {'o', "i"} - }; + const QMap formatting_codes_map = { { 'l', "b" }, { 'm', "s" }, { 'n', "u" }, { 'o', "i" } }; QString html(""); QList tags{}; @@ -212,14 +209,14 @@ void InfoFrame::updateWithResourcePack(ResourcePack& resource_pack) { setName(renderColorCodes(resource_pack.name())); setDescription(renderColorCodes(resource_pack.description())); - setImage(resource_pack.image({64, 64})); + setImage(resource_pack.image({ 64, 64 })); } void InfoFrame::updateWithTexturePack(TexturePack& texture_pack) { setName(renderColorCodes(texture_pack.name())); setDescription(renderColorCodes(texture_pack.description())); - setImage(texture_pack.image({64, 64})); + setImage(texture_pack.image({ 64, 64 })); } void InfoFrame::clear() @@ -268,9 +265,8 @@ void InfoFrame::setDescription(QString text) QChar rem('\n'); QString finaltext; finaltext.reserve(intermediatetext.size()); - foreach(const QChar& c, intermediatetext) - { - if(c == rem && prev){ + foreach (const QChar& c, intermediatetext) { + if (c == rem && prev) { continue; } prev = c == rem; @@ -278,17 +274,14 @@ void InfoFrame::setDescription(QString text) } QString labeltext; labeltext.reserve(300); - if(finaltext.length() > 290) - { + if (finaltext.length() > 290) { ui->descriptionLabel->setOpenExternalLinks(false); ui->descriptionLabel->setTextFormat(Qt::TextFormat::RichText); m_description = text; // This allows injecting HTML here. labeltext.append("" + finaltext.left(287) + "..."); QObject::connect(ui->descriptionLabel, &QLabel::linkActivated, this, &InfoFrame::descriptionEllipsisHandler); - } - else - { + } else { ui->descriptionLabel->setTextFormat(Qt::TextFormat::AutoText); labeltext.append(finaltext); } @@ -297,14 +290,11 @@ void InfoFrame::setDescription(QString text) void InfoFrame::setLicense(QString text) { - if(text.isEmpty()) - { + if (text.isEmpty()) { ui->licenseLabel->setHidden(true); updateHiddenState(); return; - } - else - { + } else { ui->licenseLabel->setHidden(false); updateHiddenState(); } @@ -314,9 +304,8 @@ void InfoFrame::setLicense(QString text) QChar rem('\n'); QString finaltext; finaltext.reserve(intermediatetext.size()); - foreach(const QChar& c, intermediatetext) - { - if(c == rem && prev){ + foreach (const QChar& c, intermediatetext) { + if (c == rem && prev) { continue; } prev = c == rem; @@ -324,17 +313,14 @@ void InfoFrame::setLicense(QString text) } QString labeltext; labeltext.reserve(300); - if(finaltext.length() > 290) - { + if (finaltext.length() > 290) { ui->licenseLabel->setOpenExternalLinks(false); ui->licenseLabel->setTextFormat(Qt::TextFormat::RichText); m_description = text; // This allows injecting HTML here. labeltext.append("" + finaltext.left(287) + "..."); QObject::connect(ui->licenseLabel, &QLabel::linkActivated, this, &InfoFrame::licenseEllipsisHandler); - } - else - { + } else { ui->licenseLabel->setTextFormat(Qt::TextFormat::AutoText); labeltext.append(finaltext); } @@ -343,12 +329,9 @@ void InfoFrame::setLicense(QString text) void InfoFrame::setIssueTracker(QString text) { - if(text.isEmpty()) - { + if (text.isEmpty()) { ui->issueTrackerLabel->setHidden(true); - } - else - { + } else { ui->issueTrackerLabel->setText(text); ui->issueTrackerLabel->setHidden(false); } @@ -367,28 +350,22 @@ void InfoFrame::setImage(QPixmap img) void InfoFrame::descriptionEllipsisHandler(QString link) { - if(!m_current_box) - { + if (!m_current_box) { m_current_box = CustomMessageBox::selectable(this, "", m_description); connect(m_current_box, &QMessageBox::finished, this, &InfoFrame::boxClosed); m_current_box->show(); - } - else - { + } else { m_current_box->setText(m_description); } } void InfoFrame::licenseEllipsisHandler(QString link) { - if(!m_current_box) - { + if (!m_current_box) { m_current_box = CustomMessageBox::selectable(this, "", m_license); connect(m_current_box, &QMessageBox::finished, this, &InfoFrame::boxClosed); m_current_box->show(); - } - else - { + } else { m_current_box->setText(m_license); } } From 14692eed4052ae550d046278f559e66d3a77fb40 Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Mon, 3 Jul 2023 14:25:54 +0200 Subject: [PATCH 105/216] flake.lock: Update MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Flake lock file updates: • Updated input 'flake-parts': 'github:hercules-ci/flake-parts/006c75898cf814ef9497252b022e91c946ba8e17' (2023-05-08) → 'github:hercules-ci/flake-parts/267149c58a14d15f7f81b4d737308421de9d7152' (2023-07-01) • Updated input 'flake-parts/nixpkgs-lib': 'github:NixOS/nixpkgs/da45bf6ec7bbcc5d1e14d3795c025199f28e0de0?dir=lib' (2023-04-30) → 'github:NixOS/nixpkgs/4bc72cae107788bf3f24f30db2e2f685c9298dc9?dir=lib' (2023-06-29) • Updated input 'nixpkgs': 'github:nixos/nixpkgs/aeb75dba965e790de427b73315d5addf91a54955' (2023-05-25) → 'github:nixos/nixpkgs/cd99c2b3c9f160cd004318e0697f90bbd5960825' (2023-07-01) • Updated input 'pre-commit-hooks': 'github:cachix/pre-commit-hooks.nix/61e567d6497bc9556f391faebe5e410e6623217f' (2023-05-23) → 'github:cachix/pre-commit-hooks.nix/42587d3414d1747999a5f71e92a83cf6547b62da' (2023-07-03) • Updated input 'pre-commit-hooks/flake-utils': 'github:numtide/flake-utils/5aed5285a952e0b949eb3ba02c12fa4fcfef535f' (2022-11-02) → 'github:numtide/flake-utils/a1720a10a6cfe8234c0e93907ffe81be440f4cef' (2023-05-31) • Added input 'pre-commit-hooks/flake-utils/systems': 'github:nix-systems/default/da67096a3b9bf56a91d16901293e51ba5b49a27e' (2023-04-09) Signed-off-by: Sefa Eyeoglu --- flake.lock | 48 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 33 insertions(+), 15 deletions(-) diff --git a/flake.lock b/flake.lock index 875866438..91a67f087 100644 --- a/flake.lock +++ b/flake.lock @@ -21,11 +21,11 @@ "nixpkgs-lib": "nixpkgs-lib" }, "locked": { - "lastModified": 1683560683, - "narHash": "sha256-XAygPMN5Xnk/W2c1aW0jyEa6lfMDZWlQgiNtmHXytPc=", + "lastModified": 1688254665, + "narHash": "sha256-8FHEgBrr7gYNiS/NzCxIO3m4hvtLRW9YY1nYo1ivm3o=", "owner": "hercules-ci", "repo": "flake-parts", - "rev": "006c75898cf814ef9497252b022e91c946ba8e17", + "rev": "267149c58a14d15f7f81b4d737308421de9d7152", "type": "github" }, "original": { @@ -35,12 +35,15 @@ } }, "flake-utils": { + "inputs": { + "systems": "systems" + }, "locked": { - "lastModified": 1667395993, - "narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=", + "lastModified": 1685518550, + "narHash": "sha256-o2d0KcvaXzTrPRIo0kOLV0/QXHhDQ5DTi+OxcjO8xqY=", "owner": "numtide", "repo": "flake-utils", - "rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f", + "rev": "a1720a10a6cfe8234c0e93907ffe81be440f4cef", "type": "github" }, "original": { @@ -88,11 +91,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1685012353, - "narHash": "sha256-U3oOge4cHnav8OLGdRVhL45xoRj4Ppd+It6nPC9nNIU=", + "lastModified": 1688221086, + "narHash": "sha256-cdW6qUL71cNWhHCpMPOJjlw0wzSRP0pVlRn2vqX/VVg=", "owner": "nixos", "repo": "nixpkgs", - "rev": "aeb75dba965e790de427b73315d5addf91a54955", + "rev": "cd99c2b3c9f160cd004318e0697f90bbd5960825", "type": "github" }, "original": { @@ -105,11 +108,11 @@ "nixpkgs-lib": { "locked": { "dir": "lib", - "lastModified": 1682879489, - "narHash": "sha256-sASwo8gBt7JDnOOstnps90K1wxmVfyhsTPPNTGBPjjg=", + "lastModified": 1688049487, + "narHash": "sha256-100g4iaKC9MalDjUW9iN6Jl/OocTDtXdeAj7pEGIRh4=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "da45bf6ec7bbcc5d1e14d3795c025199f28e0de0", + "rev": "4bc72cae107788bf3f24f30db2e2f685c9298dc9", "type": "github" }, "original": { @@ -135,11 +138,11 @@ ] }, "locked": { - "lastModified": 1684842236, - "narHash": "sha256-rYWsIXHvNhVQ15RQlBUv67W3YnM+Pd+DuXGMvCBq2IE=", + "lastModified": 1688386108, + "narHash": "sha256-Vffto9QaVonzYAcPlAzd0soqWYpPpKk60dfNLSIXcFA=", "owner": "cachix", "repo": "pre-commit-hooks.nix", - "rev": "61e567d6497bc9556f391faebe5e410e6623217f", + "rev": "42587d3414d1747999a5f71e92a83cf6547b62da", "type": "github" }, "original": { @@ -156,6 +159,21 @@ "nixpkgs": "nixpkgs", "pre-commit-hooks": "pre-commit-hooks" } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } } }, "root": "root", From fa7cfc77d8b723a53577734a0a3c76df7d9dc6d7 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Mon, 3 Jul 2023 16:08:20 +0300 Subject: [PATCH 106/216] fixed template Signed-off-by: Trial97 --- launcher/modplatform/flame/FlamePackExportTask.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/modplatform/flame/FlamePackExportTask.cpp b/launcher/modplatform/flame/FlamePackExportTask.cpp index 1b75908ad..b8edf7df8 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.cpp +++ b/launcher/modplatform/flame/FlamePackExportTask.cpp @@ -36,7 +36,7 @@ #include "modplatform/helpers/HashUtils.h" #include "tasks/Task.h" -const QString FlamePackExportTask::TEMPLATE = "
  • {name}{authors}
  • \n"; +const QString FlamePackExportTask::TEMPLATE = "
  • {name}{authors}
  • \n"; const QStringList FlamePackExportTask::FILE_EXTENSIONS({ "jar", "zip" }); FlamePackExportTask::FlamePackExportTask(const QString& name, From 96c118779daff9ea099710957a62c83115c149ef Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Mon, 3 Jul 2023 17:42:57 -0700 Subject: [PATCH 107/216] build: enable address sanitiser in debug builds Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- CMakeLists.txt | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 70a553190..dd84daf3d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -85,6 +85,28 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DTOML_ENABLE_FLOAT16=0") # set CXXFLAGS for build targets set(CMAKE_CXX_FLAGS_RELEASE "-O2 -D_FORTIFY_SOURCE=2 ${CMAKE_CXX_FLAGS_RELEASE}") +option(DEBUG_ADDRESS_SANITIZER "Enable Address Sanitizer in Debug builds" on) + +# If this is a Debug build turn on address sanitiser +if (CMAKE_BUILD_TYPE STREQUAL "Debug" AND DEBUG_ADDRESS_SANITIZER) + message(STATUS "Address Sanitizer enabeled for Debug builds, Turn it off with -DDEBUG_ADDRESS_SANITIZER=off") + if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") + # AppleClang and Clang + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address") + elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") + # GCC + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address") + elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel") + # Intell compiler ? why? + # no address sanitiser here though + message(STATUS "Address Sanitizer not available on Intell compilers") + elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /fsanitize=address") + else() + message(STATUS "Address Sanitizer not available on unknown compiler ${CMAKE_CXX_COMPILER_ID}") + endif() +endif() + option(ENABLE_LTO "Enable Link Time Optimization" off) if(ENABLE_LTO) From 50eff80ca16a351ec80f75f0f6cf5f0f87207fb1 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Mon, 3 Jul 2023 18:07:59 -0700 Subject: [PATCH 108/216] build: optimize address-sanitizer Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index dd84daf3d..11e4c6286 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -92,16 +92,16 @@ if (CMAKE_BUILD_TYPE STREQUAL "Debug" AND DEBUG_ADDRESS_SANITIZER) message(STATUS "Address Sanitizer enabeled for Debug builds, Turn it off with -DDEBUG_ADDRESS_SANITIZER=off") if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") # AppleClang and Clang - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -faddress-sanitizer -O1 -fno-omit-frame-pointer") elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") # GCC - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -O1 -fno-omit-frame-pointer") elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel") # Intell compiler ? why? # no address sanitiser here though message(STATUS "Address Sanitizer not available on Intell compilers") elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /fsanitize=address") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /fsanitize=address /O1 /Oy-") else() message(STATUS "Address Sanitizer not available on unknown compiler ${CMAKE_CXX_COMPILER_ID}") endif() From 03a1d68b742b8ec74b472e5fb32d3f9c34594b5e Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Mon, 3 Jul 2023 18:18:48 -0700 Subject: [PATCH 109/216] fix: memory leaks in filesystem test Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- tests/FileSystem_test.cpp | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/tests/FileSystem_test.cpp b/tests/FileSystem_test.cpp index ec1f0bcff..a41345c2e 100644 --- a/tests/FileSystem_test.cpp +++ b/tests/FileSystem_test.cpp @@ -42,6 +42,10 @@ class LinkTask : public Task { m_lnk->debug(true); } + ~LinkTask() { + delete m_lnk; + } + void matcher(const IPathMatcher *filter) { m_lnk->matcher(filter); @@ -219,7 +223,8 @@ slots: qDebug() << tempDir.path(); qDebug() << target_dir.path(); FS::copy c(folder, target_dir.path()); - c.matcher(new RegexpMatcher("[.]?mcmeta")); + RegexpMatcher re("[.]?mcmeta"); + c.matcher(&re); c(); for(auto entry: target_dir.entryList()) @@ -253,7 +258,8 @@ slots: qDebug() << tempDir.path(); qDebug() << target_dir.path(); FS::copy c(folder, target_dir.path()); - c.matcher(new RegexpMatcher("[.]?mcmeta")); + RegexpMatcher re("[.]?mcmeta"); + c.matcher(&re); c.whitelist(true); c(); @@ -460,7 +466,8 @@ slots: qDebug() << target_dir.path(); LinkTask lnk_tsk(folder, target_dir.path()); - lnk_tsk.matcher(new RegexpMatcher("[.]?mcmeta")); + RegexpMatcher re("[.]?mcmeta"); + lnk_tsk.matcher(&re); lnk_tsk.linkRecursively(true); QObject::connect(&lnk_tsk, &Task::finished, [&]{ QVERIFY2(lnk_tsk.wasSuccessful(), "Task finished but was not successful when it should have been."); @@ -511,7 +518,8 @@ slots: qDebug() << target_dir.path(); LinkTask lnk_tsk(folder, target_dir.path()); - lnk_tsk.matcher(new RegexpMatcher("[.]?mcmeta")); + RegexpMatcher re("[.]?mcmeta"); + lnk_tsk.matcher(&re); lnk_tsk.linkRecursively(true); lnk_tsk.whitelist(true); QObject::connect(&lnk_tsk, &Task::finished, [&]{ From c5705705d5b40e8157a88612c8a7e83f32f6745b Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Mon, 3 Jul 2023 18:35:42 -0700 Subject: [PATCH 110/216] fix: memory leaks in ResourceModel Test Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- tests/ResourceModel_test.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tests/ResourceModel_test.cpp b/tests/ResourceModel_test.cpp index c0d9cd95d..30353d3f9 100644 --- a/tests/ResourceModel_test.cpp +++ b/tests/ResourceModel_test.cpp @@ -38,6 +38,7 @@ class DummyResourceModel : public ResourceModel { public: DummyResourceModel() : ResourceModel(new DummyResourceAPI) {} + ~DummyResourceModel() {} [[nodiscard]] auto metaEntryBase() const -> QString override { return ""; }; @@ -58,7 +59,10 @@ class DummyResourceModel : public ResourceModel { class ResourceModelTest : public QObject { Q_OBJECT private slots: - void test_abstract_item_model() { [[maybe_unused]] auto tester = new QAbstractItemModelTester(new DummyResourceModel); } + void test_abstract_item_model() { + auto dummy = DummyResourceModel(); + auto tester = QAbstractItemModelTester(&dummy); + } void test_search() { @@ -78,6 +82,8 @@ class ResourceModelTest : public QObject { QVERIFY(processed_pack->addonId.toString() == Json::requireString(processed_response, "project_id")); QVERIFY(processed_pack->description == Json::requireString(processed_response, "description")); QVERIFY(processed_pack->authors.first().name == Json::requireString(processed_response, "author")); + + delete model; } }; From 3c96d5e0d568408e0505841af39aa2d539ebaf36 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Mon, 3 Jul 2023 20:04:24 -0700 Subject: [PATCH 111/216] fix: memory leaks in tests Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- CMakeLists.txt | 15 ++++++++++++--- tests/Task_test.cpp | 1 + tests/Version_test.cpp | 25 +++++++++++++++---------- 3 files changed, 28 insertions(+), 13 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 11e4c6286..bb9906691 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -91,16 +91,25 @@ option(DEBUG_ADDRESS_SANITIZER "Enable Address Sanitizer in Debug builds" on) if (CMAKE_BUILD_TYPE STREQUAL "Debug" AND DEBUG_ADDRESS_SANITIZER) message(STATUS "Address Sanitizer enabeled for Debug builds, Turn it off with -DDEBUG_ADDRESS_SANITIZER=off") if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") - # AppleClang and Clang - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -faddress-sanitizer -O1 -fno-omit-frame-pointer") + if (CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC") + # using clang with clang-cl front end + message(STATUS "Address Sanitizer available on Clang MSVC frontend") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /fsanitize=address /O1 /Oy-") + else() + # AppleClang and Clang + message(STATUS "Address Sanitizer available on Clang") + set(cmake_cxx_flags "${cmake_cxx_flags} -fsanitize=address -O1 -fno-omit-frame-pointer") + endif() elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") # GCC - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -O1 -fno-omit-frame-pointer") + message(STATUS "Address Sanitizer available on GCC") + set(cmake_cxx_flags "${cmake_cxx_flags} -fsanitize=address -O1 -fno-omit-frame-pointer") elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel") # Intell compiler ? why? # no address sanitiser here though message(STATUS "Address Sanitizer not available on Intell compilers") elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") + message(STATUS "Address Sanitizer available on MSVC") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /fsanitize=address /O1 /Oy-") else() message(STATUS "Address Sanitizer not available on unknown compiler ${CMAKE_CXX_COMPILER_ID}") diff --git a/tests/Task_test.cpp b/tests/Task_test.cpp index dabe5da26..a57102d6d 100644 --- a/tests/Task_test.cpp +++ b/tests/Task_test.cpp @@ -80,6 +80,7 @@ class BigConcurrentTaskThread : public QThread { QCoreApplication::processEvents(); emit finished(); + delete[] sub_tasks; } public: diff --git a/tests/Version_test.cpp b/tests/Version_test.cpp index afb4c6102..0f8c1652d 100644 --- a/tests/Version_test.cpp +++ b/tests/Version_test.cpp @@ -20,6 +20,8 @@ class VersionTest : public QObject { Q_OBJECT + QStringList m_flex_test_names = {}; + void addDataColumns() { QTest::addColumn("first"); @@ -101,8 +103,9 @@ class VersionTest : public QObject { QString first{split_line.first().simplified()}; QString second{split_line.last().simplified()}; - auto new_test_name = test_name_template.arg(QString::number(test_number), "lessThan").toLatin1().data(); - QTest::newRow(new_test_name) << first << second << true << false; + auto new_test_name = test_name_template.arg(QString::number(test_number), "lessThan"); + m_flex_test_names.append(new_test_name); + QTest::newRow(m_flex_test_names.last().toLatin1().data()) << first << second << true << false; continue; } @@ -112,8 +115,9 @@ class VersionTest : public QObject { QString first{split_line.first().simplified()}; QString second{split_line.last().simplified()}; - auto new_test_name = test_name_template.arg(QString::number(test_number), "equals").toLatin1().data(); - QTest::newRow(new_test_name) << first << second << false << true; + auto new_test_name = test_name_template.arg(QString::number(test_number), "equals"); + m_flex_test_names.append(new_test_name); + QTest::newRow(m_flex_test_names.last().toLatin1().data()) << first << second << false << true; continue; } @@ -123,8 +127,9 @@ class VersionTest : public QObject { QString first{split_line.first().simplified()}; QString second{split_line.last().simplified()}; - auto new_test_name = test_name_template.arg(QString::number(test_number), "greaterThan").toLatin1().data(); - QTest::newRow(new_test_name) << first << second << false << false; + auto new_test_name = test_name_template.arg(QString::number(test_number), "greaterThan"); + m_flex_test_names.append(new_test_name); + QTest::newRow(m_flex_test_names.last().toLatin1().data()) << first << second << false << false; continue; } @@ -140,10 +145,10 @@ class VersionTest : public QObject { void test_flexVerTestVector() { - QFETCH(QString, first); - QFETCH(QString, second); - QFETCH(bool, lessThan); - QFETCH(bool, equal); + QString first = *static_cast(QTest ::qData("first", ::qMetaTypeId::type>())); + QString second = *static_cast(QTest ::qData("second", ::qMetaTypeId::type>())); + bool lessThan = *static_cast(QTest ::qData("lessThan", ::qMetaTypeId::type>())); + bool equal = *static_cast(QTest ::qData("equal", ::qMetaTypeId::type>())); const auto v1 = Version(first); const auto v2 = Version(second); From 908ac813e0f96126a643851e99379956faa08cda Mon Sep 17 00:00:00 2001 From: Trial97 Date: Tue, 4 Jul 2023 15:16:54 +0300 Subject: [PATCH 112/216] escaped modlist inner html Signed-off-by: Trial97 --- launcher/modplatform/flame/FlamePackExportTask.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/launcher/modplatform/flame/FlamePackExportTask.cpp b/launcher/modplatform/flame/FlamePackExportTask.cpp index b8edf7df8..ac0da2142 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.cpp +++ b/launcher/modplatform/flame/FlamePackExportTask.cpp @@ -362,9 +362,9 @@ void FlamePackExportTask::buildZip() for (auto mod : resolvedFiles) { if (mod.isMod) { content += QString(TEMPLATE) - .replace("{name}", mod.name) - .replace("{url}", ModPlatform::getMetaURL(ModPlatform::ResourceProvider::FLAME, mod.addonId)) - .replace("{authors}", !mod.authors.isEmpty() ? QString(" (by %1)").arg(mod.authors) : ""); + .replace("{name}", mod.name.toHtmlEscaped()) + .replace("{url}", ModPlatform::getMetaURL(ModPlatform::ResourceProvider::FLAME, mod.addonId).toHtmlEscaped()) + .replace("{authors}", !mod.authors.isEmpty() ? QString(" (by %1)").arg(mod.authors).toHtmlEscaped() : ""); } } content = "
      " + content + "
    "; From 1fbc17d275b99d194906302f98412f78fbb77538 Mon Sep 17 00:00:00 2001 From: PandaNinjas Date: Tue, 4 Jul 2023 16:38:04 -0400 Subject: [PATCH 113/216] Remove break and add fallthrough comment in WorldListPage.cpp Signed-off-by: PandaNinjas --- launcher/ui/pages/instance/WorldListPage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/ui/pages/instance/WorldListPage.cpp b/launcher/ui/pages/instance/WorldListPage.cpp index b5dc5a17c..b2200b1a7 100644 --- a/launcher/ui/pages/instance/WorldListPage.cpp +++ b/launcher/ui/pages/instance/WorldListPage.cpp @@ -338,8 +338,8 @@ void WorldListPage::mceditState(LoggedProcess::State state) case LoggedProcess::Aborted: { failed = true; - break; } + /* fallthrough */ case LoggedProcess::Running: case LoggedProcess::Finished: { From 34cf28712c254ba378bdbf728471d0dfbb4ab58f Mon Sep 17 00:00:00 2001 From: PandaNinjas Date: Tue, 4 Jul 2023 16:39:24 -0400 Subject: [PATCH 114/216] Replace break with return true; Signed-off-by: PandaNinjas --- launcher/ui/setupwizard/JavaWizardPage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/ui/setupwizard/JavaWizardPage.cpp b/launcher/ui/setupwizard/JavaWizardPage.cpp index e88335355..2b70c47c3 100644 --- a/launcher/ui/setupwizard/JavaWizardPage.cpp +++ b/launcher/ui/setupwizard/JavaWizardPage.cpp @@ -69,7 +69,7 @@ bool JavaWizardPage::validatePage() case JavaSettingsWidget::ValidationStatus::AllOK: { settings->set("JavaPath", m_java_widget->javaPath()); - break; + return true; } case JavaSettingsWidget::ValidationStatus::JavaBad: { From 817ecf822583caf3a510f177d40fe8c6b3218165 Mon Sep 17 00:00:00 2001 From: PandaNinjas Date: Tue, 4 Jul 2023 17:19:08 -0400 Subject: [PATCH 115/216] Fix VersionProxyModel.cpp Signed-off-by: PandaNinjas --- launcher/VersionProxyModel.cpp | 51 +++++++++------------------------- 1 file changed, 13 insertions(+), 38 deletions(-) diff --git a/launcher/VersionProxyModel.cpp b/launcher/VersionProxyModel.cpp index 03130b239..91f94f412 100644 --- a/launcher/VersionProxyModel.cpp +++ b/launcher/VersionProxyModel.cpp @@ -191,36 +191,21 @@ QVariant VersionProxyModel::data(const QModelIndex &index, int role) const return QVariant(); } } - case Qt::ToolTipRole: { + case Qt::ToolTipRole: + { if (column == Name && hasRecommended) { - auto recommendedValue = sourceModel()->data(parentIndex, BaseVersionList::RecommendedRole); - if(recommendedValue.toBool()) { + auto value = sourceModel()->data(parentIndex, BaseVersionList::RecommendedRole); + if (value.toBool()) { return tr("Recommended"); - } - else if(hasLatest) { - auto latestValue = sourceModel()->data(parentIndex, BaseVersionList::LatestRole); - if(latestValue.toBool()) - { - auto value = sourceModel()->data(parentIndex, BaseVersionList::RecommendedRole); - if(value.toBool()) - { - return tr("Recommended"); - } - else if(hasLatest) - { - auto value = sourceModel()->data(parentIndex, BaseVersionList::LatestRole); - if(value.toBool()) - { - return tr("Latest"); - } - } + } else if(hasLatest) { + auto value = sourceModel()->data(parentIndex, BaseVersionList::LatestRole); + if(value.toBool()) { + return tr("Latest"); } } - else if(index.row() == 0) { - return tr("Latest"); - } + } else { + return sourceModel()->data(parentIndex, BaseVersionList::VersionIdRole); } - return sourceModel()->data(parentIndex, BaseVersionList::VersionIdRole); } case Qt::DecorationRole: { @@ -255,20 +240,10 @@ QVariant VersionProxyModel::data(const QModelIndex &index, int role) const return pixmap; } } - else if(index.row() == 0) { - return APPLICATION->getThemedIcon("bug"); + default: + { + return QVariant(); } - QPixmap pixmap; - QPixmapCache::find("placeholder", &pixmap); - if(!pixmap) { - QPixmap px(16,16); - px.fill(Qt::transparent); - QPixmapCache::insert("placeholder", px); - return px; - } - return pixmap; - } else { - return QVariant(); } } default: From 24b9ed106f3c217271468de565ff6706fd832ea5 Mon Sep 17 00:00:00 2001 From: seth Date: Tue, 4 Jul 2023 18:49:17 -0400 Subject: [PATCH 116/216] feat(actions): add update-flake-lock Signed-off-by: seth --- .github/workflows/update-flake.yml | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 .github/workflows/update-flake.yml diff --git a/.github/workflows/update-flake.yml b/.github/workflows/update-flake.yml new file mode 100644 index 000000000..c790c9c69 --- /dev/null +++ b/.github/workflows/update-flake.yml @@ -0,0 +1,26 @@ +name: Update Flake Lockfile + +on: + schedule: + # run weekly on sunday + - cron: "0 0 * * 0" + workflow_dispatch: + +permissions: + pull-requests: write + +jobs: + update-flake: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - uses: cachix/install-nix-action@v22 + + - uses: DeterminateSystems/update-flake-lock@v19 + with: + commit-msg: "chore(nix): update lockfile" + pr-title: "chore(nix): update lockfile" + pr-labels: | + Linux + simple change From 183ed7b90bbe015b09f545087387e1345ccaf927 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Tue, 4 Jul 2023 19:43:22 -0700 Subject: [PATCH 117/216] chore: cleanup compiler type branches Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- CMakeLists.txt | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index bb9906691..0abedab92 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -98,21 +98,17 @@ if (CMAKE_BUILD_TYPE STREQUAL "Debug" AND DEBUG_ADDRESS_SANITIZER) else() # AppleClang and Clang message(STATUS "Address Sanitizer available on Clang") - set(cmake_cxx_flags "${cmake_cxx_flags} -fsanitize=address -O1 -fno-omit-frame-pointer") + set(CMAKE_CXX_FLAGS "${cmake_cxx_flags} -fsanitize=address -O1 -fno-omit-frame-pointer") endif() elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") # GCC message(STATUS "Address Sanitizer available on GCC") - set(cmake_cxx_flags "${cmake_cxx_flags} -fsanitize=address -O1 -fno-omit-frame-pointer") - elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel") - # Intell compiler ? why? - # no address sanitiser here though - message(STATUS "Address Sanitizer not available on Intell compilers") + set(CMAKE_CXX_FLAGS "${cmake_cxx_flags} -fsanitize=address -O1 -fno-omit-frame-pointer") elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") message(STATUS "Address Sanitizer available on MSVC") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /fsanitize=address /O1 /Oy-") else() - message(STATUS "Address Sanitizer not available on unknown compiler ${CMAKE_CXX_COMPILER_ID}") + message(STATUS "Address Sanitizer not available on compiler ${CMAKE_CXX_COMPILER_ID}") endif() endif() From a028894855f29c49d4bf8b0f745c66e1ea7dd4c6 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Tue, 4 Jul 2023 23:43:39 -0700 Subject: [PATCH 118/216] Apply suggestions from code review Co-authored-by: seth Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- CMakeLists.txt | 6 +++--- tests/Version_test.cpp | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0abedab92..bc988b4ff 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -89,7 +89,7 @@ option(DEBUG_ADDRESS_SANITIZER "Enable Address Sanitizer in Debug builds" on) # If this is a Debug build turn on address sanitiser if (CMAKE_BUILD_TYPE STREQUAL "Debug" AND DEBUG_ADDRESS_SANITIZER) - message(STATUS "Address Sanitizer enabeled for Debug builds, Turn it off with -DDEBUG_ADDRESS_SANITIZER=off") + message(STATUS "Address Sanitizer enabled for Debug builds, Turn it off with -DDEBUG_ADDRESS_SANITIZER=off") if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") if (CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC") # using clang with clang-cl front end @@ -98,12 +98,12 @@ if (CMAKE_BUILD_TYPE STREQUAL "Debug" AND DEBUG_ADDRESS_SANITIZER) else() # AppleClang and Clang message(STATUS "Address Sanitizer available on Clang") - set(CMAKE_CXX_FLAGS "${cmake_cxx_flags} -fsanitize=address -O1 -fno-omit-frame-pointer") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}} -fsanitize=address -O1 -fno-omit-frame-pointer") endif() elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") # GCC message(STATUS "Address Sanitizer available on GCC") - set(CMAKE_CXX_FLAGS "${cmake_cxx_flags} -fsanitize=address -O1 -fno-omit-frame-pointer") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -O1 -fno-omit-frame-pointer") elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") message(STATUS "Address Sanitizer available on MSVC") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /fsanitize=address /O1 /Oy-") diff --git a/tests/Version_test.cpp b/tests/Version_test.cpp index 0f8c1652d..f5488cbce 100644 --- a/tests/Version_test.cpp +++ b/tests/Version_test.cpp @@ -145,10 +145,10 @@ class VersionTest : public QObject { void test_flexVerTestVector() { - QString first = *static_cast(QTest ::qData("first", ::qMetaTypeId::type>())); - QString second = *static_cast(QTest ::qData("second", ::qMetaTypeId::type>())); - bool lessThan = *static_cast(QTest ::qData("lessThan", ::qMetaTypeId::type>())); - bool equal = *static_cast(QTest ::qData("equal", ::qMetaTypeId::type>())); + QFETCH(QString, first); + QFETCH(QString, second); + QFETCH(bool, lessThan); + QFETCH(bool, equal); const auto v1 = Version(first); const auto v2 = Version(second); From 5fe9a7a6c352735801fbbea69f8d2a6cd3b884f4 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Wed, 5 Jul 2023 03:02:20 -0700 Subject: [PATCH 119/216] fix: extra } in CXX args Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index bc988b4ff..4f8befcc3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -98,7 +98,7 @@ if (CMAKE_BUILD_TYPE STREQUAL "Debug" AND DEBUG_ADDRESS_SANITIZER) else() # AppleClang and Clang message(STATUS "Address Sanitizer available on Clang") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}} -fsanitize=address -O1 -fno-omit-frame-pointer") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -O1 -fno-omit-frame-pointer") endif() elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") # GCC From 4dbcedd03f6d90a9557cd401c2236f9cda60cf9f Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Wed, 5 Jul 2023 11:51:37 -0700 Subject: [PATCH 120/216] fix: Task test memory leaks again Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- CMakeLists.txt | 5 ++ tests/Task_test.cpp | 138 +++++++++++++++++++++----------------------- 2 files changed, 72 insertions(+), 71 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4f8befcc3..afa67546d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -95,18 +95,23 @@ if (CMAKE_BUILD_TYPE STREQUAL "Debug" AND DEBUG_ADDRESS_SANITIZER) # using clang with clang-cl front end message(STATUS "Address Sanitizer available on Clang MSVC frontend") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /fsanitize=address /O1 /Oy-") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /fsanitize=address /O1 /Oy-") else() # AppleClang and Clang message(STATUS "Address Sanitizer available on Clang") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -O1 -fno-omit-frame-pointer") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -O1 -fno-omit-frame-pointer") endif() elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") # GCC message(STATUS "Address Sanitizer available on GCC") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -O1 -fno-omit-frame-pointer") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -O1 -fno-omit-frame-pointer") + link_libraries("asan") elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") message(STATUS "Address Sanitizer available on MSVC") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /fsanitize=address /O1 /Oy-") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /fsanitize=address /O1 /Oy-") else() message(STATUS "Address Sanitizer not available on compiler ${CMAKE_CXX_COMPILER_ID}") endif() diff --git a/tests/Task_test.cpp b/tests/Task_test.cpp index a57102d6d..b6bd7edf2 100644 --- a/tests/Task_test.cpp +++ b/tests/Task_test.cpp @@ -1,6 +1,6 @@ #include -#include #include +#include #include #include @@ -19,10 +19,7 @@ class BasicTask : public Task { BasicTask(bool show_debug_log = true) : Task(nullptr, show_debug_log) {} private: - void executeTask() override - { - emitSucceeded(); - }; + void executeTask() override { emitSucceeded(); }; }; /* Does nothing. Only used for testing. */ @@ -34,7 +31,7 @@ class BasicTask_MultiStep : public Task { private: auto isMultiStep() const -> bool override { return true; } - void executeTask() override {}; + void executeTask() override{}; }; class BigConcurrentTask : public ConcurrentTask { @@ -44,7 +41,7 @@ class BigConcurrentTask : public ConcurrentTask { { // This is here only to help fill the stack a bit more quickly (if there's an issue, of course :^)) // Each tasks thus adds 1024 * 4 bytes to the stack, at the very least. - [[maybe_unused]] volatile std::array some_data_on_the_stack {}; + [[maybe_unused]] volatile std::array some_data_on_the_stack{}; ConcurrentTask::startNext(); } @@ -59,28 +56,28 @@ class BigConcurrentTaskThread : public QThread { { QTimer deadline; deadline.setInterval(10000); - connect(&deadline, &QTimer::timeout, this, [this]{ passed_the_deadline = true; }); + connect(&deadline, &QTimer::timeout, this, [this] { passed_the_deadline = true; }); deadline.start(); // NOTE: Arbitrary value that manages to trigger a problem when there is one. // Considering each tasks, in a problematic state, adds 1024 * 4 bytes to the stack, // this number is enough to fill up 16 MiB of stack, more than enough to cause a problem. static const unsigned s_num_tasks = 1 << 12; - auto sub_tasks = new BasicTask::Ptr[s_num_tasks]; + { + auto sub_tasks = std::array(); - for (unsigned i = 0; i < s_num_tasks; i++) { - auto sub_task = makeShared(false); - sub_tasks[i] = sub_task; - big_task.addTask(sub_task); - } + for (unsigned i = 0; i < s_num_tasks; i++) { + auto sub_task = makeShared(false); + sub_tasks[i] = sub_task; + big_task.addTask(sub_task); + } - big_task.run(); - - while (!big_task.isFinished() && !passed_the_deadline) - QCoreApplication::processEvents(); + big_task.run(); + while (!big_task.isFinished() && !passed_the_deadline) + QCoreApplication::processEvents(); + } // drop before emit emit finished(); - delete[] sub_tasks; } public: @@ -94,9 +91,10 @@ class TaskTest : public QObject { Q_OBJECT private slots: - void test_SetStatus_NoMultiStep(){ + void test_SetStatus_NoMultiStep() + { BasicTask t; - QString status {"test status"}; + QString status{ "test status" }; t.setStatus(status); @@ -104,9 +102,10 @@ class TaskTest : public QObject { QCOMPARE(t.getStepProgress().isEmpty(), TaskStepProgressList{}.isEmpty()); } - void test_SetStatus_MultiStep(){ + void test_SetStatus_MultiStep() + { BasicTask_MultiStep t; - QString status {"test status"}; + QString status{ "test status" }; t.setStatus(status); @@ -116,7 +115,8 @@ class TaskTest : public QObject { QCOMPARE(t.getStepProgress().isEmpty(), TaskStepProgressList{}.isEmpty()); } - void test_SetProgress(){ + void test_SetProgress() + { BasicTask t; int current = 42; int total = 207; @@ -127,17 +127,18 @@ class TaskTest : public QObject { QCOMPARE(t.getTotalProgress(), total); } - void test_basicRun(){ + void test_basicRun() + { BasicTask t; - QObject::connect(&t, &Task::finished, [&]{ QVERIFY2(t.wasSuccessful(), "Task finished but was not successful when it should have been."); }); + QObject::connect(&t, &Task::finished, + [&] { QVERIFY2(t.wasSuccessful(), "Task finished but was not successful when it should have been."); }); t.start(); - QVERIFY2(QTest::qWaitFor([&]() { - return t.isFinished(); - }, 1000), "Task didn't finish as it should."); + QVERIFY2(QTest::qWaitFor([&]() { return t.isFinished(); }, 1000), "Task didn't finish as it should."); } - void test_basicConcurrentRun(){ + void test_basicConcurrentRun() + { auto t1 = makeShared(); auto t2 = makeShared(); auto t3 = makeShared(); @@ -148,21 +149,20 @@ class TaskTest : public QObject { t.addTask(t2); t.addTask(t3); - QObject::connect(&t, &Task::finished, [&]{ - QVERIFY2(t.wasSuccessful(), "Task finished but was not successful when it should have been."); - QVERIFY(t1->wasSuccessful()); - QVERIFY(t2->wasSuccessful()); - QVERIFY(t3->wasSuccessful()); + QObject::connect(&t, &Task::finished, [&t, &t1, &t2, &t3] { + QVERIFY2(t.wasSuccessful(), "Task finished but was not successful when it should have been."); + QVERIFY(t1->wasSuccessful()); + QVERIFY(t2->wasSuccessful()); + QVERIFY(t3->wasSuccessful()); }); t.start(); - QVERIFY2(QTest::qWaitFor([&]() { - return t.isFinished(); - }, 1000), "Task didn't finish as it should."); + QVERIFY2(QTest::qWaitFor([&]() { return t.isFinished(); }, 1000), "Task didn't finish as it should."); } // Tests if starting new tasks after the 6 initial ones is working - void test_moreConcurrentRun(){ + void test_moreConcurrentRun() + { auto t1 = makeShared(); auto t2 = makeShared(); auto t3 = makeShared(); @@ -185,26 +185,25 @@ class TaskTest : public QObject { t.addTask(t8); t.addTask(t9); - QObject::connect(&t, &Task::finished, [&]{ - QVERIFY2(t.wasSuccessful(), "Task finished but was not successful when it should have been."); - QVERIFY(t1->wasSuccessful()); - QVERIFY(t2->wasSuccessful()); - QVERIFY(t3->wasSuccessful()); - QVERIFY(t4->wasSuccessful()); - QVERIFY(t5->wasSuccessful()); - QVERIFY(t6->wasSuccessful()); - QVERIFY(t7->wasSuccessful()); - QVERIFY(t8->wasSuccessful()); - QVERIFY(t9->wasSuccessful()); + QObject::connect(&t, &Task::finished, [&t, &t1, &t2, &t3, &t4, &t5, &t6, &t7, &t8, &t9] { + QVERIFY2(t.wasSuccessful(), "Task finished but was not successful when it should have been."); + QVERIFY(t1->wasSuccessful()); + QVERIFY(t2->wasSuccessful()); + QVERIFY(t3->wasSuccessful()); + QVERIFY(t4->wasSuccessful()); + QVERIFY(t5->wasSuccessful()); + QVERIFY(t6->wasSuccessful()); + QVERIFY(t7->wasSuccessful()); + QVERIFY(t8->wasSuccessful()); + QVERIFY(t9->wasSuccessful()); }); t.start(); - QVERIFY2(QTest::qWaitFor([&]() { - return t.isFinished(); - }, 1000), "Task didn't finish as it should."); + QVERIFY2(QTest::qWaitFor([&]() { return t.isFinished(); }, 1000), "Task didn't finish as it should."); } - void test_basicSequentialRun(){ + void test_basicSequentialRun() + { auto t1 = makeShared(); auto t2 = makeShared(); auto t3 = makeShared(); @@ -215,20 +214,19 @@ class TaskTest : public QObject { t.addTask(t2); t.addTask(t3); - QObject::connect(&t, &Task::finished, [&]{ - QVERIFY2(t.wasSuccessful(), "Task finished but was not successful when it should have been."); - QVERIFY(t1->wasSuccessful()); - QVERIFY(t2->wasSuccessful()); - QVERIFY(t3->wasSuccessful()); + QObject::connect(&t, &Task::finished, [&t, &t1, &t2, &t3] { + QVERIFY2(t.wasSuccessful(), "Task finished but was not successful when it should have been."); + QVERIFY(t1->wasSuccessful()); + QVERIFY(t2->wasSuccessful()); + QVERIFY(t3->wasSuccessful()); }); t.start(); - QVERIFY2(QTest::qWaitFor([&]() { - return t.isFinished(); - }, 1000), "Task didn't finish as it should."); + QVERIFY2(QTest::qWaitFor([&]() { return t.isFinished(); }, 1000), "Task didn't finish as it should."); } - void test_basicMultipleOptionsRun(){ + void test_basicMultipleOptionsRun() + { auto t1 = makeShared(); auto t2 = makeShared(); auto t3 = makeShared(); @@ -239,17 +237,15 @@ class TaskTest : public QObject { t.addTask(t2); t.addTask(t3); - QObject::connect(&t, &Task::finished, [&]{ - QVERIFY2(t.wasSuccessful(), "Task finished but was not successful when it should have been."); - QVERIFY(t1->wasSuccessful()); - QVERIFY(!t2->wasSuccessful()); - QVERIFY(!t3->wasSuccessful()); + QObject::connect(&t, &Task::finished, [&t, &t1, &t2, &t3] { + QVERIFY2(t.wasSuccessful(), "Task finished but was not successful when it should have been."); + QVERIFY(t1->wasSuccessful()); + QVERIFY(!t2->wasSuccessful()); + QVERIFY(!t3->wasSuccessful()); }); t.start(); - QVERIFY2(QTest::qWaitFor([&]() { - return t.isFinished(); - }, 1000), "Task didn't finish as it should."); + QVERIFY2(QTest::qWaitFor([&]() { return t.isFinished(); }, 1000), "Task didn't finish as it should."); } void test_stackOverflowInConcurrentTask() From 965ee5687a475aa0a7e3756f0e5a7e1db26c6a16 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Wed, 5 Jul 2023 20:05:18 -0700 Subject: [PATCH 121/216] fix(test): task test memory leak *again* - put Big thread on the stack so stack will clean it up. Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- tests/Task_test.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/tests/Task_test.cpp b/tests/Task_test.cpp index b6bd7edf2..ef7042a59 100644 --- a/tests/Task_test.cpp +++ b/tests/Task_test.cpp @@ -252,16 +252,15 @@ class TaskTest : public QObject { { QEventLoop loop; - auto thread = new BigConcurrentTaskThread; + BigConcurrentTaskThread thread{}; - connect(thread, &BigConcurrentTaskThread::finished, &loop, &QEventLoop::quit); + connect(&thread, &BigConcurrentTaskThread::finished, &loop, &QEventLoop::quit); - thread->start(); + thread.start(); loop.exec(); - QVERIFY(!thread->passed_the_deadline); - thread->deleteLater(); + QVERIFY(!thread.passed_the_deadline); } }; From 8638076aa1cf3f1a975ac59ddaf0286acc7d39e2 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Wed, 5 Jul 2023 20:19:22 -0700 Subject: [PATCH 122/216] fix(test): tasks test memmory leak. don't store local task copy. Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- tests/Task_test.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/Task_test.cpp b/tests/Task_test.cpp index ef7042a59..41e51f838 100644 --- a/tests/Task_test.cpp +++ b/tests/Task_test.cpp @@ -64,11 +64,9 @@ class BigConcurrentTaskThread : public QThread { // this number is enough to fill up 16 MiB of stack, more than enough to cause a problem. static const unsigned s_num_tasks = 1 << 12; { - auto sub_tasks = std::array(); for (unsigned i = 0; i < s_num_tasks; i++) { auto sub_task = makeShared(false); - sub_tasks[i] = sub_task; big_task.addTask(sub_task); } From 71e73bb6f8c4a695e39f0c0fec901d8a5e5121b3 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Wed, 5 Jul 2023 21:18:49 -0700 Subject: [PATCH 123/216] fix(tests): linux big task memory leak. - move big_task into function scope Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- tests/Task_test.cpp | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/tests/Task_test.cpp b/tests/Task_test.cpp index 41e51f838..00d067947 100644 --- a/tests/Task_test.cpp +++ b/tests/Task_test.cpp @@ -50,31 +50,34 @@ class BigConcurrentTask : public ConcurrentTask { class BigConcurrentTaskThread : public QThread { Q_OBJECT - BigConcurrentTask big_task; void run() override { QTimer deadline; + BigConcurrentTask big_task; deadline.setInterval(10000); - connect(&deadline, &QTimer::timeout, this, [this] { passed_the_deadline = true; }); + bool* pt_deadline = &passed_the_deadline; + QMetaObject::Connection conn = connect(&deadline, &QTimer::timeout, this, [pt_deadline] { *pt_deadline = true; }); deadline.start(); // NOTE: Arbitrary value that manages to trigger a problem when there is one. // Considering each tasks, in a problematic state, adds 1024 * 4 bytes to the stack, // this number is enough to fill up 16 MiB of stack, more than enough to cause a problem. static const unsigned s_num_tasks = 1 << 12; - { + for (unsigned i = 0; i < s_num_tasks; i++) { + auto sub_task = makeShared(false); + big_task.addTask(sub_task); + } - for (unsigned i = 0; i < s_num_tasks; i++) { - auto sub_task = makeShared(false); - big_task.addTask(sub_task); - } + big_task.run(); - big_task.run(); - - while (!big_task.isFinished() && !passed_the_deadline) - QCoreApplication::processEvents(); - } // drop before emit + while (!big_task.isFinished() && !passed_the_deadline) + QCoreApplication::processEvents(); + // don't fire timer after this point + disconnect(conn); + if (deadline.isActive()) + deadline.stop(); + // task finished emit finished(); } From 13d67c6524a29daea51242d17ba0c6a2b8593747 Mon Sep 17 00:00:00 2001 From: PandaNinjas Date: Thu, 6 Jul 2023 08:51:42 -0400 Subject: [PATCH 124/216] Keep formatting consistent Signed-off-by: PandaNinjas --- launcher/VersionProxyModel.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/launcher/VersionProxyModel.cpp b/launcher/VersionProxyModel.cpp index 91f94f412..63a43465c 100644 --- a/launcher/VersionProxyModel.cpp +++ b/launcher/VersionProxyModel.cpp @@ -193,13 +193,16 @@ QVariant VersionProxyModel::data(const QModelIndex &index, int role) const } case Qt::ToolTipRole: { - if (column == Name && hasRecommended) { + if(column == Name && hasRecommended) + { auto value = sourceModel()->data(parentIndex, BaseVersionList::RecommendedRole); - if (value.toBool()) { + if(value.toBool()) + { return tr("Recommended"); } else if(hasLatest) { auto value = sourceModel()->data(parentIndex, BaseVersionList::LatestRole); - if(value.toBool()) { + if(value.toBool()) + { return tr("Latest"); } } From 93870c315f84d2bb599d669be8205990ee48907d Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 6 Jul 2023 18:46:59 +0300 Subject: [PATCH 125/216] better url handling Signed-off-by: Trial97 --- launcher/ui/widgets/InfoFrame.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/ui/widgets/InfoFrame.cpp b/launcher/ui/widgets/InfoFrame.cpp index b16bc097f..a0fda952f 100644 --- a/launcher/ui/widgets/InfoFrame.cpp +++ b/launcher/ui/widgets/InfoFrame.cpp @@ -46,7 +46,7 @@ void setupLinkToolTip(QLabel* label) { QObject::connect(label, &QLabel::linkHovered, [label](const QString& link) { - if (!link.isEmpty() && !link.startsWith("http")) + if (auto url = QUrl(link); !url.isValid() || (url.scheme() != "http" && url.scheme() != "https")) return; label->setToolTip(link); }); From b8b8c8d4acab8c794555956fae699d5706e222f3 Mon Sep 17 00:00:00 2001 From: flow Date: Thu, 6 Jul 2023 06:38:36 -0300 Subject: [PATCH 126/216] fix(tests): Fix abort of Task test on Linux Not sure exactly what caused the issue, though I suppose using QThread's exec instead of our own thingie is nice. I can't remember why I didn't use that before, so I hope there's no issue with that! :^) Signed-off-by: flow --- tests/Task_test.cpp | 26 ++++++++------------------ 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/tests/Task_test.cpp b/tests/Task_test.cpp index 00d067947..c59d4bb73 100644 --- a/tests/Task_test.cpp +++ b/tests/Task_test.cpp @@ -50,15 +50,11 @@ class BigConcurrentTask : public ConcurrentTask { class BigConcurrentTaskThread : public QThread { Q_OBJECT - + QTimer m_deadline; void run() override { - QTimer deadline; BigConcurrentTask big_task; - deadline.setInterval(10000); - bool* pt_deadline = &passed_the_deadline; - QMetaObject::Connection conn = connect(&deadline, &QTimer::timeout, this, [pt_deadline] { *pt_deadline = true; }); - deadline.start(); + m_deadline.setInterval(10000); // NOTE: Arbitrary value that manages to trigger a problem when there is one. // Considering each tasks, in a problematic state, adds 1024 * 4 bytes to the stack, @@ -69,23 +65,17 @@ class BigConcurrentTaskThread : public QThread { big_task.addTask(sub_task); } + connect(&big_task, &Task::finished, this, &QThread::quit); + connect(&m_deadline, &QTimer::timeout, this, [&] { passed_the_deadline = true; quit(); }); + + m_deadline.start(); big_task.run(); - while (!big_task.isFinished() && !passed_the_deadline) - QCoreApplication::processEvents(); - // don't fire timer after this point - disconnect(conn); - if (deadline.isActive()) - deadline.stop(); - // task finished - emit finished(); + exec(); } public: bool passed_the_deadline = false; - - signals: - void finished(); }; class TaskTest : public QObject { @@ -253,7 +243,7 @@ class TaskTest : public QObject { { QEventLoop loop; - BigConcurrentTaskThread thread{}; + BigConcurrentTaskThread thread; connect(&thread, &BigConcurrentTaskThread::finished, &loop, &QEventLoop::quit); From 8ae67b84dbf154bef957bfba1342eac27cd4837e Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Thu, 6 Jul 2023 20:03:25 +0100 Subject: [PATCH 127/216] Optional mods in mrpack export Signed-off-by: TheKodeToad --- .../modrinth/ModrinthPackExportTask.cpp | 50 +++++++++++-------- 1 file changed, 30 insertions(+), 20 deletions(-) diff --git a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp index 4cd88aa69..cbdfd04f0 100644 --- a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp +++ b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp @@ -263,13 +263,13 @@ void ModrinthPackExportTask::finish() QByteArray ModrinthPackExportTask::generateIndex() { - QJsonObject obj; - obj["formatVersion"] = 1; - obj["game"] = "minecraft"; - obj["name"] = name; - obj["versionId"] = version; + QJsonObject out; + out["formatVersion"] = 1; + out["game"] = "minecraft"; + out["name"] = name; + out["versionId"] = version; if (!summary.isEmpty()) - obj["summary"] = summary; + out["summary"] = summary; if (mcInstance) { auto profile = mcInstance->getPackProfile(); @@ -290,30 +290,40 @@ QByteArray ModrinthPackExportTask::generateIndex() if (forge != nullptr) dependencies["forge"] = forge->m_version; - obj["dependencies"] = dependencies; + out["dependencies"] = dependencies; } - QJsonArray files; - QMapIterator iterator(resolvedFiles); - while (iterator.hasNext()) { - iterator.next(); + QJsonArray filesOut; + for (auto iterator = resolvedFiles.constBegin(); iterator != resolvedFiles.constEnd(); iterator++) { + QJsonObject fileOut; + QString path = iterator.key(); const ResolvedFile& value = iterator.value(); - QJsonObject file; - file["path"] = iterator.key(); - file["downloads"] = QJsonArray({ iterator.value().url }); + // detect disabled mod + QString disabledSuffix = ".disabled"; + if (path.endsWith(disabledSuffix)) { + // rename it + path = path.left(path.length() - disabledSuffix.length()); + // ...and make it optional + QJsonObject env; + env["client"] = "optional"; + env["server"] = "optional"; + fileOut["env"] = env; + } + + fileOut["path"] = path; + fileOut["downloads"] = QJsonArray{ iterator.value().url }; QJsonObject hashes; hashes["sha1"] = value.sha1; hashes["sha512"] = value.sha512; + fileOut["hashes"] = hashes; - file["hashes"] = hashes; - file["fileSize"] = value.size; - - files << file; + fileOut["fileSize"] = value.size; + filesOut << fileOut; } - obj["files"] = files; + out["files"] = filesOut; - return QJsonDocument(obj).toJson(QJsonDocument::Compact); + return QJsonDocument(out).toJson(QJsonDocument::Compact); } From 073cb91f885b780ae04b6d9a4b94702307f07321 Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Fri, 7 Jul 2023 15:56:04 +0200 Subject: [PATCH 128/216] fix(ui): validate meta override url Signed-off-by: Sefa Eyeoglu --- launcher/ui/pages/global/APIPage.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/launcher/ui/pages/global/APIPage.cpp b/launcher/ui/pages/global/APIPage.cpp index dca1b3a63..fab31dbd9 100644 --- a/launcher/ui/pages/global/APIPage.cpp +++ b/launcher/ui/pages/global/APIPage.cpp @@ -81,6 +81,8 @@ APIPage::APIPage(QWidget *parent) : connect(ui->pasteTypeComboBox, currentIndexChangedSignal, this, &APIPage::updateBaseURLPlaceholder); // This function needs to be called even when the ComboBox's index is still in its default state. updateBaseURLPlaceholder(ui->pasteTypeComboBox->currentIndex()); + // NOTE: this allows http://, but we replace that with https later anyway + ui->metaURL->setValidator(new QRegularExpressionValidator(validUrlRegExp, ui->metaURL)); ui->baseURLEntry->setValidator(new QRegularExpressionValidator(validUrlRegExp, ui->baseURLEntry)); ui->msaClientID->setValidator(new QRegularExpressionValidator(validMSAClientID, ui->msaClientID)); ui->flameKey->setValidator(new QRegularExpressionValidator(validFlameKey, ui->flameKey)); From 6fcdac0d36865eadc2454244ce03c77e6eed767b Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Fri, 7 Jul 2023 15:57:24 +0200 Subject: [PATCH 129/216] fix: reset invalid meta url on launch Signed-off-by: Sefa Eyeoglu --- launcher/Application.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/launcher/Application.cpp b/launcher/Application.cpp index 1d97a5f2e..34e1320a2 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -687,8 +687,16 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) m_settings->reset("PastebinCustomAPIBase"); } } - // meta URL - m_settings->registerSetting("MetaURLOverride", ""); + { + // Meta URL + m_settings->registerSetting("MetaURLOverride", ""); + + QUrl metaUrl = m_settings->get("MetaURLOverride").toString(); + + // get rid of invalid meta urls + if (!metaUrl.isValid() || metaUrl.scheme() != "http" || metaUrl.scheme() != "https") + m_settings->reset("MetaURLOverride"); + } m_settings->registerSetting("CloseAfterLaunch", false); m_settings->registerSetting("QuitAfterGameStop", false); From 3139af8487ae8ea20468023e477be02cf0b96a4d Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 7 Jul 2023 17:12:10 +0300 Subject: [PATCH 130/216] Made action text simpler Signed-off-by: Trial97 --- launcher/ui/pages/instance/ModFolderPage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/ui/pages/instance/ModFolderPage.cpp b/launcher/ui/pages/instance/ModFolderPage.cpp index ce6968f53..fe2f21c90 100644 --- a/launcher/ui/pages/instance/ModFolderPage.cpp +++ b/launcher/ui/pages/instance/ModFolderPage.cpp @@ -107,7 +107,7 @@ ModFolderPage::ModFolderPage(BaseInstance* inst, std::shared_ptr ui->actionVisitItemPage->setText(tr("Visit mod's page")); ui->actionVisitItemPage->setToolTip(tr("Go to mod's home page")); } else { - ui->actionVisitItemPage->setText(tr("Visit the pages of the selected mods")); + ui->actionVisitItemPage->setText(tr("Visit mods pages")); ui->actionVisitItemPage->setToolTip(tr("Go to the pages of the selected mods")); } ui->actionVisitItemPage->setEnabled(selected != 0); From b8482a5d89b4044482e7b55aa1c2e2547b41f4fd Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Fri, 7 Jul 2023 15:53:50 +0100 Subject: [PATCH 131/216] Update ModFolderPage.cpp Signed-off-by: TheKodeToad --- launcher/ui/pages/instance/ModFolderPage.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/launcher/ui/pages/instance/ModFolderPage.cpp b/launcher/ui/pages/instance/ModFolderPage.cpp index fe2f21c90..041d1bfd2 100644 --- a/launcher/ui/pages/instance/ModFolderPage.cpp +++ b/launcher/ui/pages/instance/ModFolderPage.cpp @@ -107,7 +107,7 @@ ModFolderPage::ModFolderPage(BaseInstance* inst, std::shared_ptr ui->actionVisitItemPage->setText(tr("Visit mod's page")); ui->actionVisitItemPage->setToolTip(tr("Go to mod's home page")); } else { - ui->actionVisitItemPage->setText(tr("Visit mods pages")); + ui->actionVisitItemPage->setText(tr("Visit mods' pages")); ui->actionVisitItemPage->setToolTip(tr("Go to the pages of the selected mods")); } ui->actionVisitItemPage->setEnabled(selected != 0); @@ -303,4 +303,4 @@ void ModFolderPage::visitModPages() if (!url.isEmpty()) DesktopServices::openUrl(url); } -} \ No newline at end of file +} From 51e62761ee8e8cd868c5f2a7eb63d54de5b71d6a Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Fri, 7 Jul 2023 19:25:12 +0200 Subject: [PATCH 132/216] fix: improve QUrl construction Signed-off-by: Sefa Eyeoglu --- launcher/Application.cpp | 2 +- launcher/ui/pages/global/APIPage.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/launcher/Application.cpp b/launcher/Application.cpp index 34e1320a2..7858d7132 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -691,7 +691,7 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) // Meta URL m_settings->registerSetting("MetaURLOverride", ""); - QUrl metaUrl = m_settings->get("MetaURLOverride").toString(); + QUrl metaUrl(m_settings->get("MetaURLOverride").toString()); // get rid of invalid meta urls if (!metaUrl.isValid() || metaUrl.scheme() != "http" || metaUrl.scheme() != "https") diff --git a/launcher/ui/pages/global/APIPage.cpp b/launcher/ui/pages/global/APIPage.cpp index fab31dbd9..668aa0078 100644 --- a/launcher/ui/pages/global/APIPage.cpp +++ b/launcher/ui/pages/global/APIPage.cpp @@ -165,7 +165,7 @@ void APIPage::applySettings() QString msaClientID = ui->msaClientID->text(); s->set("MSAClientIDOverride", msaClientID); - QUrl metaURL = ui->metaURL->text(); + QUrl metaURL(ui->metaURL->text()); // Add required trailing slash if (!metaURL.isEmpty() && !metaURL.path().endsWith('/')) { From 20c781b23b0d2bd2be8bed0c015eb6c82312c29a Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Sat, 8 Jul 2023 02:28:37 -0700 Subject: [PATCH 133/216] fix(progress dialog): if there is a parent center on creation Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/ui/dialogs/ProgressDialog.cpp | 23 +++++++++++++++-------- launcher/ui/dialogs/ProgressDialog.h | 2 +- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/launcher/ui/dialogs/ProgressDialog.cpp b/launcher/ui/dialogs/ProgressDialog.cpp index 3368a8c47..4243e2917 100644 --- a/launcher/ui/dialogs/ProgressDialog.cpp +++ b/launcher/ui/dialogs/ProgressDialog.cpp @@ -67,9 +67,9 @@ ProgressDialog::ProgressDialog(QWidget* parent) : QDialog(parent), ui(new Ui::Pr ui->taskProgressScrollArea->setHidden(true); this->setWindowFlags(this->windowFlags() & ~Qt::WindowContextHelpButtonHint); setAttribute(Qt::WidgetAttribute::WA_QuitOnClose, true); - setSkipButton(false); changeProgress(0, 100); - updateSize(); + updateSize(true); + setSkipButton(false); } void ProgressDialog::setSkipButton(bool present, QString label) @@ -95,7 +95,7 @@ ProgressDialog::~ProgressDialog() delete ui; } -void ProgressDialog::updateSize() +void ProgressDialog::updateSize(bool recenterParent) { QSize lastSize = this->size(); QPoint lastPos = this->pos(); @@ -112,13 +112,20 @@ void ProgressDialog::updateSize() adjustSize(); QSize newSize = this->size(); - // if the current window is too small - if ((lastSize != newSize) && (lastSize.height() < newSize.height())) + // if the current window is a different size + auto parent = this->parentWidget(); + if (recenterParent && parent) { + auto newX = std::max(0, parent->x() + ((parent->width() - newSize.width()) / 2)); + auto newY = std::max(0, parent->y() + ((parent->height() - newSize.height()) / 2)); + this->move(newX, newY); + } + else if (lastSize != newSize) { - QSize sizeDiff = lastSize - newSize; // last size was smaller, the results should be negative // center on old position after resize - QPoint newPos(lastPos.x() + (sizeDiff.width() / 2), lastPos.y() + (sizeDiff.height() / 2)); - this->move(newPos); + QSize sizeDiff = lastSize - newSize; // last size was smaller, the results should be negative + auto newX = std::max(0, lastPos.x() + (sizeDiff.width() / 2)); + auto newY = std::max(0, lastPos.y() + (sizeDiff.height() / 2)); + this->move(newX, newY); } } diff --git a/launcher/ui/dialogs/ProgressDialog.h b/launcher/ui/dialogs/ProgressDialog.h index fc9a0fbc3..f062be084 100644 --- a/launcher/ui/dialogs/ProgressDialog.h +++ b/launcher/ui/dialogs/ProgressDialog.h @@ -62,7 +62,7 @@ public: explicit ProgressDialog(QWidget *parent = 0); ~ProgressDialog(); - void updateSize(); + void updateSize(bool recenterParent = false); int execWithTask(Task* task); int execWithTask(std::unique_ptr &&task); From 0c6362f28d1caec4d256c538d2874b226390ad85 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Sat, 8 Jul 2023 18:51:28 +0100 Subject: [PATCH 134/216] Make trash hungry Signed-off-by: TheKodeToad --- launcher/minecraft/mod/Mod.cpp | 4 ++-- launcher/minecraft/mod/Mod.h | 2 +- launcher/minecraft/mod/ModFolderModel.cpp | 6 +++--- launcher/minecraft/mod/Resource.cpp | 8 ++------ launcher/minecraft/mod/Resource.h | 2 +- launcher/minecraft/mod/ResourceFolderModel.cpp | 2 +- launcher/minecraft/mod/tasks/ModFolderLoadTask.cpp | 2 +- 7 files changed, 11 insertions(+), 15 deletions(-) diff --git a/launcher/minecraft/mod/Mod.cpp b/launcher/minecraft/mod/Mod.cpp index fa1a02534..880dacb15 100644 --- a/launcher/minecraft/mod/Mod.cpp +++ b/launcher/minecraft/mod/Mod.cpp @@ -126,7 +126,7 @@ bool Mod::applyFilter(QRegularExpression filter) const return Resource::applyFilter(filter); } -auto Mod::destroy(QDir& index_dir, bool preserve_metadata) -> bool +auto Mod::destroy(QDir& index_dir, bool preserve_metadata, bool attempt_trash) -> bool { if (!preserve_metadata) { qDebug() << QString("Destroying metadata for '%1' on purpose").arg(name()); @@ -139,7 +139,7 @@ auto Mod::destroy(QDir& index_dir, bool preserve_metadata) -> bool } } - return Resource::destroy(); + return Resource::destroy(attempt_trash); } auto Mod::details() const -> const ModDetails& diff --git a/launcher/minecraft/mod/Mod.h b/launcher/minecraft/mod/Mod.h index d6272f4d0..b67bd4659 100644 --- a/launcher/minecraft/mod/Mod.h +++ b/launcher/minecraft/mod/Mod.h @@ -93,7 +93,7 @@ public: [[nodiscard]] bool applyFilter(QRegularExpression filter) const override; // Delete all the files of this mod - auto destroy(QDir& index_dir, bool preserve_metadata = false) -> bool; + auto destroy(QDir& index_dir, bool preserve_metadata = false, bool attempt_trash = true) -> bool; void finishResolvingWithDetails(ModDetails&& details); diff --git a/launcher/minecraft/mod/ModFolderModel.cpp b/launcher/minecraft/mod/ModFolderModel.cpp index af98d8348..50f96b72c 100644 --- a/launcher/minecraft/mod/ModFolderModel.cpp +++ b/launcher/minecraft/mod/ModFolderModel.cpp @@ -199,10 +199,10 @@ Task* ModFolderModel::createParseTask(Resource& resource) bool ModFolderModel::uninstallMod(const QString& filename, bool preserve_metadata) { - for(auto mod : allMods()){ - if(mod->fileinfo().fileName() == filename){ + for(auto mod : allMods()) { + if(mod->fileinfo().fileName() == filename) { auto index_dir = indexDir(); - mod->destroy(index_dir, preserve_metadata); + mod->destroy(index_dir, preserve_metadata, false); update(); diff --git a/launcher/minecraft/mod/Resource.cpp b/launcher/minecraft/mod/Resource.cpp index e50772601..098a617f8 100644 --- a/launcher/minecraft/mod/Resource.cpp +++ b/launcher/minecraft/mod/Resource.cpp @@ -148,14 +148,10 @@ bool Resource::enable(EnableAction action) return true; } -bool Resource::destroy() +bool Resource::destroy(bool attemptTrash) { m_type = ResourceType::UNKNOWN; - - if (FS::trash(m_file_info.filePath())) - return true; - - return FS::deletePath(m_file_info.filePath()); + return (attemptTrash && FS::trash(m_file_info.filePath())) || FS::deletePath(m_file_info.filePath()); } bool Resource::isSymLinkUnder(const QString& instPath) const diff --git a/launcher/minecraft/mod/Resource.h b/launcher/minecraft/mod/Resource.h index a5e9ae91e..94f3160c3 100644 --- a/launcher/minecraft/mod/Resource.h +++ b/launcher/minecraft/mod/Resource.h @@ -92,7 +92,7 @@ class Resource : public QObject { } // Delete all files of this resource. - bool destroy(); + bool destroy(bool attemptTrash = true); [[nodiscard]] auto isSymLink() const -> bool { return m_file_info.isSymLink(); } diff --git a/launcher/minecraft/mod/ResourceFolderModel.cpp b/launcher/minecraft/mod/ResourceFolderModel.cpp index 7700fd36b..79169ae84 100644 --- a/launcher/minecraft/mod/ResourceFolderModel.cpp +++ b/launcher/minecraft/mod/ResourceFolderModel.cpp @@ -159,7 +159,7 @@ bool ResourceFolderModel::uninstallResource(QString file_name) { for (auto& resource : m_resources) { if (resource->fileinfo().fileName() == file_name) { - auto res = resource->destroy(); + auto res = resource->destroy(false); update(); diff --git a/launcher/minecraft/mod/tasks/ModFolderLoadTask.cpp b/launcher/minecraft/mod/tasks/ModFolderLoadTask.cpp index 3677a1dca..ef353c701 100644 --- a/launcher/minecraft/mod/tasks/ModFolderLoadTask.cpp +++ b/launcher/minecraft/mod/tasks/ModFolderLoadTask.cpp @@ -103,7 +103,7 @@ void ModFolderLoadTask::executeTask() while (iter.hasNext()) { auto mod = iter.next().value(); if (mod->status() == ModStatus::NotInstalled) { - mod->destroy(m_index_dir, false); + mod->destroy(m_index_dir, false, false); iter.remove(); } } From 08c140b9b45b1a8afd134793acedf867526d6432 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Sat, 8 Jul 2023 20:51:27 +0100 Subject: [PATCH 135/216] Fix actionVisitItemPage insersion, and prevent widebar segfault Signed-off-by: TheKodeToad --- launcher/ui/pages/instance/ModFolderPage.cpp | 2 +- launcher/ui/widgets/WideBar.cpp | 13 +++++++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/launcher/ui/pages/instance/ModFolderPage.cpp b/launcher/ui/pages/instance/ModFolderPage.cpp index 041d1bfd2..9f0776189 100644 --- a/launcher/ui/pages/instance/ModFolderPage.cpp +++ b/launcher/ui/pages/instance/ModFolderPage.cpp @@ -89,7 +89,7 @@ ModFolderPage::ModFolderPage(BaseInstance* inst, std::shared_ptr connect(ui->actionUpdateItem, &QAction::triggered, this, &ModFolderPage::updateMods); ui->actionVisitItemPage->setToolTip(tr("Go to mod's home page")); - ui->actionsToolbar->insertActionAfter(ui->actionViewFolder, ui->actionVisitItemPage); + ui->actionsToolbar->addAction(ui->actionVisitItemPage); connect(ui->actionVisitItemPage, &QAction::triggered, this, &ModFolderPage::visitModPages); auto check_allow_update = [this] { diff --git a/launcher/ui/widgets/WideBar.cpp b/launcher/ui/widgets/WideBar.cpp index ac34e3aaa..a77c45fee 100644 --- a/launcher/ui/widgets/WideBar.cpp +++ b/launcher/ui/widgets/WideBar.cpp @@ -116,12 +116,21 @@ void WideBar::insertActionAfter(QAction* after, QAction* action) if (iter == m_entries.end()) return; + iter++; + // the action to insert after is present + // however, the element after it isn't valid + if (iter == m_entries.end()) { + // append the action instead of inserting it + addAction(action); + return; + } + BarEntry entry; - entry.bar_action = insertWidget((iter + 1)->bar_action, new ActionButton(action, this, m_use_default_action)); + entry.bar_action = insertWidget(iter->bar_action, new ActionButton(action, this, m_use_default_action)); entry.menu_action = action; entry.type = BarEntry::Type::Action; - m_entries.insert(iter + 1, entry); + m_entries.insert(iter, entry); m_menu_state = MenuState::Dirty; } From a54bbae62282e8adce76df9626c58b6bb3e12967 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Sat, 8 Jul 2023 12:59:55 -0700 Subject: [PATCH 136/216] fix(instance edit): don't allow editing if no selected instance or instance doesn't support editing Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/ui/MainWindow.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp index 515abf070..254f229da 100644 --- a/launcher/ui/MainWindow.cpp +++ b/launcher/ui/MainWindow.cpp @@ -1279,7 +1279,17 @@ void MainWindow::globalSettingsClosed() void MainWindow::on_actionEditInstance_triggered() { - APPLICATION->showInstanceWindow(m_selectedInstance); + + if (!m_selectedInstance) + return; + + if (m_selectedInstance->canEdit()) { + APPLICATION->showInstanceWindow(m_selectedInstance); + } else { + CustomMessageBox::selectable(this, tr("Instance not editable"), + tr("This instance is not editable. it may be broken, invalid, or too old. Check logs for details,"), + QMessageBox::Critical)->show(); + } } void MainWindow::on_actionManageAccounts_triggered() From e70407289266a205147bfb1293763e64dacb0f3e Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Sat, 8 Jul 2023 13:38:00 -0700 Subject: [PATCH 137/216] fix(flame install): don't assume .zip is a resource pack. default to mod let identifier move it if needed Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/minecraft/mod/tasks/LocalResourceParse.cpp | 9 +++++---- launcher/modplatform/flame/FlameInstanceCreationTask.cpp | 8 +++++--- launcher/modplatform/flame/PackManifest.cpp | 9 ++------- 3 files changed, 12 insertions(+), 14 deletions(-) diff --git a/launcher/minecraft/mod/tasks/LocalResourceParse.cpp b/launcher/minecraft/mod/tasks/LocalResourceParse.cpp index 4d760df2b..6d9b4d97a 100644 --- a/launcher/minecraft/mod/tasks/LocalResourceParse.cpp +++ b/launcher/minecraft/mod/tasks/LocalResourceParse.cpp @@ -44,7 +44,11 @@ static const QMap s_packed_type_names = { namespace ResourceUtils { PackedResourceType identify(QFileInfo file){ if (file.exists() && file.isFile()) { - if (ResourcePackUtils::validate(file)) { + if (ModUtils::validate(file)) { + // mods can contain resource and data packs so they much be tested first + qDebug() << file.fileName() << "is a mod"; + return PackedResourceType::Mod; + } else if (ResourcePackUtils::validate(file)) { qDebug() << file.fileName() << "is a resource pack"; return PackedResourceType::ResourcePack; } else if (TexturePackUtils::validate(file)) { @@ -53,9 +57,6 @@ PackedResourceType identify(QFileInfo file){ } else if (DataPackUtils::validate(file)) { qDebug() << file.fileName() << "is a data pack"; return PackedResourceType::DataPack; - } else if (ModUtils::validate(file)) { - qDebug() << file.fileName() << "is a mod"; - return PackedResourceType::Mod; } else if (WorldSaveUtils::validate(file)) { qDebug() << file.fileName() << "is a world save"; return PackedResourceType::WorldSave; diff --git a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp index e7641d644..b57db288a 100644 --- a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp +++ b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp @@ -563,6 +563,8 @@ void FlameCreationTask::validateZIPResouces() if (FS::move(localPath, destPath)) { return destPath; } + } else { + qDebug() << "Target folder of" << fileName << "is correct at" << targetFolder; } return localPath; }; @@ -584,6 +586,9 @@ void FlameCreationTask::validateZIPResouces() QString worldPath; switch (type) { + case PackedResourceType::Mod : + validatePath(fileName, targetFolder, "mods"); + break; case PackedResourceType::ResourcePack : validatePath(fileName, targetFolder, "resourcepacks"); break; @@ -593,9 +598,6 @@ void FlameCreationTask::validateZIPResouces() case PackedResourceType::DataPack : validatePath(fileName, targetFolder, "datapacks"); break; - case PackedResourceType::Mod : - validatePath(fileName, targetFolder, "mods"); - break; case PackedResourceType::ShaderPack : // in theroy flame API can't do this but who knows, that *may* change ? // better to handle it if it *does* occure in the future diff --git a/launcher/modplatform/flame/PackManifest.cpp b/launcher/modplatform/flame/PackManifest.cpp index 22008297f..ee4d07662 100644 --- a/launcher/modplatform/flame/PackManifest.cpp +++ b/launcher/modplatform/flame/PackManifest.cpp @@ -76,13 +76,8 @@ bool Flame::File::parseFromObject(const QJsonObject& obj, bool throw_on_blocked // It is also optional type = File::Type::SingleFile; - if (fileName.endsWith(".zip")) { - // this is probably a resource pack - targetFolder = "resourcepacks"; - } else { - // this is probably a mod, dunno what else could modpacks download - targetFolder = "mods"; - } + targetFolder = "mods"; + // get the hash hash = QString(); auto hashes = Json::ensureArray(obj, "hashes"); From d53d58a5d42684c5151680016f38a0f4bd1c0298 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Sat, 8 Jul 2023 22:03:47 +0100 Subject: [PATCH 138/216] LiteMod downloading Signed-off-by: TheKodeToad --- launcher/minecraft/PackProfile.cpp | 3 ++- launcher/modplatform/flame/FlameAPI.h | 2 ++ launcher/modplatform/modrinth/ModrinthAPI.h | 6 +++--- launcher/ui/dialogs/ResourceDownloadDialog.cpp | 9 +++++++-- 4 files changed, 14 insertions(+), 6 deletions(-) diff --git a/launcher/minecraft/PackProfile.cpp b/launcher/minecraft/PackProfile.cpp index aff05dbc8..e8fd21572 100644 --- a/launcher/minecraft/PackProfile.cpp +++ b/launcher/minecraft/PackProfile.cpp @@ -65,7 +65,8 @@ static const QMap modloaderMapping{ {"net.minecraftforge", ResourceAPI::Forge}, {"net.fabricmc.fabric-loader", ResourceAPI::Fabric}, - {"org.quiltmc.quilt-loader", ResourceAPI::Quilt} + {"org.quiltmc.quilt-loader", ResourceAPI::Quilt}, + {"com.mumfrey.liteloader", ResourceAPI::LiteLoader} }; PackProfile::PackProfile(MinecraftInstance * instance) diff --git a/launcher/modplatform/flame/FlameAPI.h b/launcher/modplatform/flame/FlameAPI.h index 0a6dc78f8..49bc316f2 100644 --- a/launcher/modplatform/flame/FlameAPI.h +++ b/launcher/modplatform/flame/FlameAPI.h @@ -23,6 +23,8 @@ class FlameAPI : public NetworkResourceAPI { [[nodiscard]] auto getSortingMethods() const -> QList override; + static inline auto validateModLoaders(ModLoaderTypes loaders) -> bool { return loaders & (Forge | Fabric | Quilt); } + private: static int getClassId(ModPlatform::ResourceType type) { diff --git a/launcher/modplatform/modrinth/ModrinthAPI.h b/launcher/modplatform/modrinth/ModrinthAPI.h index e83ed2bf7..58af14cc7 100644 --- a/launcher/modplatform/modrinth/ModrinthAPI.h +++ b/launcher/modplatform/modrinth/ModrinthAPI.h @@ -38,7 +38,7 @@ class ModrinthAPI : public NetworkResourceAPI { static auto getModLoaderStrings(const ModLoaderTypes types) -> const QStringList { QStringList l; - for (auto loader : { Forge, Fabric, Quilt }) { + for (auto loader : { Forge, Fabric, Quilt, LiteLoader }) { if (types & loader) { l << getModLoaderString(loader); } @@ -92,7 +92,7 @@ class ModrinthAPI : public NetworkResourceAPI { { if (args.loaders.has_value()) { if (!validateModLoaders(args.loaders.value())) { - qWarning() << "Modrinth only have Forge and Fabric-compatible mods!"; + qWarning() << "Modrinth - or our interface - does not support any the provided mod loaders!"; return {}; } } @@ -141,7 +141,7 @@ class ModrinthAPI : public NetworkResourceAPI { return s.isEmpty() ? QString() : s; } - inline auto validateModLoaders(ModLoaderTypes loaders) const -> bool { return loaders & (Forge | Fabric | Quilt); } + static inline auto validateModLoaders(ModLoaderTypes loaders) -> bool { return loaders & (Forge | Fabric | Quilt | LiteLoader); } [[nodiscard]] std::optional getDependencyURL(DependencySearchArgs const& args) const override { diff --git a/launcher/ui/dialogs/ResourceDownloadDialog.cpp b/launcher/ui/dialogs/ResourceDownloadDialog.cpp index 4f59f5605..b17eced35 100644 --- a/launcher/ui/dialogs/ResourceDownloadDialog.cpp +++ b/launcher/ui/dialogs/ResourceDownloadDialog.cpp @@ -43,6 +43,8 @@ #include "ui/pages/modplatform/flame/FlameResourcePages.h" #include "ui/pages/modplatform/modrinth/ModrinthResourcePages.h" +#include "modplatform/flame/FlameAPI.h" +#include "modplatform/modrinth/ModrinthAPI.h" #include "ui/widgets/PageContainer.h" namespace ResourceDownload { @@ -281,8 +283,11 @@ QList ModDownloadDialog::getPages() { QList pages; - pages.append(ModrinthModPage::create(this, *m_instance)); - if (APPLICATION->capabilities() & Application::SupportsFlame) + auto loaders = static_cast(m_instance)->getPackProfile()->getModLoaders().value(); + + if (ModrinthAPI::validateModLoaders(loaders)) + pages.append(ModrinthModPage::create(this, *m_instance)); + if (APPLICATION->capabilities() & Application::SupportsFlame && FlameAPI::validateModLoaders(loaders)) pages.append(FlameModPage::create(this, *m_instance)); m_selectedPage = dynamic_cast(pages[0]); From 4dc4c589ba21df9c5e04081e35788862b498f29d Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Sat, 8 Jul 2023 15:44:09 -0700 Subject: [PATCH 139/216] packaging: fix duplicate share directories (use only lowercase) Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- CMakeLists.txt | 2 +- launcher/Application.cpp | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 70a553190..0defd5e0b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -345,7 +345,7 @@ elseif(UNIX) install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${Launcher_SVG} DESTINATION "${KDE_INSTALL_ICONDIR}/hicolor/scalable/apps") install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${Launcher_mrpack_MIMEInfo} DESTINATION ${KDE_INSTALL_MIMEDIR}) - install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/launcher/qtlogging.ini" DESTINATION "${KDE_INSTALL_DATADIR}/${Launcher_Name}") + install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/launcher/qtlogging.ini" DESTINATION "share/${Launcher_APP_BINARY_NAME}") if(Launcher_ManPage) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${Launcher_ManPage} DESTINATION "${KDE_INSTALL_MANDIR}/man6") diff --git a/launcher/Application.cpp b/launcher/Application.cpp index 7858d7132..8c60f6974 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -433,7 +433,11 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) } // seach root path if(!foundLoggingRules) { +#if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) || defined(Q_OS_OPENBSD) + logRulesPath = FS::PathCombine(m_rootPath, "share", BuildConfig.LAUNCHER_APP_BINARY_NAME, logRulesFile); +#else logRulesPath = FS::PathCombine(m_rootPath, logRulesFile); +#endif qDebug() << "Testing" << logRulesPath << "..."; foundLoggingRules = QFile::exists(logRulesPath); } From 0d31e31282008e2b6df6b551facb64a2dfc98db8 Mon Sep 17 00:00:00 2001 From: seth Date: Sun, 9 Jul 2023 01:56:21 -0400 Subject: [PATCH 140/216] fix(actions): give update-flake content write perms Signed-off-by: seth --- .github/workflows/update-flake.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/update-flake.yml b/.github/workflows/update-flake.yml index c790c9c69..e79040ab4 100644 --- a/.github/workflows/update-flake.yml +++ b/.github/workflows/update-flake.yml @@ -7,6 +7,7 @@ on: workflow_dispatch: permissions: + contents: write pull-requests: write jobs: From 6e2fcc9e1102d3955a509c3346b8df15ce52a6a1 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Sun, 9 Jul 2023 12:08:15 +0100 Subject: [PATCH 141/216] Replace string manipulation in favour of QFileInfo Signed-off-by: TheKodeToad --- launcher/modplatform/modrinth/ModrinthPackExportTask.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp index cbdfd04f0..50f6a33c6 100644 --- a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp +++ b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp @@ -301,10 +301,10 @@ QByteArray ModrinthPackExportTask::generateIndex() const ResolvedFile& value = iterator.value(); // detect disabled mod - QString disabledSuffix = ".disabled"; - if (path.endsWith(disabledSuffix)) { + const QFileInfo pathInfo(path); + if (pathInfo.suffix() == "disabled") { // rename it - path = path.left(path.length() - disabledSuffix.length()); + path = pathInfo.dir().filePath(pathInfo.completeBaseName()); // ...and make it optional QJsonObject env; env["client"] = "optional"; From 8e4de055b841a6a2ca93b758344ddb72d2ea0f59 Mon Sep 17 00:00:00 2001 From: seth Date: Sun, 9 Jul 2023 15:19:11 -0400 Subject: [PATCH 142/216] chore(actions): only run update-flake in our repo Signed-off-by: seth --- .github/workflows/update-flake.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/update-flake.yml b/.github/workflows/update-flake.yml index e79040ab4..ad22120ee 100644 --- a/.github/workflows/update-flake.yml +++ b/.github/workflows/update-flake.yml @@ -12,6 +12,7 @@ permissions: jobs: update-flake: + if: github.repository == 'PrismLauncher/PrismLauncher' runs-on: ubuntu-latest steps: From 159f14c0768a1cd8ab99b8a46f2021d163e6740c Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sun, 9 Jul 2023 22:47:38 +0300 Subject: [PATCH 143/216] feat:unlocked versions page Signed-off-by: Trial97 --- launcher/ui/pages/instance/VersionPage.cpp | 315 ++++++++------------- launcher/ui/pages/instance/VersionPage.h | 55 ++-- 2 files changed, 139 insertions(+), 231 deletions(-) diff --git a/launcher/ui/pages/instance/VersionPage.cpp b/launcher/ui/pages/instance/VersionPage.cpp index 59107c53a..7db1b19f6 100644 --- a/launcher/ui/pages/instance/VersionPage.cpp +++ b/launcher/ui/pages/instance/VersionPage.cpp @@ -40,14 +40,13 @@ #include "Application.h" -#include -#include +#include #include #include -#include -#include -#include +#include #include +#include +#include #include #include @@ -55,49 +54,42 @@ #include "ui_VersionPage.h" #include "ui/dialogs/CustomMessageBox.h" -#include "ui/dialogs/VersionSelectDialog.h" #include "ui/dialogs/NewComponentDialog.h" #include "ui/dialogs/ProgressDialog.h" +#include "ui/dialogs/VersionSelectDialog.h" #include "ui/GuiUtil.h" +#include "DesktopServices.h" +#include "Exception.h" +#include "Version.h" +#include "icons/IconList.h" #include "minecraft/PackProfile.h" #include "minecraft/auth/AccountList.h" #include "minecraft/mod/Mod.h" -#include "icons/IconList.h" -#include "Exception.h" -#include "Version.h" -#include "DesktopServices.h" #include "meta/Index.h" #include "meta/VersionList.h" -class IconProxy : public QIdentityProxyModel -{ +class IconProxy : public QIdentityProxyModel { Q_OBJECT -public: - - IconProxy(QWidget *parentWidget) : QIdentityProxyModel(parentWidget) + public: + IconProxy(QWidget* parentWidget) : QIdentityProxyModel(parentWidget) { connect(parentWidget, &QObject::destroyed, this, &IconProxy::widgetGone); m_parentWidget = parentWidget; } - virtual QVariant data(const QModelIndex &proxyIndex, int role = Qt::DisplayRole) const override + virtual QVariant data(const QModelIndex& proxyIndex, int role = Qt::DisplayRole) const override { QVariant var = QIdentityProxyModel::data(proxyIndex, role); int column = proxyIndex.column(); - if(column == 0 && role == Qt::DecorationRole && m_parentWidget) - { - if(!var.isNull()) - { + if (column == 0 && role == Qt::DecorationRole && m_parentWidget) { + if (!var.isNull()) { auto string = var.toString(); - if(string == "warning") - { + if (string == "warning") { return APPLICATION->getThemedIcon("status-yellow"); - } - else if(string == "error") - { + } else if (string == "error") { return APPLICATION->getThemedIcon("status-bad"); } } @@ -105,14 +97,11 @@ public: } return var; } -private slots: - void widgetGone() - { - m_parentWidget = nullptr; - } + private slots: + void widgetGone() { m_parentWidget = nullptr; } -private: - QWidget *m_parentWidget = nullptr; + private: + QWidget* m_parentWidget = nullptr; }; QIcon VersionPage::icon() const @@ -144,15 +133,14 @@ void VersionPage::closedImpl() m_wide_bar_setting->set(ui->toolBar->getVisibilityState()); } -QMenu * VersionPage::createPopupMenu() +QMenu* VersionPage::createPopupMenu() { QMenu* filteredMenu = QMainWindow::createPopupMenu(); - filteredMenu->removeAction( ui->toolBar->toggleViewAction() ); + filteredMenu->removeAction(ui->toolBar->toggleViewAction()); return filteredMenu; } -VersionPage::VersionPage(MinecraftInstance *inst, QWidget *parent) - : QMainWindow(parent), ui(new Ui::VersionPage), m_inst(inst) +VersionPage::VersionPage(MinecraftInstance* inst, QWidget* parent) : QMainWindow(parent), ui(new Ui::VersionPage), m_inst(inst) { ui->setupUi(this); @@ -182,10 +170,8 @@ VersionPage::VersionPage(MinecraftInstance *inst, QWidget *parent) connect(smodel, &QItemSelectionModel::currentChanged, this, &VersionPage::packageCurrent); connect(m_profile.get(), &PackProfile::minecraftChanged, this, &VersionPage::updateVersionControls); - controlsEnabled = !m_inst->isRunning(); updateVersionControls(); preselect(0); - connect(m_inst, &BaseInstance::runningStatusChanged, this, &VersionPage::updateRunningStatus); connect(ui->packageView, &ModListView::customContextMenuRequested, this, &VersionPage::showContextMenu); connect(ui->filterEdit, &QLineEdit::textChanged, this, &VersionPage::onFilterTextChanged); } @@ -202,18 +188,16 @@ void VersionPage::showContextMenu(const QPoint& pos) delete menu; } -void VersionPage::packageCurrent(const QModelIndex ¤t, const QModelIndex &previous) +void VersionPage::packageCurrent(const QModelIndex& current, const QModelIndex& previous) { - if (!current.isValid()) - { + if (!current.isValid()) { ui->frame->clear(); return; } int row = current.row(); auto patch = m_profile->getComponent(row); auto severity = patch->getProblemSeverity(); - switch(severity) - { + switch (severity) { case ProblemSeverity::Warning: ui->frame->setName(tr("%1 possibly has issues.").arg(patch->getName())); break; @@ -226,16 +210,12 @@ void VersionPage::packageCurrent(const QModelIndex ¤t, const QModelIndex & return; } - auto &problems = patch->getProblems(); + auto& problems = patch->getProblems(); QString problemOut; - for (auto &problem: problems) - { - if(problem.m_severity == ProblemSeverity::Error) - { + for (auto& problem : problems) { + if (problem.m_severity == ProblemSeverity::Error) { problemOut += tr("Error: "); - } - else if(problem.m_severity == ProblemSeverity::Warning) - { + } else if (problem.m_severity == ProblemSeverity::Warning) { problemOut += tr("Warning: "); } problemOut += problem.m_description; @@ -244,71 +224,56 @@ void VersionPage::packageCurrent(const QModelIndex ¤t, const QModelIndex & ui->frame->setDescription(problemOut); } -void VersionPage::updateRunningStatus(bool running) -{ - if(controlsEnabled == running) { - controlsEnabled = !running; - updateVersionControls(); - } -} - void VersionPage::updateVersionControls() { // FIXME: this is a dirty hack auto minecraftVersion = Version(m_profile->getComponentVersion("net.minecraft")); - ui->actionInstall_Forge->setEnabled(controlsEnabled); + ui->actionInstall_Forge->setEnabled(true); bool supportsFabric = minecraftVersion >= Version("1.14"); - ui->actionInstall_Fabric->setEnabled(controlsEnabled && supportsFabric); + ui->actionInstall_Fabric->setEnabled(supportsFabric); bool supportsQuilt = minecraftVersion >= Version("1.14"); - ui->actionInstall_Quilt->setEnabled(controlsEnabled && supportsQuilt); + ui->actionInstall_Quilt->setEnabled(supportsQuilt); bool supportsLiteLoader = minecraftVersion <= Version("1.12.2"); - ui->actionInstall_LiteLoader->setEnabled(controlsEnabled && supportsLiteLoader); + ui->actionInstall_LiteLoader->setEnabled(supportsLiteLoader); updateButtons(); } void VersionPage::updateButtons(int row) { - if(row == -1) + if (row == -1) row = currentRow(); auto patch = m_profile->getComponent(row); - ui->actionRemove->setEnabled(controlsEnabled && patch && patch->isRemovable()); - ui->actionMove_down->setEnabled(controlsEnabled && patch && patch->isMoveable()); - ui->actionMove_up->setEnabled(controlsEnabled && patch && patch->isMoveable()); - ui->actionChange_version->setEnabled(controlsEnabled && patch && patch->isVersionChangeable()); - ui->actionEdit->setEnabled(controlsEnabled && patch && patch->isCustom()); - ui->actionCustomize->setEnabled(controlsEnabled && patch && patch->isCustomizable()); - ui->actionRevert->setEnabled(controlsEnabled && patch && patch->isRevertible()); - ui->actionDownload_All->setEnabled(controlsEnabled); - ui->actionAdd_Empty->setEnabled(controlsEnabled); - ui->actionImport_Components->setEnabled(controlsEnabled); - ui->actionReload->setEnabled(controlsEnabled); - ui->actionReplace_Minecraft_jar->setEnabled(controlsEnabled); - ui->actionAdd_to_Minecraft_jar->setEnabled(controlsEnabled); - ui->actionAdd_Agents->setEnabled(controlsEnabled); + ui->actionRemove->setEnabled(patch && patch->isRemovable()); + ui->actionMove_down->setEnabled(patch && patch->isMoveable()); + ui->actionMove_up->setEnabled(patch && patch->isMoveable()); + ui->actionChange_version->setEnabled(patch && patch->isVersionChangeable()); + ui->actionEdit->setEnabled(patch && patch->isCustom()); + ui->actionCustomize->setEnabled(patch && patch->isCustomizable()); + ui->actionRevert->setEnabled(patch && patch->isRevertible()); + ui->actionDownload_All->setEnabled(true); + ui->actionAdd_Empty->setEnabled(true); + ui->actionImport_Components->setEnabled(true); + ui->actionReload->setEnabled(true); + ui->actionReplace_Minecraft_jar->setEnabled(true); + ui->actionAdd_to_Minecraft_jar->setEnabled(true); + ui->actionAdd_Agents->setEnabled(true); } bool VersionPage::reloadPackProfile() { - try - { + try { m_profile->reload(Net::Mode::Online); return true; - } - catch (const Exception &e) - { + } catch (const Exception& e) { QMessageBox::critical(this, tr("Error"), e.cause()); return false; - } - catch (...) - { - QMessageBox::critical( - this, tr("Error"), - tr("Couldn't load the instance profile.")); + } catch (...) { + QMessageBox::critical(this, tr("Error"), tr("Couldn't load the instance profile.")); return false; } } @@ -321,14 +286,12 @@ void VersionPage::on_actionReload_triggered() void VersionPage::on_actionRemove_triggered() { - if (!ui->packageView->currentIndex().isValid()) - { + if (!ui->packageView->currentIndex().isValid()) { return; } int index = ui->packageView->currentIndex().row(); auto component = m_profile->getComponent(index); - if (component->isCustom()) - { + if (component->isCustom()) { auto response = CustomMessageBox::selectable(this, tr("Confirm Removal"), tr("You are about to remove \"%1\".\n" "This is permanent and will completely remove the custom component.\n\n" @@ -341,8 +304,7 @@ void VersionPage::on_actionRemove_triggered() return; } // FIXME: use actual model, not reloading. - if (!m_profile->remove(index)) - { + if (!m_profile->remove(index)) { QMessageBox::critical(this, tr("Error"), tr("Couldn't remove file")); } updateButtons(); @@ -352,17 +314,16 @@ void VersionPage::on_actionRemove_triggered() void VersionPage::on_actionInstall_mods_triggered() { - if(m_container) - { + if (m_container) { m_container->selectPage("mods"); } } void VersionPage::on_actionAdd_to_Minecraft_jar_triggered() { - auto list = GuiUtil::BrowseForFiles("jarmod", tr("Select jar mods"), tr("Minecraft.jar mods (*.zip *.jar)"), APPLICATION->settings()->get("CentralModsDir").toString(), this->parentWidget()); - if(!list.empty()) - { + auto list = GuiUtil::BrowseForFiles("jarmod", tr("Select jar mods"), tr("Minecraft.jar mods (*.zip *.jar)"), + APPLICATION->settings()->get("CentralModsDir").toString(), this->parentWidget()); + if (!list.empty()) { m_profile->installJarMods(list); } updateButtons(); @@ -370,9 +331,9 @@ void VersionPage::on_actionAdd_to_Minecraft_jar_triggered() void VersionPage::on_actionReplace_Minecraft_jar_triggered() { - auto jarPath = GuiUtil::BrowseForFile("jar", tr("Select jar"), tr("Minecraft.jar replacement (*.jar)"), APPLICATION->settings()->get("CentralModsDir").toString(), this->parentWidget()); - if(!jarPath.isEmpty()) - { + auto jarPath = GuiUtil::BrowseForFile("jar", tr("Select jar"), tr("Minecraft.jar replacement (*.jar)"), + APPLICATION->settings()->get("CentralModsDir").toString(), this->parentWidget()); + if (!jarPath.isEmpty()) { m_profile->installCustomJar(jarPath); } updateButtons(); @@ -406,12 +367,9 @@ void VersionPage::on_actionAdd_Agents_triggered() void VersionPage::on_actionMove_up_triggered() { - try - { + try { m_profile->move(currentRow(), PackProfile::MoveUp); - } - catch (const Exception &e) - { + } catch (const Exception& e) { QMessageBox::critical(this, tr("Error"), e.cause()); } updateButtons(); @@ -419,12 +377,9 @@ void VersionPage::on_actionMove_up_triggered() void VersionPage::on_actionMove_down_triggered() { - try - { + try { m_profile->move(currentRow(), PackProfile::MoveDown); - } - catch (const Exception &e) - { + } catch (const Exception& e) { QMessageBox::critical(this, tr("Error"), e.cause()); } updateButtons(); @@ -433,39 +388,32 @@ void VersionPage::on_actionMove_down_triggered() void VersionPage::on_actionChange_version_triggered() { auto versionRow = currentRow(); - if(versionRow == -1) - { + if (versionRow == -1) { return; } auto patch = m_profile->getComponent(versionRow); auto name = patch->getName(); auto list = patch->getVersionList(); - if(!list) - { + if (!list) { return; } auto uid = list->uid(); // FIXME: this is a horrible HACK. Get version filtering information from the actual metadata... - if(uid == "net.minecraftforge") - { + if (uid == "net.minecraftforge") { on_actionInstall_Forge_triggered(); return; - } - else if (uid == "com.mumfrey.liteloader") - { + } else if (uid == "com.mumfrey.liteloader") { on_actionInstall_LiteLoader_triggered(); return; } VersionSelectDialog vselect(list.get(), tr("Change %1 version").arg(name), this); - if (uid == "net.fabricmc.intermediary" || uid == "org.quiltmc.hashed") - { + if (uid == "net.fabricmc.intermediary" || uid == "org.quiltmc.hashed") { vselect.setEmptyString(tr("No intermediary mappings versions are currently available.")); vselect.setEmptyErrorString(tr("Couldn't load or download the intermediary mappings version lists!")); vselect.setExactFilter(BaseVersionList::ParentVersionRole, m_profile->getComponentVersion("net.minecraft")); } auto currentVersion = patch->getVersion(); - if(!currentVersion.isEmpty()) - { + if (!currentVersion.isEmpty()) { vselect.setCurrentVersion(currentVersion); } if (!vselect.exec() || !vselect.selectedVersion()) @@ -473,8 +421,7 @@ void VersionPage::on_actionChange_version_triggered() qDebug() << "Change" << uid << "to" << vselect.selectedVersion()->descriptor(); bool important = false; - if(uid == "net.minecraft") - { + if (uid == "net.minecraft") { important = true; } m_profile->setComponentVersion(uid, vselect.selectedVersion()->descriptor(), important); @@ -484,19 +431,17 @@ void VersionPage::on_actionChange_version_triggered() void VersionPage::on_actionDownload_All_triggered() { - if (!APPLICATION->accounts()->anyAccountIsValid()) - { - CustomMessageBox::selectable( - this, tr("Error"), - tr("Cannot download Minecraft or update instances unless you have at least " - "one account added.\nPlease add your Mojang or Minecraft account."), - QMessageBox::Warning)->show(); + if (!APPLICATION->accounts()->anyAccountIsValid()) { + CustomMessageBox::selectable(this, tr("Error"), + tr("Cannot download Minecraft or update instances unless you have at least " + "one account added.\nPlease add your Mojang or Minecraft account."), + QMessageBox::Warning) + ->show(); return; } auto updateTask = m_inst->createUpdateTask(Net::Mode::Online); - if (!updateTask) - { + if (!updateTask) { return; } ProgressDialog tDialog(this); @@ -510,28 +455,26 @@ void VersionPage::on_actionDownload_All_triggered() void VersionPage::on_actionInstall_Forge_triggered() { auto vlist = APPLICATION->metadataIndex()->get("net.minecraftforge"); - if(!vlist) - { + if (!vlist) { return; } VersionSelectDialog vselect(vlist.get(), tr("Select Forge version"), this); vselect.setExactFilter(BaseVersionList::ParentVersionRole, m_profile->getComponentVersion("net.minecraft")); - vselect.setEmptyString(tr("No Forge versions are currently available for Minecraft ") + m_profile->getComponentVersion("net.minecraft")); + vselect.setEmptyString(tr("No Forge versions are currently available for Minecraft ") + + m_profile->getComponentVersion("net.minecraft")); vselect.setEmptyErrorString(tr("Couldn't load or download the Forge version lists!")); auto currentVersion = m_profile->getComponentVersion("net.minecraftforge"); - if(!currentVersion.isEmpty()) - { + if (!currentVersion.isEmpty()) { vselect.setCurrentVersion(currentVersion); } - if (vselect.exec() && vselect.selectedVersion()) - { + if (vselect.exec() && vselect.selectedVersion()) { auto vsn = vselect.selectedVersion(); m_profile->setComponentVersion("net.minecraftforge", vsn->descriptor()); m_profile->resolve(Net::Mode::Online); // m_profile->installVersion(); - preselect(m_profile->rowCount(QModelIndex())-1); + preselect(m_profile->rowCount(QModelIndex()) - 1); m_container->refreshContainer(); } } @@ -539,8 +482,7 @@ void VersionPage::on_actionInstall_Forge_triggered() void VersionPage::on_actionInstall_Fabric_triggered() { auto vlist = APPLICATION->metadataIndex()->get("net.fabricmc.fabric-loader"); - if(!vlist) - { + if (!vlist) { return; } VersionSelectDialog vselect(vlist.get(), tr("Select Fabric Loader version"), this); @@ -548,17 +490,15 @@ void VersionPage::on_actionInstall_Fabric_triggered() vselect.setEmptyErrorString(tr("Couldn't load or download the Fabric Loader version lists!")); auto currentVersion = m_profile->getComponentVersion("net.fabricmc.fabric-loader"); - if(!currentVersion.isEmpty()) - { + if (!currentVersion.isEmpty()) { vselect.setCurrentVersion(currentVersion); } - if (vselect.exec() && vselect.selectedVersion()) - { + if (vselect.exec() && vselect.selectedVersion()) { auto vsn = vselect.selectedVersion(); m_profile->setComponentVersion("net.fabricmc.fabric-loader", vsn->descriptor()); m_profile->resolve(Net::Mode::Online); - preselect(m_profile->rowCount(QModelIndex())-1); + preselect(m_profile->rowCount(QModelIndex()) - 1); m_container->refreshContainer(); } } @@ -566,8 +506,7 @@ void VersionPage::on_actionInstall_Fabric_triggered() void VersionPage::on_actionInstall_Quilt_triggered() { auto vlist = APPLICATION->metadataIndex()->get("org.quiltmc.quilt-loader"); - if(!vlist) - { + if (!vlist) { return; } VersionSelectDialog vselect(vlist.get(), tr("Select Quilt Loader version"), this); @@ -575,17 +514,15 @@ void VersionPage::on_actionInstall_Quilt_triggered() vselect.setEmptyErrorString(tr("Couldn't load or download the Quilt Loader version lists!")); auto currentVersion = m_profile->getComponentVersion("org.quiltmc.quilt-loader"); - if(!currentVersion.isEmpty()) - { + if (!currentVersion.isEmpty()) { vselect.setCurrentVersion(currentVersion); } - if (vselect.exec() && vselect.selectedVersion()) - { + if (vselect.exec() && vselect.selectedVersion()) { auto vsn = vselect.selectedVersion(); m_profile->setComponentVersion("org.quiltmc.quilt-loader", vsn->descriptor()); m_profile->resolve(Net::Mode::Online); - preselect(m_profile->rowCount(QModelIndex())-1); + preselect(m_profile->rowCount(QModelIndex()) - 1); m_container->refreshContainer(); } } @@ -594,14 +531,12 @@ void VersionPage::on_actionAdd_Empty_triggered() { NewComponentDialog compdialog(QString(), QString(), this); QStringList blacklist; - for(int i = 0; i < m_profile->rowCount(); i++) - { + for (int i = 0; i < m_profile->rowCount(); i++) { auto comp = m_profile->getComponent(i); blacklist.push_back(comp->getID()); } compdialog.setBlacklist(blacklist); - if (compdialog.exec()) - { + if (compdialog.exec()) { qDebug() << "name:" << compdialog.name(); qDebug() << "uid:" << compdialog.uid(); m_profile->installEmpty(compdialog.uid(), compdialog.name()); @@ -611,28 +546,26 @@ void VersionPage::on_actionAdd_Empty_triggered() void VersionPage::on_actionInstall_LiteLoader_triggered() { auto vlist = APPLICATION->metadataIndex()->get("com.mumfrey.liteloader"); - if(!vlist) - { + if (!vlist) { return; } VersionSelectDialog vselect(vlist.get(), tr("Select LiteLoader version"), this); vselect.setExactFilter(BaseVersionList::ParentVersionRole, m_profile->getComponentVersion("net.minecraft")); - vselect.setEmptyString(tr("No LiteLoader versions are currently available for Minecraft ") + m_profile->getComponentVersion("net.minecraft")); + vselect.setEmptyString(tr("No LiteLoader versions are currently available for Minecraft ") + + m_profile->getComponentVersion("net.minecraft")); vselect.setEmptyErrorString(tr("Couldn't load or download the LiteLoader version lists!")); auto currentVersion = m_profile->getComponentVersion("com.mumfrey.liteloader"); - if(!currentVersion.isEmpty()) - { + if (!currentVersion.isEmpty()) { vselect.setCurrentVersion(currentVersion); } - if (vselect.exec() && vselect.selectedVersion()) - { + if (vselect.exec() && vselect.selectedVersion()) { auto vsn = vselect.selectedVersion(); m_profile->setComponentVersion("com.mumfrey.liteloader", vsn->descriptor()); m_profile->resolve(Net::Mode::Online); // m_profile->installVersion(vselect.selectedVersion()); - preselect(m_profile->rowCount(QModelIndex())-1); + preselect(m_profile->rowCount(QModelIndex()) - 1); m_container->refreshContainer(); } } @@ -647,7 +580,7 @@ void VersionPage::on_actionMinecraftFolder_triggered() DesktopServices::openDirectory(m_inst->gameRoot(), true); } -void VersionPage::versionCurrent(const QModelIndex ¤t, const QModelIndex &previous) +void VersionPage::versionCurrent(const QModelIndex& current, const QModelIndex& previous) { currentIdx = current.row(); updateButtons(currentIdx); @@ -655,16 +588,13 @@ void VersionPage::versionCurrent(const QModelIndex ¤t, const QModelIndex & void VersionPage::preselect(int row) { - if(row < 0) - { + if (row < 0) { row = 0; } - if(row >= m_profile->rowCount(QModelIndex())) - { + if (row >= m_profile->rowCount(QModelIndex())) { row = m_profile->rowCount(QModelIndex()) - 1; } - if(row < 0) - { + if (row < 0) { return; } auto model_index = m_profile->index(row); @@ -680,8 +610,7 @@ void VersionPage::onGameUpdateError(QString error) ComponentPtr VersionPage::current() { auto row = currentRow(); - if(row < 0) - { + if (row < 0) { return nullptr; } return m_profile->getComponent(row); @@ -689,8 +618,7 @@ ComponentPtr VersionPage::current() int VersionPage::currentRow() { - if (ui->packageView->selectionModel()->selectedRows().isEmpty()) - { + if (ui->packageView->selectionModel()->selectedRows().isEmpty()) { return -1; } return ui->packageView->selectionModel()->selectedRows().first().row(); @@ -699,18 +627,15 @@ int VersionPage::currentRow() void VersionPage::on_actionCustomize_triggered() { auto version = currentRow(); - if(version == -1) - { + if (version == -1) { return; } auto patch = m_profile->getComponent(version); - if(!patch->getVersionFile()) - { + if (!patch->getVersionFile()) { // TODO: wait for the update task to finish here... return; } - if(!m_profile->customize(version)) - { + if (!m_profile->customize(version)) { // TODO: some error box here } updateButtons(); @@ -720,13 +645,11 @@ void VersionPage::on_actionCustomize_triggered() void VersionPage::on_actionEdit_triggered() { auto version = current(); - if(!version) - { + if (!version) { return; } auto filename = version->getFilename(); - if(!QFileInfo::exists(filename)) - { + if (!QFileInfo::exists(filename)) { qWarning() << "file" << filename << "can't be opened for editing, doesn't exist!"; return; } @@ -736,8 +659,7 @@ void VersionPage::on_actionEdit_triggered() void VersionPage::on_actionRevert_triggered() { auto version = currentRow(); - if(version == -1) - { + if (version == -1) { return; } auto component = m_profile->getComponent(version); @@ -753,8 +675,7 @@ void VersionPage::on_actionRevert_triggered() if (response != QMessageBox::Yes) return; - if(!m_profile->revertToBase(version)) - { + if (!m_profile->revertToBase(version)) { // TODO: some error box here } updateButtons(); @@ -762,7 +683,7 @@ void VersionPage::on_actionRevert_triggered() m_container->refreshContainer(); } -void VersionPage::onFilterTextChanged(const QString &newContents) +void VersionPage::onFilterTextChanged(const QString& newContents) { m_filterModel->setFilterFixedString(newContents); } diff --git a/launcher/ui/pages/instance/VersionPage.h b/launcher/ui/pages/instance/VersionPage.h index d00877142..45d383f41 100644 --- a/launcher/ui/pages/instance/VersionPage.h +++ b/launcher/ui/pages/instance/VersionPage.h @@ -46,38 +46,27 @@ #include "minecraft/PackProfile.h" #include "ui/pages/BasePage.h" -namespace Ui -{ +namespace Ui { class VersionPage; } -class VersionPage : public QMainWindow, public BasePage -{ +class VersionPage : public QMainWindow, public BasePage { Q_OBJECT -public: - explicit VersionPage(MinecraftInstance *inst, QWidget *parent = 0); + public: + explicit VersionPage(MinecraftInstance* inst, QWidget* parent = 0); virtual ~VersionPage(); - virtual QString displayName() const override - { - return tr("Version"); - } + virtual QString displayName() const override { return tr("Version"); } virtual QIcon icon() const override; - virtual QString id() const override - { - return "version"; - } - virtual QString helpPage() const override - { - return "Instance-Version"; - } + virtual QString id() const override { return "version"; } + virtual QString helpPage() const override { return "Instance-Version"; } virtual bool shouldDisplay() const override; void retranslate() override; void openedImpl() override; void closedImpl() override; -private slots: + private slots: void on_actionChange_version_triggered(); void on_actionInstall_Forge_triggered(); void on_actionInstall_Fabric_triggered(); @@ -103,36 +92,34 @@ private slots: void updateVersionControls(); -private: + private: ComponentPtr current(); int currentRow(); void updateButtons(int row = -1); void preselect(int row = 0); int doUpdate(); -protected: - QMenu * createPopupMenu() override; + protected: + QMenu* createPopupMenu() override; /// FIXME: this shouldn't be necessary! bool reloadPackProfile(); -private: - Ui::VersionPage *ui; - QSortFilterProxyModel *m_filterModel; + private: + Ui::VersionPage* ui; + QSortFilterProxyModel* m_filterModel; std::shared_ptr m_profile; - MinecraftInstance *m_inst; + MinecraftInstance* m_inst; int currentIdx = 0; - bool controlsEnabled = false; std::shared_ptr m_wide_bar_setting = nullptr; -public slots: - void versionCurrent(const QModelIndex ¤t, const QModelIndex &previous); + public slots: + void versionCurrent(const QModelIndex& current, const QModelIndex& previous); -private slots: - void updateRunningStatus(bool running); + private slots: void onGameUpdateError(QString error); - void packageCurrent(const QModelIndex ¤t, const QModelIndex &previous); - void showContextMenu(const QPoint &pos); - void onFilterTextChanged(const QString & newContents); + void packageCurrent(const QModelIndex& current, const QModelIndex& previous); + void showContextMenu(const QPoint& pos); + void onFilterTextChanged(const QString& newContents); }; From 308877aa8f105de408c4c8fe87d3476116b23cf4 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sun, 9 Jul 2023 23:18:38 +0300 Subject: [PATCH 144/216] removed redundant code Signed-off-by: Trial97 --- launcher/ui/pages/instance/VersionPage.cpp | 9 --------- 1 file changed, 9 deletions(-) diff --git a/launcher/ui/pages/instance/VersionPage.cpp b/launcher/ui/pages/instance/VersionPage.cpp index 7db1b19f6..a180c8041 100644 --- a/launcher/ui/pages/instance/VersionPage.cpp +++ b/launcher/ui/pages/instance/VersionPage.cpp @@ -229,8 +229,6 @@ void VersionPage::updateVersionControls() // FIXME: this is a dirty hack auto minecraftVersion = Version(m_profile->getComponentVersion("net.minecraft")); - ui->actionInstall_Forge->setEnabled(true); - bool supportsFabric = minecraftVersion >= Version("1.14"); ui->actionInstall_Fabric->setEnabled(supportsFabric); @@ -255,13 +253,6 @@ void VersionPage::updateButtons(int row) ui->actionEdit->setEnabled(patch && patch->isCustom()); ui->actionCustomize->setEnabled(patch && patch->isCustomizable()); ui->actionRevert->setEnabled(patch && patch->isRevertible()); - ui->actionDownload_All->setEnabled(true); - ui->actionAdd_Empty->setEnabled(true); - ui->actionImport_Components->setEnabled(true); - ui->actionReload->setEnabled(true); - ui->actionReplace_Minecraft_jar->setEnabled(true); - ui->actionAdd_to_Minecraft_jar->setEnabled(true); - ui->actionAdd_Agents->setEnabled(true); } bool VersionPage::reloadPackProfile() From 99ba02afb6a7af1bc0800552338ab811b027eb9e Mon Sep 17 00:00:00 2001 From: Nathan Date: Mon, 10 Jul 2023 11:26:25 -0700 Subject: [PATCH 145/216] Shortcuts on macOS (#1081) Co-authored-by: TheKodeToad --- launcher/FileSystem.cpp | 60 ++++++++++++++++++++++++++++++++++++-- launcher/ui/MainWindow.cpp | 44 ++++++++++++++++++++++++---- 2 files changed, 96 insertions(+), 8 deletions(-) diff --git a/launcher/FileSystem.cpp b/launcher/FileSystem.cpp index 812d45eb5..4538702f2 100644 --- a/launcher/FileSystem.cpp +++ b/launcher/FileSystem.cpp @@ -778,9 +778,43 @@ bool createShortcut(QString destination, QString target, QStringList args, QStri destination = PathCombine(getDesktopDir(), RemoveInvalidFilenameChars(name)); } #if defined(Q_OS_MACOS) - destination += ".command"; + // Create the Application + QDir applicationDirectory = QStandardPaths::writableLocation(QStandardPaths::ApplicationsLocation) + "/" + BuildConfig.LAUNCHER_NAME + " Instances/"; - QFile f(destination); + if (!applicationDirectory.mkpath(".")) { + qWarning() << "Couldn't create application directory"; + return false; + } + + QDir application = applicationDirectory.path() + "/" + name + ".app/"; + + if (application.exists()) { + qWarning() << "Application already exists!"; + return false; + } + + if (!application.mkpath(".")) { + qWarning() << "Couldn't create application"; + return false; + } + + QDir content = application.path() + "/Contents/"; + QDir resources = content.path() + "/Resources/"; + QDir binaryDir = content.path() + "/MacOS/"; + QFile info = content.path() + "/Info.plist"; + + if (!(content.mkpath(".") && resources.mkpath(".") && binaryDir.mkpath("."))) { + qWarning() << "Couldn't create directories within application"; + return false; + } + info.open(QIODevice::WriteOnly | QIODevice::Text); + + QFile(icon).rename(resources.path() + "/Icon.icns"); + + // Create the Command file + QString exec = binaryDir.path() + "/Run.command"; + + QFile f(exec); f.open(QIODevice::WriteOnly | QIODevice::Text); QTextStream stream(&f); @@ -797,6 +831,28 @@ bool createShortcut(QString destination, QString target, QStringList args, QStri f.setPermissions(f.permissions() | QFileDevice::ExeOwner | QFileDevice::ExeGroup | QFileDevice::ExeOther); + // Generate the Info.plist + QTextStream infoStream(&info); + infoStream << " \n" + "" + "\n" + "\n" + " CFBundleExecutable\n" + " Run.command\n" // The path to the executable + " CFBundleIconFile\n" + " Icon.icns\n" + " CFBundleName\n" + " " << name << "\n" // Name of the application + " CFBundlePackageType\n" + " APPL\n" + " CFBundleShortVersionString\n" + " 1.0\n" + " CFBundleVersion\n" + " 1.0\n" + "\n" + ""; + return true; #elif defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) || defined(Q_OS_OPENBSD) if (!destination.endsWith(".desktop")) // in case of isFlatpak destination is already populated diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp index 2f944472e..fe3649379 100644 --- a/launcher/ui/MainWindow.cpp +++ b/launcher/ui/MainWindow.cpp @@ -1536,11 +1536,39 @@ void MainWindow::on_actionCreateInstanceShortcut_triggered() QString iconPath; QStringList args; #if defined(Q_OS_MACOS) - if (appPath.startsWith("/private/var/")) { - QMessageBox::critical(this, tr("Create instance shortcut"), - tr("The launcher is in the folder it was extracted from, therefore it cannot create shortcuts.")); - return; - } + appPath = QApplication::applicationFilePath(); + if (appPath.startsWith("/private/var/")) { + QMessageBox::critical(this, tr("Create instance shortcut"), + tr("The launcher is in the folder it was extracted from, therefore it cannot create shortcuts.")); + return; + } + + auto pIcon = APPLICATION->icons()->icon(m_selectedInstance->iconKey()); + if (pIcon == nullptr) + { + pIcon = APPLICATION->icons()->icon("grass"); + } + + iconPath = FS::PathCombine(m_selectedInstance->instanceRoot(), "Icon.icns"); + + QFile iconFile(iconPath); + if (!iconFile.open(QFile::WriteOnly)) + { + QMessageBox::critical(this, tr("Create instance Application"), tr("Failed to create icon for Application.")); + return; + } + + QIcon icon = pIcon->icon(); + + bool success = icon.pixmap(1024, 1024).save(iconPath, "ICNS"); + iconFile.close(); + + if (!success) + { + iconFile.remove(); + QMessageBox::critical(this, tr("Create instance Application"), tr("Failed to create icon for Application.")); + return; + } #elif defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) || defined(Q_OS_OPENBSD) if (appPath.startsWith("/tmp/.mount_")) { // AppImage! @@ -1623,7 +1651,11 @@ void MainWindow::on_actionCreateInstanceShortcut_triggered() #endif args.append({ "--launch", m_selectedInstance->id() }); if (FS::createShortcut(desktopFilePath, appPath, args, m_selectedInstance->name(), iconPath)) { - QMessageBox::information(this, tr("Create instance shortcut"), tr("Created a shortcut to this instance on your desktop!")); +#if not defined(Q_OS_MACOS) + QMessageBox::information(this, tr("Create instance shortcut"), tr("Created a shortcut to this instance on your desktop!")); +#else + QMessageBox::information(this, tr("Create instance shortcut"), tr("Created a shortcut to this instance!")); +#endif } else { #if not defined(Q_OS_MACOS) iconFile.remove(); From 1aa5fa03f94438ce53899e4660f12e794fd8bc35 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Mon, 10 Jul 2023 12:05:01 -0700 Subject: [PATCH 146/216] Update launcher/ui/MainWindow.cpp Co-authored-by: TheKodeToad Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/ui/MainWindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp index 254f229da..5a8fcc78f 100644 --- a/launcher/ui/MainWindow.cpp +++ b/launcher/ui/MainWindow.cpp @@ -1287,7 +1287,7 @@ void MainWindow::on_actionEditInstance_triggered() APPLICATION->showInstanceWindow(m_selectedInstance); } else { CustomMessageBox::selectable(this, tr("Instance not editable"), - tr("This instance is not editable. it may be broken, invalid, or too old. Check logs for details,"), + tr("This instance is not editable. It may be broken, invalid, or too old. Check logs for details."), QMessageBox::Critical)->show(); } } From f0d2aab784fd0ff0fc495d5f0c44715887741eb1 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Tue, 11 Jul 2023 18:05:43 +0300 Subject: [PATCH 147/216] feat:Added option to use system locale Signed-off-by: Trial97 --- launcher/Application.cpp | 8 ++--- launcher/translations/TranslationsModel.cpp | 29 ++++++++++--------- launcher/translations/TranslationsModel.h | 29 +++++++++---------- .../ui/widgets/LanguageSelectionWidget.cpp | 28 +++++++++++------- launcher/ui/widgets/LanguageSelectionWidget.h | 25 ++++++++-------- 5 files changed, 61 insertions(+), 58 deletions(-) diff --git a/launcher/Application.cpp b/launcher/Application.cpp index 7858d7132..86005ef79 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -568,6 +568,7 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) // Language m_settings->registerSetting("Language", QString()); + m_settings->registerSetting("UseSystemLocales", false); // Console m_settings->registerSetting("ShowConsole", false); @@ -918,12 +919,7 @@ bool Application::createSetupWizard() } return false; }(); - bool languageRequired = [&]() - { - if (settings()->get("Language").toString().isEmpty()) - return true; - return false; - }(); + bool languageRequired = settings()->get("Language").toString().isEmpty(); bool pasteInterventionRequired = settings()->get("PastebinURL") != ""; bool themeInterventionRequired = settings()->get("ApplicationTheme") == ""; bool wizardRequired = javaRequired || languageRequired || pasteInterventionRequired || themeInterventionRequired; diff --git a/launcher/translations/TranslationsModel.cpp b/launcher/translations/TranslationsModel.cpp index 489dff86d..838155a49 100644 --- a/launcher/translations/TranslationsModel.cpp +++ b/launcher/translations/TranslationsModel.cpp @@ -527,34 +527,34 @@ Language * TranslationsModel::findLanguage(const QString& key) } } +void TranslationsModel::setUseSystemLocale(bool useSystemLocale) +{ + APPLICATION->settings()->set("UseSystemLocales", useSystemLocale); + QLocale::setDefault(QLocale(useSystemLocale ? QString::fromStdString(std::locale().name()) : defaultLangCode)); +} + bool TranslationsModel::selectLanguage(QString key) { - QString &langCode = key; + QString& langCode = key; auto langPtr = findLanguage(key); - if (langCode.isEmpty()) - { + if (langCode.isEmpty()) { d->no_language_set = true; } - if(!langPtr) - { + if (!langPtr) { qWarning() << "Selected invalid language" << key << ", defaulting to" << defaultLangCode; langCode = defaultLangCode; - } - else - { + } else { langCode = langPtr->key; } // uninstall existing translators if there are any - if (d->m_app_translator) - { + if (d->m_app_translator) { QCoreApplication::removeTranslator(d->m_app_translator.get()); d->m_app_translator.reset(); } - if (d->m_qt_translator) - { + if (d->m_qt_translator) { QCoreApplication::removeTranslator(d->m_qt_translator.get()); d->m_qt_translator.reset(); } @@ -564,8 +564,9 @@ bool TranslationsModel::selectLanguage(QString key) * In a multithreaded application, the default locale should be set at application startup, before any non-GUI threads are created. * This function is not reentrant. */ - QLocale locale = QLocale(langCode); - QLocale::setDefault(locale); + QLocale::setDefault( + QLocale(APPLICATION->settings()->get("UseSystemLocales").toBool() ? QString::fromStdString(std::locale().name()) : langCode)); + // if it's the default UI language, finish if(langCode == defaultLangCode) diff --git a/launcher/translations/TranslationsModel.h b/launcher/translations/TranslationsModel.h index 3abf84e6e..cff23ce74 100644 --- a/launcher/translations/TranslationsModel.h +++ b/launcher/translations/TranslationsModel.h @@ -20,17 +20,16 @@ struct Language; -class TranslationsModel : public QAbstractListModel -{ +class TranslationsModel : public QAbstractListModel { Q_OBJECT -public: - explicit TranslationsModel(QString path, QObject *parent = 0); + public: + explicit TranslationsModel(QString path, QObject* parent = 0); virtual ~TranslationsModel(); - QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; QVariant headerData(int section, Qt::Orientation orientation, int role) const override; - int rowCount(const QModelIndex &parent = QModelIndex()) const override; - int columnCount(const QModelIndex & parent) const override; + int rowCount(const QModelIndex& parent = QModelIndex()) const override; + int columnCount(const QModelIndex& parent) const override; bool selectLanguage(QString key); void updateLanguage(QString key); @@ -38,27 +37,27 @@ public: QString selectedLanguage(); void downloadIndex(); + void setUseSystemLocale(bool useSystemLocale); -private: - Language *findLanguage(const QString & key); + private: + Language* findLanguage(const QString& key); void reloadLocalFiles(); void downloadTranslation(QString key); void downloadNext(); // hide copy constructor - TranslationsModel(const TranslationsModel &) = delete; + TranslationsModel(const TranslationsModel&) = delete; // hide assign op - TranslationsModel &operator=(const TranslationsModel &) = delete; + TranslationsModel& operator=(const TranslationsModel&) = delete; -private slots: + private slots: void indexReceived(); void indexFailed(QString reason); void dlFailed(QString reason); void dlGood(); - void translationDirChanged(const QString &path); + void translationDirChanged(const QString& path); - -private: /* data */ + private: /* data */ struct Private; std::unique_ptr d; }; diff --git a/launcher/ui/widgets/LanguageSelectionWidget.cpp b/launcher/ui/widgets/LanguageSelectionWidget.cpp index 256b09dad..8b95999d2 100644 --- a/launcher/ui/widgets/LanguageSelectionWidget.cpp +++ b/launcher/ui/widgets/LanguageSelectionWidget.cpp @@ -1,16 +1,16 @@ #include "LanguageSelectionWidget.h" -#include -#include +#include #include #include +#include +#include #include "Application.h" #include "BuildConfig.h" -#include "translations/TranslationsModel.h" #include "settings/Setting.h" +#include "translations/TranslationsModel.h" -LanguageSelectionWidget::LanguageSelectionWidget(QWidget *parent) : - QWidget(parent) +LanguageSelectionWidget::LanguageSelectionWidget(QWidget* parent) : QWidget(parent) { verticalLayout = new QVBoxLayout(this); verticalLayout->setObjectName(QStringLiteral("verticalLayout")); @@ -31,6 +31,13 @@ LanguageSelectionWidget::LanguageSelectionWidget(QWidget *parent) : helpUsLabel->setWordWrap(true); verticalLayout->addWidget(helpUsLabel); + formatCheckbox = new QCheckBox(this); + formatCheckbox->setObjectName(QStringLiteral("formatCheckbox")); + formatCheckbox->setCheckState(APPLICATION->settings()->get("UseSystemLocales").toBool() ? Qt::Checked : Qt::Unchecked); + connect(formatCheckbox, &QCheckBox::stateChanged, + [this]() { APPLICATION->translations()->setUseSystemLocale(formatCheckbox->isChecked()); }); + verticalLayout->addWidget(formatCheckbox); + auto translations = APPLICATION->translations(); auto index = translations->selectedIndex(); languageView->setModel(translations.get()); @@ -38,7 +45,7 @@ LanguageSelectionWidget::LanguageSelectionWidget(QWidget *parent) : languageView->header()->setSectionResizeMode(QHeaderView::ResizeToContents); languageView->header()->setSectionResizeMode(0, QHeaderView::Stretch); connect(languageView->selectionModel(), &QItemSelectionModel::currentRowChanged, this, &LanguageSelectionWidget::languageRowChanged); - verticalLayout->setContentsMargins(0,0,0,0); + verticalLayout->setContentsMargins(0, 0, 0, 0); auto language_setting = APPLICATION->settings()->getSetting("Language"); connect(language_setting.get(), &Setting::SettingChanged, this, &LanguageSelectionWidget::languageSettingChanged); @@ -53,15 +60,14 @@ QString LanguageSelectionWidget::getSelectedLanguageKey() const void LanguageSelectionWidget::retranslate() { QString text = tr("Don't see your language or the quality is poor?
    Help us with translations!") - .arg(BuildConfig.TRANSLATIONS_URL); + .arg(BuildConfig.TRANSLATIONS_URL); helpUsLabel->setText(text); - + formatCheckbox->setText(tr("Use system locales")); } void LanguageSelectionWidget::languageRowChanged(const QModelIndex& current, const QModelIndex& previous) { - if (current == previous) - { + if (current == previous) { return; } auto translations = APPLICATION->translations(); @@ -70,7 +76,7 @@ void LanguageSelectionWidget::languageRowChanged(const QModelIndex& current, con translations->updateLanguage(key); } -void LanguageSelectionWidget::languageSettingChanged(const Setting &, const QVariant) +void LanguageSelectionWidget::languageSettingChanged(const Setting&, const QVariant) { auto translations = APPLICATION->translations(); auto index = translations->selectedIndex(); diff --git a/launcher/ui/widgets/LanguageSelectionWidget.h b/launcher/ui/widgets/LanguageSelectionWidget.h index 4a88924c4..5e86a288f 100644 --- a/launcher/ui/widgets/LanguageSelectionWidget.h +++ b/launcher/ui/widgets/LanguageSelectionWidget.h @@ -21,23 +21,24 @@ class QVBoxLayout; class QTreeView; class QLabel; class Setting; +class QCheckBox; -class LanguageSelectionWidget: public QWidget -{ +class LanguageSelectionWidget : public QWidget { Q_OBJECT -public: - explicit LanguageSelectionWidget(QWidget *parent = 0); - virtual ~LanguageSelectionWidget() { }; + public: + explicit LanguageSelectionWidget(QWidget* parent = 0); + virtual ~LanguageSelectionWidget(){}; QString getSelectedLanguageKey() const; void retranslate(); -protected slots: - void languageRowChanged(const QModelIndex ¤t, const QModelIndex &previous); - void languageSettingChanged(const Setting &, const QVariant); + protected slots: + void languageRowChanged(const QModelIndex& current, const QModelIndex& previous); + void languageSettingChanged(const Setting&, const QVariant); -private: - QVBoxLayout *verticalLayout = nullptr; - QTreeView *languageView = nullptr; - QLabel *helpUsLabel = nullptr; + private: + QVBoxLayout* verticalLayout = nullptr; + QTreeView* languageView = nullptr; + QLabel* helpUsLabel = nullptr; + QCheckBox* formatCheckbox = nullptr; }; From 634612ae816f2c8687efa43aa204b361dc0bc274 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Tue, 11 Jul 2023 18:20:44 +0300 Subject: [PATCH 148/216] added missing header Signed-off-by: Trial97 --- launcher/translations/TranslationsModel.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/launcher/translations/TranslationsModel.cpp b/launcher/translations/TranslationsModel.cpp index 838155a49..e6bc06a64 100644 --- a/launcher/translations/TranslationsModel.cpp +++ b/launcher/translations/TranslationsModel.cpp @@ -42,6 +42,7 @@ #include #include #include +#include #include "FileSystem.h" #include "net/NetJob.h" From 766e833a7386c9b027c02687ce345b985b4a256d Mon Sep 17 00:00:00 2001 From: Trial97 Date: Wed, 12 Jul 2023 16:25:05 +0300 Subject: [PATCH 149/216] fixed crash if no version is loaded Signed-off-by: Trial97 --- .../ui/pages/instance/ManagedPackPage.cpp | 25 +++++++++++++++---- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/launcher/ui/pages/instance/ManagedPackPage.cpp b/launcher/ui/pages/instance/ManagedPackPage.cpp index d89c5bfc0..0fc0c9867 100644 --- a/launcher/ui/pages/instance/ManagedPackPage.cpp +++ b/launcher/ui/pages/instance/ManagedPackPage.cpp @@ -69,7 +69,6 @@ class NoBigComboBoxStyle : public QProxyStyle { private: NoBigComboBoxStyle(QStyle* style) : QProxyStyle(style) {} - }; ManagedPackPage* ManagedPackPage::createPage(BaseInstance* inst, QString type, QWidget* parent) @@ -91,13 +90,13 @@ ManagedPackPage::ManagedPackPage(BaseInstance* inst, InstanceWindow* instance_wi // NOTE: GTK2 themes crash with the proxy style. // This seems like an upstream bug, so there's not much else that can be done. - if (!QStyleFactory::keys().contains("gtk2")){ + if (!QStyleFactory::keys().contains("gtk2")) { auto comboStyle = NoBigComboBoxStyle::getInstance(ui->versionsComboBox->style()); ui->versionsComboBox->setStyle(comboStyle); } ui->reloadButton->setVisible(false); - connect(ui->reloadButton, &QPushButton::clicked, this, [this](bool){ + connect(ui->reloadButton, &QPushButton::clicked, this, [this](bool) { ui->reloadButton->setVisible(false); m_loaded = false; @@ -226,7 +225,8 @@ void ModrinthManagedPackPage::parseManagedPack() QString id = m_inst->getManagedPackID(); - m_fetch_job->addNetAction(Net::Download::makeByteArray(QString("%1/project/%2/version").arg(BuildConfig.MODRINTH_PROD_URL, id), response)); + m_fetch_job->addNetAction( + Net::Download::makeByteArray(QString("%1/project/%2/version").arg(BuildConfig.MODRINTH_PROD_URL, id), response)); QObject::connect(m_fetch_job.get(), &NetJob::succeeded, this, [this, response, id] { QJsonParseError parse_error{}; @@ -267,7 +267,6 @@ void ModrinthManagedPackPage::parseManagedPack() if (version.version == m_inst->getManagedPackVersionName()) name = tr("%1 (Current)").arg(name); - ui->versionsComboBox->addItem(name, QVariant(version.id)); } @@ -291,6 +290,10 @@ QString ModrinthManagedPackPage::url() const void ModrinthManagedPackPage::suggestVersion() { auto index = ui->versionsComboBox->currentIndex(); + if (m_pack.versions.length() == 0) { + setFailState(); + return; + } auto version = m_pack.versions.at(index); ui->changelogTextBrowser->setHtml(markdownToHTML(version.changelog.toUtf8())); @@ -301,6 +304,10 @@ void ModrinthManagedPackPage::suggestVersion() void ModrinthManagedPackPage::update() { auto index = ui->versionsComboBox->currentIndex(); + if (m_pack.versions.length() == 0) { + setFailState(); + return; + } auto version = m_pack.versions.at(index); QMap extra_info; @@ -429,6 +436,10 @@ QString FlameManagedPackPage::url() const void FlameManagedPackPage::suggestVersion() { auto index = ui->versionsComboBox->currentIndex(); + if (m_pack.versions.length() == 0) { + setFailState(); + return; + } auto version = m_pack.versions.at(index); ui->changelogTextBrowser->setHtml(m_api.getModFileChangelog(m_inst->getManagedPackID().toInt(), version.fileId)); @@ -439,6 +450,10 @@ void FlameManagedPackPage::suggestVersion() void FlameManagedPackPage::update() { auto index = ui->versionsComboBox->currentIndex(); + if (m_pack.versions.length() == 0) { + setFailState(); + return; + } auto version = m_pack.versions.at(index); QMap extra_info; From 9ee68b926829495b4b87e7044bd31352ef6a6a84 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Wed, 12 Jul 2023 18:12:31 +0300 Subject: [PATCH 150/216] small pointer check Signed-off-by: Trial97 --- launcher/modplatform/EnsureMetadataTask.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/launcher/modplatform/EnsureMetadataTask.cpp b/launcher/modplatform/EnsureMetadataTask.cpp index 93b5ce76c..d76497007 100644 --- a/launcher/modplatform/EnsureMetadataTask.cpp +++ b/launcher/modplatform/EnsureMetadataTask.cpp @@ -154,7 +154,8 @@ void EnsureMetadataTask::executeTask() connect(version_task.get(), &Task::finished, [=] { version_task->deleteLater(); - m_current_task = nullptr; + if (m_current_task) + m_current_task.reset(); }); if (m_mods.size() > 1) From 25f7cf23d3572e444617c347ade71fffddd8af8b Mon Sep 17 00:00:00 2001 From: Trial97 Date: Wed, 12 Jul 2023 19:55:11 +0300 Subject: [PATCH 151/216] the other place Signed-off-by: Trial97 --- launcher/modplatform/EnsureMetadataTask.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/launcher/modplatform/EnsureMetadataTask.cpp b/launcher/modplatform/EnsureMetadataTask.cpp index d76497007..c3eadd06d 100644 --- a/launcher/modplatform/EnsureMetadataTask.cpp +++ b/launcher/modplatform/EnsureMetadataTask.cpp @@ -145,7 +145,8 @@ void EnsureMetadataTask::executeTask() connect(project_task.get(), &Task::finished, this, [=] { invalidade_leftover(); project_task->deleteLater(); - m_current_task = nullptr; + if (m_current_task) + m_current_task.reset(); }); m_current_task = project_task; From 76cc8ce0437b7047ee984993daab57b2605f52a6 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Wed, 12 Jul 2023 21:05:13 +0300 Subject: [PATCH 152/216] renamed setting Signed-off-by: Trial97 --- launcher/Application.cpp | 2 +- launcher/translations/TranslationsModel.cpp | 4 ++-- launcher/ui/widgets/LanguageSelectionWidget.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/launcher/Application.cpp b/launcher/Application.cpp index 86005ef79..5aa9efc4a 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -568,7 +568,7 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) // Language m_settings->registerSetting("Language", QString()); - m_settings->registerSetting("UseSystemLocales", false); + m_settings->registerSetting("UseSystemLocale", false); // Console m_settings->registerSetting("ShowConsole", false); diff --git a/launcher/translations/TranslationsModel.cpp b/launcher/translations/TranslationsModel.cpp index e6bc06a64..2763cca26 100644 --- a/launcher/translations/TranslationsModel.cpp +++ b/launcher/translations/TranslationsModel.cpp @@ -530,7 +530,7 @@ Language * TranslationsModel::findLanguage(const QString& key) void TranslationsModel::setUseSystemLocale(bool useSystemLocale) { - APPLICATION->settings()->set("UseSystemLocales", useSystemLocale); + APPLICATION->settings()->set("UseSystemLocale", useSystemLocale); QLocale::setDefault(QLocale(useSystemLocale ? QString::fromStdString(std::locale().name()) : defaultLangCode)); } @@ -566,7 +566,7 @@ bool TranslationsModel::selectLanguage(QString key) * This function is not reentrant. */ QLocale::setDefault( - QLocale(APPLICATION->settings()->get("UseSystemLocales").toBool() ? QString::fromStdString(std::locale().name()) : langCode)); + QLocale(APPLICATION->settings()->get("UseSystemLocale").toBool() ? QString::fromStdString(std::locale().name()) : langCode)); // if it's the default UI language, finish diff --git a/launcher/ui/widgets/LanguageSelectionWidget.cpp b/launcher/ui/widgets/LanguageSelectionWidget.cpp index 8b95999d2..37d053478 100644 --- a/launcher/ui/widgets/LanguageSelectionWidget.cpp +++ b/launcher/ui/widgets/LanguageSelectionWidget.cpp @@ -33,7 +33,7 @@ LanguageSelectionWidget::LanguageSelectionWidget(QWidget* parent) : QWidget(pare formatCheckbox = new QCheckBox(this); formatCheckbox->setObjectName(QStringLiteral("formatCheckbox")); - formatCheckbox->setCheckState(APPLICATION->settings()->get("UseSystemLocales").toBool() ? Qt::Checked : Qt::Unchecked); + formatCheckbox->setCheckState(APPLICATION->settings()->get("UseSystemLocale").toBool() ? Qt::Checked : Qt::Unchecked); connect(formatCheckbox, &QCheckBox::stateChanged, [this]() { APPLICATION->translations()->setUseSystemLocale(formatCheckbox->isChecked()); }); verticalLayout->addWidget(formatCheckbox); From 89aaedc06c3eb7a035d8be593a7bbe417cb2f712 Mon Sep 17 00:00:00 2001 From: seth Date: Wed, 12 Jul 2023 21:10:48 -0400 Subject: [PATCH 153/216] feat: add toggle for quilt beacon Signed-off-by: seth --- launcher/Application.cpp | 4 ++++ launcher/minecraft/MinecraftInstance.cpp | 10 ++++++++- launcher/ui/pages/global/MinecraftPage.cpp | 6 +++++ launcher/ui/pages/global/MinecraftPage.ui | 16 ++++++++++++++ .../pages/instance/InstanceSettingsPage.cpp | 15 ++++++++++++- .../ui/pages/instance/InstanceSettingsPage.ui | 22 +++++++++++++++++++ 6 files changed, 71 insertions(+), 2 deletions(-) diff --git a/launcher/Application.cpp b/launcher/Application.cpp index 5aa9efc4a..f98594292 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -9,6 +9,7 @@ * Copyright (C) 2022 Tayou * Copyright (C) 2023 TheKodeToad * Copyright (C) 2023 Rachel Powers <508861+Ryex@users.noreply.github.com> + * Copyright (C) 2023 seth * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -605,6 +606,9 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) m_settings->registerSetting("IgnoreJavaCompatibility", false); m_settings->registerSetting("IgnoreJavaWizard", false); + // Mod loader settings + m_settings->registerSetting("DisableQuiltBeacon", false); + // Native library workarounds m_settings->registerSetting("UseNativeOpenAL", false); m_settings->registerSetting("UseNativeGLFW", false); diff --git a/launcher/minecraft/MinecraftInstance.cpp b/launcher/minecraft/MinecraftInstance.cpp index 4867cc7a3..180838ad2 100644 --- a/launcher/minecraft/MinecraftInstance.cpp +++ b/launcher/minecraft/MinecraftInstance.cpp @@ -3,7 +3,8 @@ * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * Copyright (C) 2022 Jamie Mansfield - * Copyright (C) 2022 TheKodeToad + * Copyright (C) 2022 TheKodeToad \ + * Copyright (c) 2023 seth * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -186,6 +187,10 @@ void MinecraftInstance::loadSpecificSettings() m_settings->registerOverride(global_settings->getSetting("CloseAfterLaunch"), miscellaneousOverride); m_settings->registerOverride(global_settings->getSetting("QuitAfterGameStop"), miscellaneousOverride); + // Mod loader specific options + auto modLoaderSettings = m_settings->registerSetting("OverrideModLoaderSettings", false); + m_settings->registerOverride(global_settings->getSetting("DisableQuiltBeacon"), modLoaderSettings); + m_settings->set("InstanceType", "OneSix"); } @@ -391,6 +396,9 @@ QStringList MinecraftInstance::extraArguments() agent->library()->getApplicableFiles(runtimeContext(), jar, temp1, temp2, temp3, getLocalLibraryPath()); list.append("-javaagent:"+jar[0]+(agent->argument().isEmpty() ? "" : "="+agent->argument())); } + if (version->getModLoaders().value() & ResourceAPI::Quilt && settings()->get("DisableQuiltBeacon").toBool()) { + list.append("-Dloader.disable_beacon=true"); + } return list; } diff --git a/launcher/ui/pages/global/MinecraftPage.cpp b/launcher/ui/pages/global/MinecraftPage.cpp index eca3e8657..954823564 100644 --- a/launcher/ui/pages/global/MinecraftPage.cpp +++ b/launcher/ui/pages/global/MinecraftPage.cpp @@ -2,6 +2,7 @@ /* * PolyMC - Minecraft Launcher * Copyright (c) 2022 Jamie Mansfield + * Copyright (C) 2023 seth * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -99,6 +100,9 @@ void MinecraftPage::applySettings() // Miscellaneous s->set("CloseAfterLaunch", ui->closeAfterLaunchCheck->isChecked()); s->set("QuitAfterGameStop", ui->quitAfterGameStopCheck->isChecked()); + + // Mod loader settings + s->set("DisableQuiltBeacon", ui->disableQuiltBeaconCheckBox->isChecked()); } void MinecraftPage::loadSettings() @@ -137,6 +141,8 @@ void MinecraftPage::loadSettings() ui->closeAfterLaunchCheck->setChecked(s->get("CloseAfterLaunch").toBool()); ui->quitAfterGameStopCheck->setChecked(s->get("QuitAfterGameStop").toBool()); + + ui->disableQuiltBeaconCheckBox->setChecked(s->get("DisableQuiltBeacon").toBool()); } void MinecraftPage::retranslate() diff --git a/launcher/ui/pages/global/MinecraftPage.ui b/launcher/ui/pages/global/MinecraftPage.ui index 8f5de725d..7a8f107b0 100644 --- a/launcher/ui/pages/global/MinecraftPage.ui +++ b/launcher/ui/pages/global/MinecraftPage.ui @@ -190,6 +190,22 @@ Tweaks + + + + Mod loader settings + + + + + + Disable Quilt's Beacon + + + + + + diff --git a/launcher/ui/pages/instance/InstanceSettingsPage.cpp b/launcher/ui/pages/instance/InstanceSettingsPage.cpp index 943ff17f1..25cc1a0de 100644 --- a/launcher/ui/pages/instance/InstanceSettingsPage.cpp +++ b/launcher/ui/pages/instance/InstanceSettingsPage.cpp @@ -3,6 +3,7 @@ * PolyMC - Minecraft Launcher * Copyright (c) 2022 Jamie Mansfield * Copyright (C) 2022 Sefa Eyeoglu + * Copyright (C) 2023 seth * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -50,9 +51,9 @@ #include "Application.h" #include "minecraft/auth/AccountList.h" +#include "FileSystem.h" #include "java/JavaInstallList.h" #include "java/JavaUtils.h" -#include "FileSystem.h" InstanceSettingsPage::InstanceSettingsPage(BaseInstance *inst, QWidget *parent) : QWidget(parent), ui(new Ui::InstanceSettingsPage), m_instance(inst) @@ -280,6 +281,14 @@ void InstanceSettingsPage::applySettings() m_settings->reset("InstanceAccountId"); } + bool overrideModLoaderSettings = ui->modLoaderSettingsGroupBox->isChecked(); + m_settings->set("OverrideModLoaderSettings", overrideModLoaderSettings); + if (overrideModLoaderSettings) { + m_settings->set("DisableQuiltBeacon", ui->disableQuiltBeaconCheckBox->isChecked()); + } else { + m_settings->reset("DisableQuiltBeacon"); + } + // FIXME: This should probably be called by a signal instead m_instance->updateRuntimeContext(); } @@ -380,6 +389,10 @@ void InstanceSettingsPage::loadSettings() ui->instanceAccountGroupBox->setChecked(m_settings->get("UseAccountForInstance").toBool()); updateAccountsMenu(); + + // Mod loader specific settings + ui->modLoaderSettingsGroupBox->setChecked(m_settings->get("OverrideModLoaderSettings").toBool()); + ui->disableQuiltBeaconCheckBox->setChecked(m_settings->get("DisableQuiltBeacon").toBool()); } void InstanceSettingsPage::on_javaDetectBtn_clicked() diff --git a/launcher/ui/pages/instance/InstanceSettingsPage.ui b/launcher/ui/pages/instance/InstanceSettingsPage.ui index 8427965de..5c6f74d47 100644 --- a/launcher/ui/pages/instance/InstanceSettingsPage.ui +++ b/launcher/ui/pages/instance/InstanceSettingsPage.ui @@ -541,6 +541,28 @@ Miscellaneous + + + + true + + + false + + + Mod loader settings + + + + + + Disable Quilt's Beacon + + + + + + From 95b300f1ea7791a7a358d95abb473699d1f016b7 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Thu, 13 Jul 2023 19:56:36 -0700 Subject: [PATCH 154/216] packaging: use PascalCase folder name instead Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- CMakeLists.txt | 4 ++-- launcher/Application.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0defd5e0b..5358d1a8d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -332,7 +332,7 @@ elseif(UNIX) set(BINARY_DEST_DIR "bin") set(LIBRARY_DEST_DIR "lib${LIB_SUFFIX}") - set(JARS_DEST_DIR "share/${Launcher_APP_BINARY_NAME}") + set(JARS_DEST_DIR "share/${Launcher_Name}") # install as bundle with no dependencies included set(INSTALL_BUNDLE "nodeps") @@ -345,7 +345,7 @@ elseif(UNIX) install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${Launcher_SVG} DESTINATION "${KDE_INSTALL_ICONDIR}/hicolor/scalable/apps") install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${Launcher_mrpack_MIMEInfo} DESTINATION ${KDE_INSTALL_MIMEDIR}) - install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/launcher/qtlogging.ini" DESTINATION "share/${Launcher_APP_BINARY_NAME}") + install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/launcher/qtlogging.ini" DESTINATION "share/${Launcher_Name}") if(Launcher_ManPage) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${Launcher_ManPage} DESTINATION "${KDE_INSTALL_MANDIR}/man6") diff --git a/launcher/Application.cpp b/launcher/Application.cpp index 8c60f6974..372a4fc67 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -434,7 +434,7 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) // seach root path if(!foundLoggingRules) { #if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) || defined(Q_OS_OPENBSD) - logRulesPath = FS::PathCombine(m_rootPath, "share", BuildConfig.LAUNCHER_APP_BINARY_NAME, logRulesFile); + logRulesPath = FS::PathCombine(m_rootPath, "share", BuildConfig.LAUNCHER_NAME, logRulesFile); #else logRulesPath = FS::PathCombine(m_rootPath, logRulesFile); #endif @@ -1571,7 +1571,7 @@ QString Application::getJarPath(QString jarFile) { QStringList potentialPaths = { #if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) || defined(Q_OS_OPENBSD) - FS::PathCombine(m_rootPath, "share/" + BuildConfig.LAUNCHER_APP_BINARY_NAME), + FS::PathCombine(m_rootPath, "share/" + BuildConfig.LAUNCHER_NAME), #endif FS::PathCombine(m_rootPath, "jars"), FS::PathCombine(applicationDirPath(), "jars"), From cde85947c7dd4c2508938490789fef60cd464828 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Thu, 13 Jul 2023 21:12:12 -0700 Subject: [PATCH 155/216] Update launcher/minecraft/mod/tasks/LocalResourceParse.cpp Co-authored-by: seth Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/minecraft/mod/tasks/LocalResourceParse.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/minecraft/mod/tasks/LocalResourceParse.cpp b/launcher/minecraft/mod/tasks/LocalResourceParse.cpp index 6d9b4d97a..0894049cd 100644 --- a/launcher/minecraft/mod/tasks/LocalResourceParse.cpp +++ b/launcher/minecraft/mod/tasks/LocalResourceParse.cpp @@ -45,7 +45,7 @@ namespace ResourceUtils { PackedResourceType identify(QFileInfo file){ if (file.exists() && file.isFile()) { if (ModUtils::validate(file)) { - // mods can contain resource and data packs so they much be tested first + // mods can contain resource and data packs so they must be tested first qDebug() << file.fileName() << "is a mod"; return PackedResourceType::Mod; } else if (ResourcePackUtils::validate(file)) { From b0a018d8239df32272a7145f2cf71d1413333060 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 14 Jul 2023 12:28:23 +0300 Subject: [PATCH 156/216] format Signed-off-by: Trial97 --- .../legacy_ftb/PackInstallTask.cpp | 57 ++++++++----------- .../modplatform/legacy_ftb/PackInstallTask.h | 23 ++++---- 2 files changed, 35 insertions(+), 45 deletions(-) diff --git a/launcher/modplatform/legacy_ftb/PackInstallTask.cpp b/launcher/modplatform/legacy_ftb/PackInstallTask.cpp index 36c142acb..4b01e4690 100644 --- a/launcher/modplatform/legacy_ftb/PackInstallTask.cpp +++ b/launcher/modplatform/legacy_ftb/PackInstallTask.cpp @@ -37,16 +37,16 @@ #include -#include "MMCZip.h" #include "BaseInstance.h" #include "FileSystem.h" -#include "settings/INISettingsObject.h" +#include "MMCZip.h" +#include "minecraft/GradleSpecifier.h" #include "minecraft/MinecraftInstance.h" #include "minecraft/PackProfile.h" -#include "minecraft/GradleSpecifier.h" +#include "settings/INISettingsObject.h" -#include "BuildConfig.h" #include "Application.h" +#include "BuildConfig.h" namespace LegacyFTB { @@ -120,16 +120,17 @@ void PackInstallTask::unzip() QDir extractDir(m_stagingPath); m_packZip.reset(new QuaZip(archivePath)); - if(!m_packZip->open(QuaZip::mdUnzip)) - { + if (!m_packZip->open(QuaZip::mdUnzip)) { emitFailed(tr("Failed to open modpack file %1!").arg(archivePath)); return; } #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) - m_extractFuture = QtConcurrent::run(QThreadPool::globalInstance(), QOverload::of(MMCZip::extractDir), archivePath, extractDir.absolutePath() + "/unzip"); + m_extractFuture = QtConcurrent::run(QThreadPool::globalInstance(), QOverload::of(MMCZip::extractDir), archivePath, + extractDir.absolutePath() + "/unzip"); #else - m_extractFuture = QtConcurrent::run(QThreadPool::globalInstance(), MMCZip::extractDir, archivePath, extractDir.absolutePath() + "/unzip"); + m_extractFuture = + QtConcurrent::run(QThreadPool::globalInstance(), MMCZip::extractDir, archivePath, extractDir.absolutePath() + "/unzip"); #endif connect(&m_extractFutureWatcher, &QFutureWatcher::finished, this, &PackInstallTask::onUnzipFinished); connect(&m_extractFutureWatcher, &QFutureWatcher::canceled, this, &PackInstallTask::onUnzipCanceled); @@ -151,11 +152,9 @@ void PackInstallTask::install() setStatus(tr("Installing modpack")); progress(3, 4); QDir unzipMcDir(m_stagingPath + "/unzip/minecraft"); - if(unzipMcDir.exists()) - { - //ok, found minecraft dir, move contents to instance dir - if(!QDir().rename(m_stagingPath + "/unzip/minecraft", m_stagingPath + "/.minecraft")) - { + if (unzipMcDir.exists()) { + // ok, found minecraft dir, move contents to instance dir + if (!QDir().rename(m_stagingPath + "/unzip/minecraft", m_stagingPath + "/.minecraft")) { emitFailed(tr("Failed to move unzipped Minecraft!")); return; } @@ -172,23 +171,20 @@ void PackInstallTask::install() bool fallback = true; - //handle different versions + // handle different versions QFile packJson(m_stagingPath + "/.minecraft/pack.json"); QDir jarmodDir = QDir(m_stagingPath + "/unzip/instMods"); - if(packJson.exists()) - { + if (packJson.exists()) { packJson.open(QIODevice::ReadOnly | QIODevice::Text); QJsonDocument doc = QJsonDocument::fromJson(packJson.readAll()); packJson.close(); - //we only care about the libs + // we only care about the libs QJsonArray libs = doc.object().value("libraries").toArray(); - foreach (const QJsonValue &value, libs) - { + foreach (const QJsonValue& value, libs) { QString nameValue = value.toObject().value("name").toString(); - if(!nameValue.startsWith("net.minecraftforge")) - { + if (!nameValue.startsWith("net.minecraftforge")) { continue; } @@ -199,16 +195,13 @@ void PackInstallTask::install() fallback = false; break; } - } - if(jarmodDir.exists()) - { + if (jarmodDir.exists()) { qDebug() << "Found jarmods, installing..."; QStringList jarmods; - for (auto info: jarmodDir.entryInfoList(QDir::NoDotAndDotDot | QDir::Files)) - { + for (auto info : jarmodDir.entryInfoList(QDir::NoDotAndDotDot | QDir::Files)) { qDebug() << "Jarmod:" << info.fileName(); jarmods.push_back(info.absoluteFilePath()); } @@ -217,12 +210,11 @@ void PackInstallTask::install() fallback = false; } - //just nuke unzip directory, it s not needed anymore + // just nuke unzip directory, it s not needed anymore FS::deletePath(m_stagingPath + "/unzip"); - if(fallback) - { - //TODO: Some fallback mechanism... or just keep failing! + if (fallback) { + // TODO: Some fallback mechanism... or just keep failing! emitFailed(tr("No installation method found!")); return; } @@ -232,8 +224,7 @@ void PackInstallTask::install() progress(4, 4); instance.setName(name()); - if(m_instIcon == "default") - { + if (m_instIcon == "default") { m_instIcon = "ftb_logo"; } instance.setIconKey(m_instIcon); @@ -252,4 +243,4 @@ bool PackInstallTask::abort() return InstanceTask::abort(); } -} +} // namespace LegacyFTB diff --git a/launcher/modplatform/legacy_ftb/PackInstallTask.h b/launcher/modplatform/legacy_ftb/PackInstallTask.h index da791e065..94bb2901a 100644 --- a/launcher/modplatform/legacy_ftb/PackInstallTask.h +++ b/launcher/modplatform/legacy_ftb/PackInstallTask.h @@ -1,12 +1,12 @@ #pragma once -#include "InstanceTask.h" -#include "net/NetJob.h" #include #include +#include "InstanceTask.h" +#include "PackHelpers.h" #include "meta/Index.h" #include "meta/Version.h" #include "meta/VersionList.h" -#include "PackHelpers.h" +#include "net/NetJob.h" #include "net/NetJob.h" @@ -14,27 +14,26 @@ namespace LegacyFTB { -class PackInstallTask : public InstanceTask -{ +class PackInstallTask : public InstanceTask { Q_OBJECT -public: + public: explicit PackInstallTask(shared_qobject_ptr network, Modpack pack, QString version); - virtual ~PackInstallTask(){} + virtual ~PackInstallTask() {} bool canAbort() const override { return true; } bool abort() override; -protected: + protected: //! Entry point for tasks. virtual void executeTask() override; -private: + private: void downloadPack(); void unzip(); void install(); -private slots: + private slots: void onDownloadSucceeded(); void onDownloadFailed(QString reason); void onDownloadProgress(qint64 current, qint64 total); @@ -43,7 +42,7 @@ private slots: void onUnzipFinished(); void onUnzipCanceled(); -private: /* data */ + private: /* data */ shared_qobject_ptr m_network; bool abortable = false; std::unique_ptr m_packZip; @@ -56,4 +55,4 @@ private: /* data */ QString m_version; }; -} +} // namespace LegacyFTB From c8533c0b0d4e510bfe6c6818a25f5c45bc796a53 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Wed, 12 Jul 2023 17:58:24 +0300 Subject: [PATCH 157/216] fixed substatus on ftb_import Signed-off-by: Trial97 --- .../legacy_ftb/PackInstallTask.cpp | 29 +++---------------- .../modplatform/legacy_ftb/PackInstallTask.h | 4 --- 2 files changed, 4 insertions(+), 29 deletions(-) diff --git a/launcher/modplatform/legacy_ftb/PackInstallTask.cpp b/launcher/modplatform/legacy_ftb/PackInstallTask.cpp index 4b01e4690..a4c78397b 100644 --- a/launcher/modplatform/legacy_ftb/PackInstallTask.cpp +++ b/launcher/modplatform/legacy_ftb/PackInstallTask.cpp @@ -65,6 +65,7 @@ void PackInstallTask::executeTask() void PackInstallTask::downloadPack() { setStatus(tr("Downloading zip for %1").arg(m_pack.name)); + setProgress(1, 4); setAbortable(false); archivePath = QString("%1/%2/%3").arg(m_pack.dir, m_version.replace(".", "_"), m_pack.file); @@ -78,11 +79,10 @@ void PackInstallTask::downloadPack() } netJobContainer->addNetAction(Net::Download::makeFile(url, archivePath)); - connect(netJobContainer.get(), &NetJob::succeeded, this, &PackInstallTask::onDownloadSucceeded); - connect(netJobContainer.get(), &NetJob::failed, this, &PackInstallTask::onDownloadFailed); - connect(netJobContainer.get(), &NetJob::progress, this, &PackInstallTask::onDownloadProgress); + connect(netJobContainer.get(), &NetJob::succeeded, this, &PackInstallTask::unzip); + connect(netJobContainer.get(), &NetJob::failed, this, &PackInstallTask::emitFailed); connect(netJobContainer.get(), &NetJob::stepProgress, this, &PackInstallTask::propogateStepProgress); - connect(netJobContainer.get(), &NetJob::aborted, this, &PackInstallTask::onDownloadAborted); + connect(netJobContainer.get(), &NetJob::aborted, this, &PackInstallTask::emitAborted); netJobContainer->start(); @@ -90,27 +90,6 @@ void PackInstallTask::downloadPack() progress(1, 4); } -void PackInstallTask::onDownloadSucceeded() -{ - unzip(); -} - -void PackInstallTask::onDownloadFailed(QString reason) -{ - emitFailed(reason); -} - -void PackInstallTask::onDownloadProgress(qint64 current, qint64 total) -{ - progress(current, total * 4); - setStatus(tr("Downloading zip for %1 (%2%)").arg(m_pack.name).arg(current / 10)); -} - -void PackInstallTask::onDownloadAborted() -{ - emitAborted(); -} - void PackInstallTask::unzip() { setStatus(tr("Extracting modpack")); diff --git a/launcher/modplatform/legacy_ftb/PackInstallTask.h b/launcher/modplatform/legacy_ftb/PackInstallTask.h index 94bb2901a..30ff48597 100644 --- a/launcher/modplatform/legacy_ftb/PackInstallTask.h +++ b/launcher/modplatform/legacy_ftb/PackInstallTask.h @@ -34,10 +34,6 @@ class PackInstallTask : public InstanceTask { void install(); private slots: - void onDownloadSucceeded(); - void onDownloadFailed(QString reason); - void onDownloadProgress(qint64 current, qint64 total); - void onDownloadAborted(); void onUnzipFinished(); void onUnzipCanceled(); From fc4a1ef1935059b3c8e4f5d7bdac9fa2311485ac Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 14 Jul 2023 13:31:13 +0300 Subject: [PATCH 158/216] format Signed-off-by: Trial97 --- launcher/BaseVersion.h | 19 ++++++------------- launcher/java/JavaInstall.cpp | 14 ++++++-------- launcher/java/JavaInstall.h | 31 +++++++++---------------------- 3 files changed, 21 insertions(+), 43 deletions(-) diff --git a/launcher/BaseVersion.h b/launcher/BaseVersion.h index ca0e45027..c7cedbe10 100644 --- a/launcher/BaseVersion.h +++ b/launcher/BaseVersion.h @@ -15,16 +15,15 @@ #pragma once -#include -#include #include +#include +#include /*! * An abstract base class for versions. */ -class BaseVersion -{ -public: +class BaseVersion { + public: using Ptr = std::shared_ptr; virtual ~BaseVersion() {} /*! @@ -45,14 +44,8 @@ public: */ virtual QString typeString() const = 0; - virtual bool operator<(BaseVersion &a) - { - return name() < a.name(); - }; - virtual bool operator>(BaseVersion &a) - { - return name() > a.name(); - }; + virtual bool operator<(BaseVersion& a) { return name() < a.name(); }; + virtual bool operator>(BaseVersion& a) { return name() > a.name(); }; }; Q_DECLARE_METATYPE(BaseVersion::Ptr) diff --git a/launcher/java/JavaInstall.cpp b/launcher/java/JavaInstall.cpp index d5932bcb9..f095aa37f 100644 --- a/launcher/java/JavaInstall.cpp +++ b/launcher/java/JavaInstall.cpp @@ -2,28 +2,26 @@ #include "StringUtils.h" -bool JavaInstall::operator<(const JavaInstall &rhs) +bool JavaInstall::operator<(const JavaInstall& rhs) { auto archCompare = StringUtils::naturalCompare(arch, rhs.arch, Qt::CaseInsensitive); - if(archCompare != 0) + if (archCompare != 0) return archCompare < 0; - if(id < rhs.id) - { + if (id < rhs.id) { return true; } - if(id > rhs.id) - { + if (id > rhs.id) { return false; } return StringUtils::naturalCompare(path, rhs.path, Qt::CaseInsensitive) < 0; } -bool JavaInstall::operator==(const JavaInstall &rhs) +bool JavaInstall::operator==(const JavaInstall& rhs) { return arch == rhs.arch && id == rhs.id && path == rhs.path; } -bool JavaInstall::operator>(const JavaInstall &rhs) +bool JavaInstall::operator>(const JavaInstall& rhs) { return (!operator<(rhs)) && (!operator==(rhs)); } diff --git a/launcher/java/JavaInstall.h b/launcher/java/JavaInstall.h index 64be40d19..2d6e4d537 100644 --- a/launcher/java/JavaInstall.h +++ b/launcher/java/JavaInstall.h @@ -3,31 +3,18 @@ #include "BaseVersion.h" #include "JavaVersion.h" -struct JavaInstall : public BaseVersion -{ - JavaInstall(){} - JavaInstall(QString id, QString arch, QString path) - : id(id), arch(arch), path(path) - { - } - virtual QString descriptor() - { - return id.toString(); - } +struct JavaInstall : public BaseVersion { + JavaInstall() {} + JavaInstall(QString id, QString arch, QString path) : id(id), arch(arch), path(path) {} + virtual QString descriptor() { return id.toString(); } - virtual QString name() - { - return id.toString(); - } + virtual QString name() { return id.toString(); } - virtual QString typeString() const - { - return arch; - } + virtual QString typeString() const { return arch; } - bool operator<(const JavaInstall & rhs); - bool operator==(const JavaInstall & rhs); - bool operator>(const JavaInstall & rhs); + bool operator<(const JavaInstall& rhs); + bool operator==(const JavaInstall& rhs); + bool operator>(const JavaInstall& rhs); JavaVersion id; QString arch; From b0a21c9389dfb6962713b61cdb28fa0022c25eeb Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 14 Jul 2023 13:31:28 +0300 Subject: [PATCH 159/216] insert header Signed-off-by: Trial97 --- launcher/java/JavaInstall.cpp | 18 ++++++++++++++++++ launcher/java/JavaInstall.h | 18 ++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/launcher/java/JavaInstall.cpp b/launcher/java/JavaInstall.cpp index f095aa37f..2931a0deb 100644 --- a/launcher/java/JavaInstall.cpp +++ b/launcher/java/JavaInstall.cpp @@ -1,3 +1,21 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (c) 2023 Trial97 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + #include "JavaInstall.h" #include "StringUtils.h" diff --git a/launcher/java/JavaInstall.h b/launcher/java/JavaInstall.h index 2d6e4d537..aa673dad6 100644 --- a/launcher/java/JavaInstall.h +++ b/launcher/java/JavaInstall.h @@ -1,3 +1,21 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (c) 2023 Trial97 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + #pragma once #include "BaseVersion.h" From 440afcedb02bd878deb2053d2905170763df673d Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 14 Jul 2023 13:32:18 +0300 Subject: [PATCH 160/216] fixed warning Signed-off-by: Trial97 --- launcher/java/JavaInstall.cpp | 19 +++++++++++++++++++ launcher/java/JavaInstall.h | 2 ++ 2 files changed, 21 insertions(+) diff --git a/launcher/java/JavaInstall.cpp b/launcher/java/JavaInstall.cpp index 2931a0deb..cfa471402 100644 --- a/launcher/java/JavaInstall.cpp +++ b/launcher/java/JavaInstall.cpp @@ -18,6 +18,7 @@ #include "JavaInstall.h" +#include "BaseVersion.h" #include "StringUtils.h" bool JavaInstall::operator<(const JavaInstall& rhs) @@ -43,3 +44,21 @@ bool JavaInstall::operator>(const JavaInstall& rhs) { return (!operator<(rhs)) && (!operator==(rhs)); } + +bool JavaInstall::operator<(BaseVersion& a) +{ + try { + return operator<(dynamic_cast(a)); + } catch (const std::bad_cast& e) { + return BaseVersion::operator<(a); + } +} + +bool JavaInstall::operator>(BaseVersion& a) +{ + try { + return operator>(dynamic_cast(a)); + } catch (const std::bad_cast& e) { + return BaseVersion::operator>(a); + } +} diff --git a/launcher/java/JavaInstall.h b/launcher/java/JavaInstall.h index aa673dad6..30815b5a8 100644 --- a/launcher/java/JavaInstall.h +++ b/launcher/java/JavaInstall.h @@ -30,6 +30,8 @@ struct JavaInstall : public BaseVersion { virtual QString typeString() const { return arch; } + virtual bool operator<(BaseVersion& a) override; + virtual bool operator>(BaseVersion& a) override; bool operator<(const JavaInstall& rhs); bool operator==(const JavaInstall& rhs); bool operator>(const JavaInstall& rhs); From 3487e1cb640962ee95520309d5e4b00d6f629c3f Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Fri, 14 Jul 2023 03:56:18 -0700 Subject: [PATCH 161/216] Update launcher/Application.cpp Co-authored-by: Sefa Eyeoglu Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/Application.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/Application.cpp b/launcher/Application.cpp index 372a4fc67..a30409684 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -1571,7 +1571,7 @@ QString Application::getJarPath(QString jarFile) { QStringList potentialPaths = { #if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) || defined(Q_OS_OPENBSD) - FS::PathCombine(m_rootPath, "share/" + BuildConfig.LAUNCHER_NAME), + FS::PathCombine(m_rootPath, "share", BuildConfig.LAUNCHER_NAME), #endif FS::PathCombine(m_rootPath, "jars"), FS::PathCombine(applicationDirPath(), "jars"), From 515197fba2da1d674dbe7bd17dae4e0f22f64097 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Mon, 26 Jun 2023 11:57:21 +0300 Subject: [PATCH 162/216] fix: html sintax for modlist export Signed-off-by: Trial97 --- launcher/modplatform/helpers/ExportToModList.cpp | 16 ++++++++-------- launcher/ui/dialogs/ExportToModListDialog.cpp | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/launcher/modplatform/helpers/ExportToModList.cpp b/launcher/modplatform/helpers/ExportToModList.cpp index 5e01367f9..d837fb0ba 100644 --- a/launcher/modplatform/helpers/ExportToModList.cpp +++ b/launcher/modplatform/helpers/ExportToModList.cpp @@ -37,13 +37,13 @@ QString ExportToModList(QList mods, Formats format, OptionalData extraData if (ver.isEmpty() && meta != nullptr) ver = meta->version().toString(); if (!ver.isEmpty()) - line += QString("[%1]").arg(ver); + line += QString(" [%1]").arg(ver); } if (extraData & Authors && !mod->authors().isEmpty()) line += " by " + mod->authors().join(", "); - lines.append(QString("
      %1
    ").arg(line)); + lines.append(QString("
  • %1
  • ").arg(line)); } - return QString("
  • \n\t%1\n
  • ").arg(lines.join("\n\t")); + return QString("
      \n\t%1\n
    ").arg(lines.join("\n\t")); } case MARKDOWN: { QStringList lines; @@ -61,7 +61,7 @@ QString ExportToModList(QList mods, Formats format, OptionalData extraData if (ver.isEmpty() && meta != nullptr) ver = meta->version().toString(); if (!ver.isEmpty()) - line += QString("[%1]").arg(ver); + line += QString(" [%1]").arg(ver); } if (extraData & Authors && !mod->authors().isEmpty()) line += " by " + mod->authors().join(", "); @@ -75,21 +75,21 @@ QString ExportToModList(QList mods, Formats format, OptionalData extraData auto meta = mod->metadata(); auto modName = mod->name(); - auto line = "name: " + modName + ";"; + auto line = modName; if (extraData & Url) { auto url = mod->metaurl(); if (!url.isEmpty()) - line += " url: " + url + ";"; + line += QString(" (%1)").arg(url); } if (extraData & Version) { auto ver = mod->version(); if (ver.isEmpty() && meta != nullptr) ver = meta->version().toString(); if (!ver.isEmpty()) - line += " version: " + QString("[%1]").arg(ver) + ";"; + line += QString(" [%1]").arg(ver); } if (extraData & Authors && !mod->authors().isEmpty()) - line += " authors " + mod->authors().join(", ") + ";"; + line += " by " + mod->authors().join(", "); lines << line; } return lines.join("\n"); diff --git a/launcher/ui/dialogs/ExportToModListDialog.cpp b/launcher/ui/dialogs/ExportToModListDialog.cpp index 149f6b358..700e7178a 100644 --- a/launcher/ui/dialogs/ExportToModListDialog.cpp +++ b/launcher/ui/dialogs/ExportToModListDialog.cpp @@ -118,7 +118,7 @@ void ExportToModListDialog::triggerImp() QString exampleLine; switch (format) { case ExportToModList::HTML: { - exampleLine = "
      {name} [{version}] by {authors}
    "; + exampleLine = "
  • {name} [{version}] by {authors}
  • "; ui->resultText->setHtml(txt); break; } From 9a3931dac6e75a79989f13b10604a142dbafcfbb Mon Sep 17 00:00:00 2001 From: Trial97 Date: Tue, 27 Jun 2023 16:57:30 +0300 Subject: [PATCH 163/216] Added json and csv format Signed-off-by: Trial97 --- .../modplatform/helpers/ExportToModList.cpp | 56 +++++++++++++++++++ .../modplatform/helpers/ExportToModList.h | 2 +- launcher/ui/dialogs/ExportToModListDialog.cpp | 26 ++++++++- launcher/ui/dialogs/ExportToModListDialog.ui | 10 ++++ 4 files changed, 92 insertions(+), 2 deletions(-) diff --git a/launcher/modplatform/helpers/ExportToModList.cpp b/launcher/modplatform/helpers/ExportToModList.cpp index d837fb0ba..86bb9c419 100644 --- a/launcher/modplatform/helpers/ExportToModList.cpp +++ b/launcher/modplatform/helpers/ExportToModList.cpp @@ -16,6 +16,9 @@ * along with this program. If not, see . */ #include "ExportToModList.h" +#include +#include +#include namespace ExportToModList { QString ExportToModList(QList mods, Formats format, OptionalData extraData) @@ -94,6 +97,59 @@ QString ExportToModList(QList mods, Formats format, OptionalData extraData } return lines.join("\n"); } + case JSON: { + QJsonArray lines; + for (auto mod : mods) { + auto meta = mod->metadata(); + auto modName = mod->name(); + QJsonObject line; + line["name"] = modName; + if (extraData & Url) { + auto url = mod->metaurl(); + if (!url.isEmpty()) + line["url"] = url; + } + if (extraData & Version) { + auto ver = mod->version(); + if (ver.isEmpty() && meta != nullptr) + ver = meta->version().toString(); + if (!ver.isEmpty()) + line["version"] = ver; + } + if (extraData & Authors && !mod->authors().isEmpty()) + line["authors"] = QJsonArray::fromStringList(mod->authors()); + lines << line; + } + QJsonDocument doc; + doc.setArray(lines); + return doc.toJson(); + } + case CSV: { + QStringList lines; + for (auto mod : mods) { + QStringList data; + auto meta = mod->metadata(); + auto modName = mod->name(); + + data << modName; + if (extraData & Url) { + auto url = mod->metaurl(); + if (!url.isEmpty()) + data << url; + } + if (extraData & Version) { + auto ver = mod->version(); + if (ver.isEmpty() && meta != nullptr) + ver = meta->version().toString(); + if (!ver.isEmpty()) + data << ver; + } + if (extraData & Authors && !mod->authors().isEmpty()) + data << QString("\"%1\"").arg(mod->authors().join(",")); + lines << data.join(","); + } + return lines.join("\n"); + } default: { return QString("unknown format:%1").arg(format); } diff --git a/launcher/modplatform/helpers/ExportToModList.h b/launcher/modplatform/helpers/ExportToModList.h index 9ff8d25a1..abd6e9bc6 100644 --- a/launcher/modplatform/helpers/ExportToModList.h +++ b/launcher/modplatform/helpers/ExportToModList.h @@ -22,7 +22,7 @@ namespace ExportToModList { -enum Formats { HTML, MARKDOWN, PLAINTXT, CUSTOM }; +enum Formats { HTML, MARKDOWN, PLAINTXT, JSON, CSV, CUSTOM }; enum OptionalData { Authors = 1 << 0, Url = 1 << 1, diff --git a/launcher/ui/dialogs/ExportToModListDialog.cpp b/launcher/ui/dialogs/ExportToModListDialog.cpp index 700e7178a..cfd28cf85 100644 --- a/launcher/ui/dialogs/ExportToModListDialog.cpp +++ b/launcher/ui/dialogs/ExportToModListDialog.cpp @@ -89,6 +89,20 @@ void ExportToModListDialog::formatChanged(int index) break; } case 3: { + ui->templateGroup->setDisabled(true); + ui->optionsGroup->setDisabled(false); + ui->resultText->hide(); + format = ExportToModList::JSON; + break; + } + case 4: { + ui->templateGroup->setDisabled(true); + ui->optionsGroup->setDisabled(false); + ui->resultText->hide(); + format = ExportToModList::CSV; + break; + } + case 5: { ui->templateGroup->setDisabled(false); ui->optionsGroup->setDisabled(true); ui->resultText->hide(); @@ -133,6 +147,12 @@ void ExportToModListDialog::triggerImp() } case ExportToModList::CUSTOM: return; + case ExportToModList::JSON: + exampleLine = "{\"name\":\"{name}\",\"url\":\"{url}\",\"version\":\"{version}\",\"authors\":\"{authors}\"},"; + break; + case ExportToModList::CSV: + exampleLine = "{name},{url},{version},\"{authors}\""; + break; } if (!m_template_selected) { if (ui->templateText->toPlainText() != exampleLine) @@ -146,7 +166,7 @@ void ExportToModListDialog::done(int result) const QString filename = FS::RemoveInvalidFilenameChars(name); const QString output = QFileDialog::getSaveFileName(this, tr("Export %1").arg(name), FS::PathCombine(QDir::homePath(), filename + extension()), - "File (*.txt *.html *.md)", nullptr); + "File (*.txt *.html *.md *.json *.csv)", nullptr); if (output.isEmpty()) return; @@ -167,6 +187,10 @@ QString ExportToModListDialog::extension() return ".txt"; case ExportToModList::CUSTOM: return ".txt"; + case ExportToModList::JSON: + return ".json"; + case ExportToModList::CSV: + return ".csv"; } return ".txt"; } diff --git a/launcher/ui/dialogs/ExportToModListDialog.ui b/launcher/ui/dialogs/ExportToModListDialog.ui index 640b17665..e0f138f9e 100644 --- a/launcher/ui/dialogs/ExportToModListDialog.ui +++ b/launcher/ui/dialogs/ExportToModListDialog.ui @@ -58,6 +58,16 @@ Plaintext
    + + + JSON + + + + + CSV + + Custom From 50dae9d4f38d84f168922552e9f87bf2d1130d98 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Tue, 27 Jun 2023 18:09:29 +0300 Subject: [PATCH 164/216] Moved to separate functions Signed-off-by: Trial97 --- .../modplatform/helpers/ExportToModList.cpp | 274 ++++++++++-------- 1 file changed, 148 insertions(+), 126 deletions(-) diff --git a/launcher/modplatform/helpers/ExportToModList.cpp b/launcher/modplatform/helpers/ExportToModList.cpp index 86bb9c419..a8a015e34 100644 --- a/launcher/modplatform/helpers/ExportToModList.cpp +++ b/launcher/modplatform/helpers/ExportToModList.cpp @@ -21,135 +21,157 @@ #include namespace ExportToModList { +QString toHTML(QList mods, OptionalData extraData) +{ + QStringList lines; + for (auto mod : mods) { + auto meta = mod->metadata(); + auto modName = mod->name(); + if (extraData & Url) { + auto url = mod->metaurl(); + if (!url.isEmpty()) + modName = QString("%2").arg(url, modName); + } + auto line = modName; + if (extraData & Version) { + auto ver = mod->version(); + if (ver.isEmpty() && meta != nullptr) + ver = meta->version().toString(); + if (!ver.isEmpty()) + line += QString(" [%1]").arg(ver); + } + if (extraData & Authors && !mod->authors().isEmpty()) + line += " by " + mod->authors().join(", "); + lines.append(QString("
  • %1
  • ").arg(line)); + } + return QString("
      \n\t%1\n
    ").arg(lines.join("\n\t")); +} + +QString toMARKDOWN(QList mods, OptionalData extraData) +{ + QStringList lines; + for (auto mod : mods) { + auto meta = mod->metadata(); + auto modName = mod->name(); + if (extraData & Url) { + auto url = mod->metaurl(); + if (!url.isEmpty()) + modName = QString("[%1](%2)").arg(modName, url); + } + auto line = modName; + if (extraData & Version) { + auto ver = mod->version(); + if (ver.isEmpty() && meta != nullptr) + ver = meta->version().toString(); + if (!ver.isEmpty()) + line += QString(" [%1]").arg(ver); + } + if (extraData & Authors && !mod->authors().isEmpty()) + line += " by " + mod->authors().join(", "); + lines << "- " + line; + } + return lines.join("\n"); +} + +QString toPLAINTXT(QList mods, OptionalData extraData) +{ + QStringList lines; + for (auto mod : mods) { + auto meta = mod->metadata(); + auto modName = mod->name(); + + auto line = modName; + if (extraData & Url) { + auto url = mod->metaurl(); + if (!url.isEmpty()) + line += QString(" (%1)").arg(url); + } + if (extraData & Version) { + auto ver = mod->version(); + if (ver.isEmpty() && meta != nullptr) + ver = meta->version().toString(); + if (!ver.isEmpty()) + line += QString(" [%1]").arg(ver); + } + if (extraData & Authors && !mod->authors().isEmpty()) + line += " by " + mod->authors().join(", "); + lines << line; + } + return lines.join("\n"); +} + +QString toJSON(QList mods, OptionalData extraData) +{ + QJsonArray lines; + for (auto mod : mods) { + auto meta = mod->metadata(); + auto modName = mod->name(); + QJsonObject line; + line["name"] = modName; + if (extraData & Url) { + auto url = mod->metaurl(); + if (!url.isEmpty()) + line["url"] = url; + } + if (extraData & Version) { + auto ver = mod->version(); + if (ver.isEmpty() && meta != nullptr) + ver = meta->version().toString(); + if (!ver.isEmpty()) + line["version"] = ver; + } + if (extraData & Authors && !mod->authors().isEmpty()) + line["authors"] = QJsonArray::fromStringList(mod->authors()); + lines << line; + } + QJsonDocument doc; + doc.setArray(lines); + return doc.toJson(); +} + +QString toCSV(QList mods, OptionalData extraData) +{ + QStringList lines; + for (auto mod : mods) { + QStringList data; + auto meta = mod->metadata(); + auto modName = mod->name(); + + data << modName; + if (extraData & Url) + data << mod->metaurl(); + if (extraData & Version) { + auto ver = mod->version(); + if (ver.isEmpty() && meta != nullptr) + ver = meta->version().toString(); + data << ver; + } + if (extraData & Authors) { + QString authors; + if (mod->authors().length() == 1) + authors = mod->authors().back(); + else if (mod->authors().length() > 1) + authors = QString("\"%1\"").arg(mod->authors().join(",")); + data << authors; + } + lines << data.join(","); + } + return lines.join("\n"); +} + QString ExportToModList(QList mods, Formats format, OptionalData extraData) { switch (format) { - case HTML: { - QStringList lines; - for (auto mod : mods) { - auto meta = mod->metadata(); - auto modName = mod->name(); - if (extraData & Url) { - auto url = mod->metaurl(); - if (!url.isEmpty()) - modName = QString("%2").arg(url, modName); - } - auto line = modName; - if (extraData & Version) { - auto ver = mod->version(); - if (ver.isEmpty() && meta != nullptr) - ver = meta->version().toString(); - if (!ver.isEmpty()) - line += QString(" [%1]").arg(ver); - } - if (extraData & Authors && !mod->authors().isEmpty()) - line += " by " + mod->authors().join(", "); - lines.append(QString("
  • %1
  • ").arg(line)); - } - return QString("
      \n\t%1\n
    ").arg(lines.join("\n\t")); - } - case MARKDOWN: { - QStringList lines; - for (auto mod : mods) { - auto meta = mod->metadata(); - auto modName = mod->name(); - if (extraData & Url) { - auto url = mod->metaurl(); - if (!url.isEmpty()) - modName = QString("[%1](%2)").arg(modName, url); - } - auto line = modName; - if (extraData & Version) { - auto ver = mod->version(); - if (ver.isEmpty() && meta != nullptr) - ver = meta->version().toString(); - if (!ver.isEmpty()) - line += QString(" [%1]").arg(ver); - } - if (extraData & Authors && !mod->authors().isEmpty()) - line += " by " + mod->authors().join(", "); - lines << "- " + line; - } - return lines.join("\n"); - } - case PLAINTXT: { - QStringList lines; - for (auto mod : mods) { - auto meta = mod->metadata(); - auto modName = mod->name(); - - auto line = modName; - if (extraData & Url) { - auto url = mod->metaurl(); - if (!url.isEmpty()) - line += QString(" (%1)").arg(url); - } - if (extraData & Version) { - auto ver = mod->version(); - if (ver.isEmpty() && meta != nullptr) - ver = meta->version().toString(); - if (!ver.isEmpty()) - line += QString(" [%1]").arg(ver); - } - if (extraData & Authors && !mod->authors().isEmpty()) - line += " by " + mod->authors().join(", "); - lines << line; - } - return lines.join("\n"); - } - case JSON: { - QJsonArray lines; - for (auto mod : mods) { - auto meta = mod->metadata(); - auto modName = mod->name(); - QJsonObject line; - line["name"] = modName; - if (extraData & Url) { - auto url = mod->metaurl(); - if (!url.isEmpty()) - line["url"] = url; - } - if (extraData & Version) { - auto ver = mod->version(); - if (ver.isEmpty() && meta != nullptr) - ver = meta->version().toString(); - if (!ver.isEmpty()) - line["version"] = ver; - } - if (extraData & Authors && !mod->authors().isEmpty()) - line["authors"] = QJsonArray::fromStringList(mod->authors()); - lines << line; - } - QJsonDocument doc; - doc.setArray(lines); - return doc.toJson(); - } - case CSV: { - QStringList lines; - for (auto mod : mods) { - QStringList data; - auto meta = mod->metadata(); - auto modName = mod->name(); - - data << modName; - if (extraData & Url) { - auto url = mod->metaurl(); - if (!url.isEmpty()) - data << url; - } - if (extraData & Version) { - auto ver = mod->version(); - if (ver.isEmpty() && meta != nullptr) - ver = meta->version().toString(); - if (!ver.isEmpty()) - data << ver; - } - if (extraData & Authors && !mod->authors().isEmpty()) - data << QString("\"%1\"").arg(mod->authors().join(",")); - lines << data.join(","); - } - return lines.join("\n"); - } + case HTML: + return toHTML(mods, extraData); + case MARKDOWN: + return toMARKDOWN(mods, extraData); + case PLAINTXT: + return toPLAINTXT(mods, extraData); + case JSON: + return toJSON(mods, extraData); + case CSV: + return toCSV(mods, extraData); default: { return QString("unknown format:%1").arg(format); } From 9b02c31f8dab0f36f3d0c30115ab323dabe21541 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Tue, 4 Jul 2023 17:48:20 +0300 Subject: [PATCH 165/216] escaped text for html export Signed-off-by: Trial97 --- launcher/modplatform/helpers/ExportToModList.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/launcher/modplatform/helpers/ExportToModList.cpp b/launcher/modplatform/helpers/ExportToModList.cpp index a8a015e34..e7bafac47 100644 --- a/launcher/modplatform/helpers/ExportToModList.cpp +++ b/launcher/modplatform/helpers/ExportToModList.cpp @@ -26,9 +26,9 @@ QString toHTML(QList mods, OptionalData extraData) QStringList lines; for (auto mod : mods) { auto meta = mod->metadata(); - auto modName = mod->name(); + auto modName = mod->name().toHtmlEscaped(); if (extraData & Url) { - auto url = mod->metaurl(); + auto url = mod->metaurl().toHtmlEscaped(); if (!url.isEmpty()) modName = QString("%2").arg(url, modName); } @@ -38,10 +38,10 @@ QString toHTML(QList mods, OptionalData extraData) if (ver.isEmpty() && meta != nullptr) ver = meta->version().toString(); if (!ver.isEmpty()) - line += QString(" [%1]").arg(ver); + line += QString(" [%1]").arg(ver.toHtmlEscaped()); } if (extraData & Authors && !mod->authors().isEmpty()) - line += " by " + mod->authors().join(", "); + line += " by " + mod->authors().join(", ").toHtmlEscaped(); lines.append(QString("
  • %1
  • ").arg(line)); } return QString("
      \n\t%1\n
    ").arg(lines.join("\n\t")); From 1495bfb73ead50b45942e94a8e3b18e111820b4b Mon Sep 17 00:00:00 2001 From: Trial97 Date: Tue, 11 Jul 2023 22:43:27 +0300 Subject: [PATCH 166/216] Made custom template enabled all time Signed-off-by: Trial97 --- .../modplatform/helpers/ExportToModList.h | 2 +- launcher/ui/dialogs/ExportToModListDialog.cpp | 59 +++++++++---------- launcher/ui/dialogs/ExportToModListDialog.h | 3 +- launcher/ui/dialogs/ExportToModListDialog.ui | 14 ++++- 4 files changed, 43 insertions(+), 35 deletions(-) diff --git a/launcher/modplatform/helpers/ExportToModList.h b/launcher/modplatform/helpers/ExportToModList.h index abd6e9bc6..49252fc4f 100644 --- a/launcher/modplatform/helpers/ExportToModList.h +++ b/launcher/modplatform/helpers/ExportToModList.h @@ -16,7 +16,7 @@ * along with this program. If not, see . */ #pragma once -#include +#include #include #include "minecraft/mod/Mod.h" diff --git a/launcher/ui/dialogs/ExportToModListDialog.cpp b/launcher/ui/dialogs/ExportToModListDialog.cpp index cfd28cf85..b86b10561 100644 --- a/launcher/ui/dialogs/ExportToModListDialog.cpp +++ b/launcher/ui/dialogs/ExportToModListDialog.cpp @@ -33,11 +33,19 @@ #include #include +const QHash ExportToModListDialog::exampleLines = { + { ExportToModList::HTML, "
  • {name} [{version}] by {authors}
  • " }, + { ExportToModList::MARKDOWN, "[{name}]({url}) [{version}] by {authors}" }, + { ExportToModList::PLAINTXT, "{name} ({url}) [{version}] by {authors}" }, + { ExportToModList::JSON, "{\"name\":\"{name}\",\"url\":\"{url}\",\"version\":\"{version}\",\"authors\":\"{authors}\"}," }, + { ExportToModList::CSV, "{name},{url},{version},\"{authors}\"" }, +}; + ExportToModListDialog::ExportToModListDialog(InstancePtr instance, QWidget* parent) - : QDialog(parent), m_template_selected(false), name(instance->name()), ui(new Ui::ExportToModListDialog) + : QDialog(parent), m_template_changed(false), name(instance->name()), ui(new Ui::ExportToModListDialog) { ui->setupUi(this); - ui->templateGroup->setDisabled(true); + ui->optionsGroup->setDisabled(false); MinecraftInstance* mcInstance = dynamic_cast(instance.get()); if (mcInstance) { @@ -52,7 +60,12 @@ ExportToModListDialog::ExportToModListDialog(InstancePtr instance, QWidget* pare connect(ui->authorsCheckBox, &QCheckBox::stateChanged, this, &ExportToModListDialog::trigger); connect(ui->versionCheckBox, &QCheckBox::stateChanged, this, &ExportToModListDialog::trigger); connect(ui->urlCheckBox, &QCheckBox::stateChanged, this, &ExportToModListDialog::trigger); - connect(ui->templateText, &QTextEdit::textChanged, this, &ExportToModListDialog::triggerImp); + connect(ui->templateText, &QTextEdit::textChanged, this, [this] { + if (ui->templateText->toPlainText() != exampleLines[format]) + ui->formatComboBox->setCurrentIndex(5); + else + triggerImp(); + }); connect(ui->copyButton, &QPushButton::clicked, this, [this](bool) { this->ui->finalText->selectAll(); this->ui->finalText->copy(); @@ -68,42 +81,37 @@ void ExportToModListDialog::formatChanged(int index) { switch (index) { case 0: { - ui->templateGroup->setDisabled(true); ui->optionsGroup->setDisabled(false); ui->resultText->show(); format = ExportToModList::HTML; break; } case 1: { - ui->templateGroup->setDisabled(true); ui->optionsGroup->setDisabled(false); ui->resultText->show(); format = ExportToModList::MARKDOWN; break; } case 2: { - ui->templateGroup->setDisabled(true); ui->optionsGroup->setDisabled(false); ui->resultText->hide(); format = ExportToModList::PLAINTXT; break; } case 3: { - ui->templateGroup->setDisabled(true); ui->optionsGroup->setDisabled(false); ui->resultText->hide(); format = ExportToModList::JSON; break; } case 4: { - ui->templateGroup->setDisabled(true); ui->optionsGroup->setDisabled(false); ui->resultText->hide(); format = ExportToModList::CSV; break; } case 5: { - ui->templateGroup->setDisabled(false); + m_template_changed = true; ui->optionsGroup->setDisabled(true); ui->resultText->hide(); format = ExportToModList::CUSTOM; @@ -116,7 +124,6 @@ void ExportToModListDialog::formatChanged(int index) void ExportToModListDialog::triggerImp() { if (format == ExportToModList::CUSTOM) { - m_template_selected = true; ui->finalText->setPlainText(ExportToModList::ExportToModList(m_allMods, ui->templateText->toPlainText())); return; } @@ -129,35 +136,25 @@ void ExportToModListDialog::triggerImp() opt |= ExportToModList::Url; auto txt = ExportToModList::ExportToModList(m_allMods, format, static_cast(opt)); ui->finalText->setPlainText(txt); - QString exampleLine; switch (format) { - case ExportToModList::HTML: { - exampleLine = "
  • {name} [{version}] by {authors}
  • "; - ui->resultText->setHtml(txt); - break; - } - case ExportToModList::MARKDOWN: { - exampleLine = "[{name}]({url}) [{version}] by {authors}"; - ui->resultText->setHtml(markdownToHTML(txt)); - break; - } - case ExportToModList::PLAINTXT: { - exampleLine = "{name} ({url}) [{version}] by {authors}"; - break; - } case ExportToModList::CUSTOM: return; + case ExportToModList::HTML: + ui->resultText->setHtml(txt); + break; + case ExportToModList::MARKDOWN: + ui->resultText->setHtml(markdownToHTML(txt)); + break; + case ExportToModList::PLAINTXT: + break; case ExportToModList::JSON: - exampleLine = "{\"name\":\"{name}\",\"url\":\"{url}\",\"version\":\"{version}\",\"authors\":\"{authors}\"},"; break; case ExportToModList::CSV: - exampleLine = "{name},{url},{version},\"{authors}\""; break; } - if (!m_template_selected) { - if (ui->templateText->toPlainText() != exampleLine) - ui->templateText->setPlainText(exampleLine); - } + auto exampleLine = exampleLines[format]; + if (!m_template_changed && ui->templateText->toPlainText() != exampleLine) + ui->templateText->setPlainText(exampleLine); } void ExportToModListDialog::done(int result) diff --git a/launcher/ui/dialogs/ExportToModListDialog.h b/launcher/ui/dialogs/ExportToModListDialog.h index a7a6bcdce..b8a83d830 100644 --- a/launcher/ui/dialogs/ExportToModListDialog.h +++ b/launcher/ui/dialogs/ExportToModListDialog.h @@ -45,8 +45,9 @@ class ExportToModListDialog : public QDialog { private: QString extension(); QList m_allMods; - bool m_template_selected; + bool m_template_changed; QString name; ExportToModList::Formats format = ExportToModList::Formats::HTML; Ui::ExportToModListDialog* ui; + static const QHash exampleLines; }; diff --git a/launcher/ui/dialogs/ExportToModListDialog.ui b/launcher/ui/dialogs/ExportToModListDialog.ui index e0f138f9e..90f179a63 100644 --- a/launcher/ui/dialogs/ExportToModListDialog.ui +++ b/launcher/ui/dialogs/ExportToModListDialog.ui @@ -18,7 +18,7 @@
    - + @@ -149,6 +149,16 @@
    + + + + This depends on the mods meta data. To ensure the meta data run at least one time the mods update on the selected instance(no need to update the mods). + + + true + + +
    @@ -189,7 +199,7 @@ - + buttonBox rejected() ExportToModListDialog From b9ed8283b7e22fff5920dcd81ae347822d31353a Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 13 Jul 2023 20:38:08 +0300 Subject: [PATCH 167/216] Added buttons Signed-off-by: Trial97 --- launcher/ui/dialogs/ExportToModListDialog.cpp | 44 ++++++++++++--- launcher/ui/dialogs/ExportToModListDialog.h | 2 + launcher/ui/dialogs/ExportToModListDialog.ui | 53 +++++++++++++------ 3 files changed, 76 insertions(+), 23 deletions(-) diff --git a/launcher/ui/dialogs/ExportToModListDialog.cpp b/launcher/ui/dialogs/ExportToModListDialog.cpp index b86b10561..a0f8ee7b0 100644 --- a/launcher/ui/dialogs/ExportToModListDialog.cpp +++ b/launcher/ui/dialogs/ExportToModListDialog.cpp @@ -45,7 +45,7 @@ ExportToModListDialog::ExportToModListDialog(InstancePtr instance, QWidget* pare : QDialog(parent), m_template_changed(false), name(instance->name()), ui(new Ui::ExportToModListDialog) { ui->setupUi(this); - ui->optionsGroup->setDisabled(false); + enableCustom(false); MinecraftInstance* mcInstance = dynamic_cast(instance.get()); if (mcInstance) { @@ -60,6 +60,9 @@ ExportToModListDialog::ExportToModListDialog(InstancePtr instance, QWidget* pare connect(ui->authorsCheckBox, &QCheckBox::stateChanged, this, &ExportToModListDialog::trigger); connect(ui->versionCheckBox, &QCheckBox::stateChanged, this, &ExportToModListDialog::trigger); connect(ui->urlCheckBox, &QCheckBox::stateChanged, this, &ExportToModListDialog::trigger); + connect(ui->authorsButton, &QPushButton::clicked, this, [this](bool) { addExtra(ExportToModList::Authors); }); + connect(ui->versionButton, &QPushButton::clicked, this, [this](bool) { addExtra(ExportToModList::Version); }); + connect(ui->urlButton, &QPushButton::clicked, this, [this](bool) { addExtra(ExportToModList::Url); }); connect(ui->templateText, &QTextEdit::textChanged, this, [this] { if (ui->templateText->toPlainText() != exampleLines[format]) ui->formatComboBox->setCurrentIndex(5); @@ -81,38 +84,38 @@ void ExportToModListDialog::formatChanged(int index) { switch (index) { case 0: { - ui->optionsGroup->setDisabled(false); + enableCustom(false); ui->resultText->show(); format = ExportToModList::HTML; break; } case 1: { - ui->optionsGroup->setDisabled(false); + enableCustom(false); ui->resultText->show(); format = ExportToModList::MARKDOWN; break; } case 2: { - ui->optionsGroup->setDisabled(false); + enableCustom(false); ui->resultText->hide(); format = ExportToModList::PLAINTXT; break; } case 3: { - ui->optionsGroup->setDisabled(false); + enableCustom(false); ui->resultText->hide(); format = ExportToModList::JSON; break; } case 4: { - ui->optionsGroup->setDisabled(false); + enableCustom(false); ui->resultText->hide(); format = ExportToModList::CSV; break; } case 5: { m_template_changed = true; - ui->optionsGroup->setDisabled(true); + enableCustom(true); ui->resultText->hide(); format = ExportToModList::CUSTOM; break; @@ -191,3 +194,30 @@ QString ExportToModListDialog::extension() } return ".txt"; } + +void ExportToModListDialog::addExtra(ExportToModList::OptionalData option) +{ + if (format != ExportToModList::CUSTOM) + return; + switch (option) { + case ExportToModList::Authors: + ui->templateText->insertPlainText("{authors}"); + break; + case ExportToModList::Url: + ui->templateText->insertPlainText("{url}"); + break; + case ExportToModList::Version: + ui->templateText->insertPlainText("{version}"); + break; + } +} +void ExportToModListDialog::enableCustom(bool enabled) +{ + ui->authorsCheckBox->setHidden(enabled); + ui->versionCheckBox->setHidden(enabled); + ui->urlCheckBox->setHidden(enabled); + + ui->authorsButton->setHidden(!enabled); + ui->versionButton->setHidden(!enabled); + ui->urlButton->setHidden(!enabled); +} diff --git a/launcher/ui/dialogs/ExportToModListDialog.h b/launcher/ui/dialogs/ExportToModListDialog.h index b8a83d830..9886ae5a0 100644 --- a/launcher/ui/dialogs/ExportToModListDialog.h +++ b/launcher/ui/dialogs/ExportToModListDialog.h @@ -41,9 +41,11 @@ class ExportToModListDialog : public QDialog { void formatChanged(int index); void triggerImp(); void trigger(int) { triggerImp(); }; + void addExtra(ExportToModList::OptionalData option); private: QString extension(); + void enableCustom(bool enabled); QList m_allMods; bool m_template_changed; QString name; diff --git a/launcher/ui/dialogs/ExportToModListDialog.ui b/launcher/ui/dialogs/ExportToModListDialog.ui index 90f179a63..fc72f9a99 100644 --- a/launcher/ui/dialogs/ExportToModListDialog.ui +++ b/launcher/ui/dialogs/ExportToModListDialog.ui @@ -25,22 +25,6 @@ Settings
    - - - - QFrame::NoFrame - - - QFrame::Plain - - - 1 - - - Format - - - @@ -114,9 +98,46 @@ + + + + Version + + + + + + + Authors + + + + + + + URL + + + + + + + QFrame::NoFrame + + + QFrame::Plain + + + 1 + + + Format + + + From 1ccfba13ebe11a1d6ea2897db45b47c2452931f5 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 14 Jul 2023 23:39:54 +0300 Subject: [PATCH 168/216] renames Signed-off-by: Trial97 --- launcher/modplatform/helpers/ExportToModList.cpp | 12 ++++++------ launcher/modplatform/helpers/ExportToModList.h | 4 ++-- launcher/ui/dialogs/ExportToModListDialog.cpp | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/launcher/modplatform/helpers/ExportToModList.cpp b/launcher/modplatform/helpers/ExportToModList.cpp index e7bafac47..1f01c4a89 100644 --- a/launcher/modplatform/helpers/ExportToModList.cpp +++ b/launcher/modplatform/helpers/ExportToModList.cpp @@ -47,7 +47,7 @@ QString toHTML(QList mods, OptionalData extraData) return QString("
      \n\t%1\n
    ").arg(lines.join("\n\t")); } -QString toMARKDOWN(QList mods, OptionalData extraData) +QString toMarkdown(QList mods, OptionalData extraData) { QStringList lines; for (auto mod : mods) { @@ -73,7 +73,7 @@ QString toMARKDOWN(QList mods, OptionalData extraData) return lines.join("\n"); } -QString toPLAINTXT(QList mods, OptionalData extraData) +QString toPlainTXT(QList mods, OptionalData extraData) { QStringList lines; for (auto mod : mods) { @@ -159,15 +159,15 @@ QString toCSV(QList mods, OptionalData extraData) return lines.join("\n"); } -QString ExportToModList(QList mods, Formats format, OptionalData extraData) +QString exportToModList(QList mods, Formats format, OptionalData extraData) { switch (format) { case HTML: return toHTML(mods, extraData); case MARKDOWN: - return toMARKDOWN(mods, extraData); + return toMarkdown(mods, extraData); case PLAINTXT: - return toPLAINTXT(mods, extraData); + return toPlainTXT(mods, extraData); case JSON: return toJSON(mods, extraData); case CSV: @@ -178,7 +178,7 @@ QString ExportToModList(QList mods, Formats format, OptionalData extraData } } -QString ExportToModList(QList mods, QString lineTemplate) +QString exportToModList(QList mods, QString lineTemplate) { QStringList lines; for (auto mod : mods) { diff --git a/launcher/modplatform/helpers/ExportToModList.h b/launcher/modplatform/helpers/ExportToModList.h index 49252fc4f..7ea4ba9c2 100644 --- a/launcher/modplatform/helpers/ExportToModList.h +++ b/launcher/modplatform/helpers/ExportToModList.h @@ -28,6 +28,6 @@ enum OptionalData { Url = 1 << 1, Version = 1 << 2, }; -QString ExportToModList(QList mods, Formats format, OptionalData extraData); -QString ExportToModList(QList mods, QString lineTemplate); +QString exportToModList(QList mods, Formats format, OptionalData extraData); +QString exportToModList(QList mods, QString lineTemplate); } // namespace ExportToModList diff --git a/launcher/ui/dialogs/ExportToModListDialog.cpp b/launcher/ui/dialogs/ExportToModListDialog.cpp index a0f8ee7b0..c811bfe6a 100644 --- a/launcher/ui/dialogs/ExportToModListDialog.cpp +++ b/launcher/ui/dialogs/ExportToModListDialog.cpp @@ -127,7 +127,7 @@ void ExportToModListDialog::formatChanged(int index) void ExportToModListDialog::triggerImp() { if (format == ExportToModList::CUSTOM) { - ui->finalText->setPlainText(ExportToModList::ExportToModList(m_allMods, ui->templateText->toPlainText())); + ui->finalText->setPlainText(ExportToModList::exportToModList(m_allMods, ui->templateText->toPlainText())); return; } auto opt = 0; @@ -137,7 +137,7 @@ void ExportToModListDialog::triggerImp() opt |= ExportToModList::Version; if (ui->urlCheckBox->isChecked()) opt |= ExportToModList::Url; - auto txt = ExportToModList::ExportToModList(m_allMods, format, static_cast(opt)); + auto txt = ExportToModList::exportToModList(m_allMods, format, static_cast(opt)); ui->finalText->setPlainText(txt); switch (format) { case ExportToModList::CUSTOM: From da87e825a154bc87a6017270d80e4afc1b3c2e64 Mon Sep 17 00:00:00 2001 From: Alexandru Ionut Tripon Date: Sat, 15 Jul 2023 15:59:19 +0300 Subject: [PATCH 169/216] Update launcher/ui/dialogs/ExportToModListDialog.ui Co-authored-by: TheKodeToad Signed-off-by: Alexandru Ionut Tripon --- launcher/ui/dialogs/ExportToModListDialog.ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/ui/dialogs/ExportToModListDialog.ui b/launcher/ui/dialogs/ExportToModListDialog.ui index fc72f9a99..25eb43429 100644 --- a/launcher/ui/dialogs/ExportToModListDialog.ui +++ b/launcher/ui/dialogs/ExportToModListDialog.ui @@ -173,7 +173,7 @@ - This depends on the mods meta data. To ensure the meta data run at least one time the mods update on the selected instance(no need to update the mods). + This depends on the mods' metadata. To ensure it is available, run an update on the instance. Installing the updates isn't necessary. true From a2a09ffe01fe8eb6cd1f557b0feb98ed0271151e Mon Sep 17 00:00:00 2001 From: seth Date: Thu, 13 Jul 2023 20:57:38 -0400 Subject: [PATCH 170/216] chore: better explain quilt loader beacon Signed-off-by: seth --- launcher/minecraft/MinecraftInstance.cpp | 2 +- launcher/ui/pages/global/MinecraftPage.ui | 5 ++++- launcher/ui/pages/instance/InstanceSettingsPage.ui | 5 ++++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/launcher/minecraft/MinecraftInstance.cpp b/launcher/minecraft/MinecraftInstance.cpp index 180838ad2..0833d5912 100644 --- a/launcher/minecraft/MinecraftInstance.cpp +++ b/launcher/minecraft/MinecraftInstance.cpp @@ -3,7 +3,7 @@ * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * Copyright (C) 2022 Jamie Mansfield - * Copyright (C) 2022 TheKodeToad \ + * Copyright (C) 2022 TheKodeToad * Copyright (c) 2023 seth * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/ui/pages/global/MinecraftPage.ui b/launcher/ui/pages/global/MinecraftPage.ui index 7a8f107b0..a3188dccb 100644 --- a/launcher/ui/pages/global/MinecraftPage.ui +++ b/launcher/ui/pages/global/MinecraftPage.ui @@ -199,7 +199,10 @@ - Disable Quilt's Beacon + Disable Quilt Loader Beacon + + + Disable Quilt loader's beacon for counting monthly active users diff --git a/launcher/ui/pages/instance/InstanceSettingsPage.ui b/launcher/ui/pages/instance/InstanceSettingsPage.ui index 5c6f74d47..323890b90 100644 --- a/launcher/ui/pages/instance/InstanceSettingsPage.ui +++ b/launcher/ui/pages/instance/InstanceSettingsPage.ui @@ -556,7 +556,10 @@ - Disable Quilt's Beacon + Disable Quilt Loader Beacon + + + Disable Quilt loader's beacon for counting monthly active users From c346d875a2d26435f680efb07f785c43af5ad95a Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sat, 15 Jul 2023 23:26:52 +0300 Subject: [PATCH 171/216] make FileResolvingTask accept empty modlist Signed-off-by: Trial97 --- .../modplatform/flame/FileResolvingTask.cpp | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/launcher/modplatform/flame/FileResolvingTask.cpp b/launcher/modplatform/flame/FileResolvingTask.cpp index ce7a60551..34bd401d3 100644 --- a/launcher/modplatform/flame/FileResolvingTask.cpp +++ b/launcher/modplatform/flame/FileResolvingTask.cpp @@ -21,6 +21,10 @@ bool Flame::FileResolvingTask::abort() void Flame::FileResolvingTask::executeTask() { + if (m_toProcess.files.isEmpty()) { // no file to resolve so leave it empty and emit success immediately + emitSucceeded(); + return; + } setStatus(tr("Resolving mod IDs...")); setProgress(0, 3); m_dljob.reset(new NetJob("Mod id resolver", m_network)); @@ -128,12 +132,13 @@ void Flame::FileResolvingTask::netJobFinished() m_checkJob->start(); } -void Flame::FileResolvingTask::modrinthCheckFinished() { +void Flame::FileResolvingTask::modrinthCheckFinished() +{ setProgress(2, 3); qDebug() << "Finished with blocked mods : " << blockedProjects.size(); for (auto it = blockedProjects.keyBegin(); it != blockedProjects.keyEnd(); it++) { - auto &out = *it; + auto& out = *it; auto bytes = blockedProjects[out]; if (!out->resolved) { continue; @@ -153,15 +158,13 @@ void Flame::FileResolvingTask::modrinthCheckFinished() { out->resolved = false; } } - //copy to an output list and filter out projects found on modrinth + // copy to an output list and filter out projects found on modrinth auto block = std::make_shared>(); auto it = blockedProjects.keys(); - std::copy_if(it.begin(), it.end(), std::back_inserter(*block), [](File *f) { - return !f->resolved; - }); - //Display not found mods early + std::copy_if(it.begin(), it.end(), std::back_inserter(*block), [](File* f) { return !f->resolved; }); + // Display not found mods early if (!block->empty()) { - //blocked mods found, we need the slug for displaying.... we need another job :D ! + // blocked mods found, we need the slug for displaying.... we need another job :D ! m_slugJob.reset(new NetJob("Slug Job", m_network)); int index = 0; for (auto mod : *block) { @@ -173,8 +176,8 @@ void Flame::FileResolvingTask::modrinthCheckFinished() { QObject::connect(dl.get(), &Net::Download::succeeded, [block, index, output]() { auto mod = block->at(index); // use the shared_ptr so it is captured and only freed when we are done auto json = QJsonDocument::fromJson(*output); - auto base = Json::requireString(Json::requireObject(Json::requireObject(Json::requireObject(json),"data"),"links"), - "websiteUrl"); + auto base = + Json::requireString(Json::requireObject(Json::requireObject(Json::requireObject(json), "data"), "links"), "websiteUrl"); auto link = QString("%1/download/%2").arg(base, QString::number(mod->fileId)); mod->websiteUrl = link; }); From 06fc8358d9836a203cd31580fa57f055c9bcef05 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sat, 15 Jul 2023 23:57:32 +0300 Subject: [PATCH 172/216] auto focus search line on resource download Signed-off-by: Trial97 --- launcher/ui/pages/modplatform/ResourcePage.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/launcher/ui/pages/modplatform/ResourcePage.cpp b/launcher/ui/pages/modplatform/ResourcePage.cpp index aab2ee89a..48afbd900 100644 --- a/launcher/ui/pages/modplatform/ResourcePage.cpp +++ b/launcher/ui/pages/modplatform/ResourcePage.cpp @@ -104,6 +104,7 @@ void ResourcePage::openedImpl() updateSelectionButton(); triggerSearch(); + m_ui->searchEdit->setFocus(); } auto ResourcePage::eventFilter(QObject* watched, QEvent* event) -> bool From 6597a5c8604c580994958c2fff87ccbe90988df4 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 16 Jul 2023 00:23:55 +0000 Subject: [PATCH 173/216] 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-parts': 'github:hercules-ci/flake-parts/267149c58a14d15f7f81b4d737308421de9d7152' (2023-07-01) → 'github:hercules-ci/flake-parts/8e8d955c22df93dbe24f19ea04f47a74adbdc5ec' (2023-07-04) • Updated input 'nixpkgs': 'github:nixos/nixpkgs/cd99c2b3c9f160cd004318e0697f90bbd5960825' (2023-07-01) → 'github:nixos/nixpkgs/46ed466081b9cad1125b11f11a2af5cc40b942c7' (2023-07-15) • Updated input 'pre-commit-hooks': 'github:cachix/pre-commit-hooks.nix/42587d3414d1747999a5f71e92a83cf6547b62da' (2023-07-03) → 'github:cachix/pre-commit-hooks.nix/5e28316db471d1ac234beb70031b635437421dd6' (2023-07-14) --- flake.lock | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/flake.lock b/flake.lock index 91a67f087..370250c4b 100644 --- a/flake.lock +++ b/flake.lock @@ -21,11 +21,11 @@ "nixpkgs-lib": "nixpkgs-lib" }, "locked": { - "lastModified": 1688254665, - "narHash": "sha256-8FHEgBrr7gYNiS/NzCxIO3m4hvtLRW9YY1nYo1ivm3o=", + "lastModified": 1688466019, + "narHash": "sha256-VeM2akYrBYMsb4W/MmBo1zmaMfgbL4cH3Pu8PGyIwJ0=", "owner": "hercules-ci", "repo": "flake-parts", - "rev": "267149c58a14d15f7f81b4d737308421de9d7152", + "rev": "8e8d955c22df93dbe24f19ea04f47a74adbdc5ec", "type": "github" }, "original": { @@ -91,11 +91,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1688221086, - "narHash": "sha256-cdW6qUL71cNWhHCpMPOJjlw0wzSRP0pVlRn2vqX/VVg=", + "lastModified": 1689413807, + "narHash": "sha256-exuzOvOhGAEKWQKwDuZAL4N8a1I837hH5eocaTcIbLc=", "owner": "nixos", "repo": "nixpkgs", - "rev": "cd99c2b3c9f160cd004318e0697f90bbd5960825", + "rev": "46ed466081b9cad1125b11f11a2af5cc40b942c7", "type": "github" }, "original": { @@ -138,11 +138,11 @@ ] }, "locked": { - "lastModified": 1688386108, - "narHash": "sha256-Vffto9QaVonzYAcPlAzd0soqWYpPpKk60dfNLSIXcFA=", + "lastModified": 1689328505, + "narHash": "sha256-9B3+OeUn1a/CvzE3GW6nWNwS5J7PDHTyHGlpL3wV5oA=", "owner": "cachix", "repo": "pre-commit-hooks.nix", - "rev": "42587d3414d1747999a5f71e92a83cf6547b62da", + "rev": "5e28316db471d1ac234beb70031b635437421dd6", "type": "github" }, "original": { From 18ebc858fdebbd08703d9e5ddeaf23abcfceaa94 Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Sun, 16 Jul 2023 11:47:47 +0200 Subject: [PATCH 174/216] feat(actions): add backport action Signed-off-by: Sefa Eyeoglu --- .github/workflows/backport.yml | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 .github/workflows/backport.yml diff --git a/.github/workflows/backport.yml b/.github/workflows/backport.yml new file mode 100644 index 000000000..77c1a8802 --- /dev/null +++ b/.github/workflows/backport.yml @@ -0,0 +1,32 @@ +name: Backport +on: + pull_request_target: + types: [closed, labeled] + +# WARNING: +# When extending this action, be aware that $GITHUB_TOKEN allows write access to +# the GitHub repository. This means that it should not evaluate user input in a +# way that allows code injection. + +permissions: + contents: read + +jobs: + backport: + permissions: + contents: write # for korthout/backport-action to create branch + pull-requests: write # for korthout/backport-action to create PR to backport + name: Backport Pull Request + if: github.repository_owner == 'PrismLauncher' && github.event.pull_request.merged == true && (github.event_name != 'labeled' || startsWith('backport', github.event.label.name)) + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + with: + ref: ${{ github.event.pull_request.head.sha }} + - name: Create backport PRs + uses: korthout/backport-action@v1.3.1 + with: + # Config README: https://github.com/korthout/backport-action#backport-action + pull_description: |- + Bot-based backport to `${target_branch}`, triggered by a label in #${pull_number}. + From 1e9a596908ba85dea974e6d041b53c675f8d7b78 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sun, 16 Jul 2023 14:18:17 +0300 Subject: [PATCH 175/216] simplified code in cat packs Signed-off-by: Trial97 --- launcher/ui/themes/CatPack.cpp | 45 ++++++++++------------------- launcher/ui/themes/ThemeManager.cpp | 15 ++++++---- 2 files changed, 26 insertions(+), 34 deletions(-) diff --git a/launcher/ui/themes/CatPack.cpp b/launcher/ui/themes/CatPack.cpp index 435ccdb88..e1f2caf3c 100644 --- a/launcher/ui/themes/CatPack.cpp +++ b/launcher/ui/themes/CatPack.cpp @@ -61,36 +61,23 @@ QString BasicCatPack::path() JsonCatPack::JsonCatPack(QFileInfo& manifestInfo) : BasicCatPack(manifestInfo.dir().dirName()) { - QString path = FS::PathCombine("catpacks", m_id); - - if (!FS::ensureFolderPathExists(path)) { - themeWarningLog() << "couldn't create folder for catpack!"; - return; - } - - if (manifestInfo.exists() && manifestInfo.isFile()) { - try { - auto doc = Json::requireDocument(manifestInfo.absoluteFilePath(), "CatPack JSON file"); - const auto root = doc.object(); - m_name = Json::requireString(root, "name", "Catpack name"); - auto id = Json::ensureString(root, "id", "", "Catpack ID"); - if (!id.isEmpty()) - m_id = id; - m_defaultPath = FS::PathCombine(path, Json::requireString(root, "default", "Deafult Cat")); - auto variants = Json::ensureArray(root, "variants", QJsonArray(), "Catpack Variants"); - for (auto v : variants) { - auto variant = Json::ensureObject(v, QJsonObject(), "Cat variant"); - m_variants << Variant{ FS::PathCombine(path, Json::requireString(variant, "path", "Variant path")), - PartialDate(Json::requireString(variant, "startTime", "Variant startTime")), - PartialDate(Json::requireString(variant, "endTime", "Variant endTime")) }; - } - - } catch (const Exception& e) { - themeWarningLog() << "Couldn't load catpack json: " << e.cause(); - return; + QString path = manifestInfo.path(); + try { + auto doc = Json::requireDocument(manifestInfo.absoluteFilePath(), "CatPack JSON file"); + const auto root = doc.object(); + m_name = Json::requireString(root, "name", "Catpack name"); + m_defaultPath = FS::PathCombine(path, Json::requireString(root, "default", "Default Cat")); + auto variants = Json::ensureArray(root, "variants", QJsonArray(), "Catpack Variants"); + for (auto v : variants) { + auto variant = Json::ensureObject(v, QJsonObject(), "Cat variant"); + m_variants << Variant{ FS::PathCombine(path, Json::requireString(variant, "path", "Variant path")), + PartialDate(Json::requireString(variant, "startTime", "Variant startTime")), + PartialDate(Json::requireString(variant, "endTime", "Variant endTime")) }; } - } else { - themeDebugLog() << "No catpack json present."; + + } catch (const Exception& e) { + themeWarningLog() << "Couldn't load catpack json:" << e.cause(); + return; } } diff --git a/launcher/ui/themes/ThemeManager.cpp b/launcher/ui/themes/ThemeManager.cpp index d00b3a992..ba09f6276 100644 --- a/launcher/ui/themes/ThemeManager.cpp +++ b/launcher/ui/themes/ThemeManager.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include "ui/themes/BrightTheme.h" #include "ui/themes/CatPack.h" #include "ui/themes/CustomTheme.h" @@ -179,13 +180,17 @@ void ThemeManager::initializeCatPacks() for (auto [id, name] : defaultCats) { addCatPack(std::unique_ptr(new BasicCatPack(id, name))); } - QDir catpacksDir("./catpacks/"); + QDir catpacksDir("catpacks"); QString catpacksFolder = catpacksDir.absoluteFilePath(""); - themeDebugLog() << "CatPacks Folder Path: " << catpacksFolder; + themeDebugLog() << "CatPacks Folder Path:" << catpacksFolder; - auto loadFiles = [this](QDir dir) { + QStringList supportedImageFormats; + for (auto format : QImageReader::supportedImageFormats()) { + supportedImageFormats.append("*." + format); + } + auto loadFiles = [this, supportedImageFormats](QDir dir) { // Load image files directly - QDirIterator ImageFileIterator(dir.absoluteFilePath(""), { "*.png", "*.gif", "*.jpg", "*.apng", "*.jxl", "*.avif" }, QDir::Files); + QDirIterator ImageFileIterator(dir.absoluteFilePath(""), supportedImageFormats, QDir::Files); while (ImageFileIterator.hasNext()) { QFile customCatFile(ImageFileIterator.next()); QFileInfo customCatFileInfo(customCatFile); @@ -200,7 +205,7 @@ void ThemeManager::initializeCatPacks() while (directoryIterator.hasNext()) { QDir dir(directoryIterator.next()); QFileInfo manifest(dir.absoluteFilePath("catpack.json")); - if (manifest.exists()) { + if (manifest.isFile()) { // Load background manifest themeDebugLog() << "Loading background manifest from:" << manifest.absoluteFilePath(); addCatPack(std::unique_ptr(new JsonCatPack(manifest))); From de30a72c4e1f051eef2a0bd389fc51e6a64d54c3 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sun, 16 Jul 2023 15:16:16 +0300 Subject: [PATCH 176/216] made the date a object Signed-off-by: Trial97 --- launcher/ui/themes/CatPack.cpp | 58 ++++++++++++++++++----------- launcher/ui/themes/CatPack.h | 7 ---- launcher/ui/themes/ThemeManager.cpp | 21 ++++++++--- 3 files changed, 53 insertions(+), 33 deletions(-) diff --git a/launcher/ui/themes/CatPack.cpp b/launcher/ui/themes/CatPack.cpp index e1f2caf3c..ebb100a40 100644 --- a/launcher/ui/themes/CatPack.cpp +++ b/launcher/ui/themes/CatPack.cpp @@ -39,7 +39,6 @@ #include #include "FileSystem.h" #include "Json.h" -#include "ui/themes/ThemeManager.h" QString BasicCatPack::path() { @@ -59,39 +58,56 @@ QString BasicCatPack::path() return cat; } +JsonCatPack::PartialDate partialDate(QJsonObject date) +{ + auto month = Json::ensureInteger(date, "month", 1); + if (month > 12) + month = 12; + else if (month <= 0) + month = 1; + auto day = Json::ensureInteger(date, "day", 1); + if (day > 31) + day = 31; + else if (day <= 0) + day = 1; + return { month, day }; +}; + JsonCatPack::JsonCatPack(QFileInfo& manifestInfo) : BasicCatPack(manifestInfo.dir().dirName()) { QString path = manifestInfo.path(); - try { - auto doc = Json::requireDocument(manifestInfo.absoluteFilePath(), "CatPack JSON file"); - const auto root = doc.object(); - m_name = Json::requireString(root, "name", "Catpack name"); - m_defaultPath = FS::PathCombine(path, Json::requireString(root, "default", "Default Cat")); - auto variants = Json::ensureArray(root, "variants", QJsonArray(), "Catpack Variants"); - for (auto v : variants) { - auto variant = Json::ensureObject(v, QJsonObject(), "Cat variant"); - m_variants << Variant{ FS::PathCombine(path, Json::requireString(variant, "path", "Variant path")), - PartialDate(Json::requireString(variant, "startTime", "Variant startTime")), - PartialDate(Json::requireString(variant, "endTime", "Variant endTime")) }; - } - - } catch (const Exception& e) { - themeWarningLog() << "Couldn't load catpack json:" << e.cause(); - return; + auto doc = Json::requireDocument(manifestInfo.absoluteFilePath(), "CatPack JSON file"); + const auto root = doc.object(); + m_name = Json::requireString(root, "name", "Catpack name"); + m_defaultPath = FS::PathCombine(path, Json::requireString(root, "default", "Default Cat")); + auto variants = Json::ensureArray(root, "variants", QJsonArray(), "Catpack Variants"); + for (auto v : variants) { + auto variant = Json::ensureObject(v, QJsonObject(), "Cat variant"); + m_variants << Variant{ FS::PathCombine(path, Json::requireString(variant, "path", "Variant path")), + partialDate(Json::requireObject(variant, "startTime", "Variant startTime")), + partialDate(Json::requireObject(variant, "endTime", "Variant endTime")) }; } } +QDate ensureDay(int year, int month, int day) +{ + QDate date(year, month, 1); + if (day > date.daysInMonth()) + day = date.daysInMonth(); + return QDate(year, month, day); +} + QString JsonCatPack::path() { const QDate now = QDate::currentDate(); for (auto var : m_variants) { - QDate startDate(now.year(), var.startTime.month, var.startTime.day); - QDate endDate(now.year(), var.endTime.month, var.endTime.day); + QDate startDate = ensureDay(now.year(), var.startTime.month, var.startTime.day); + QDate endDate = ensureDay(now.year(), var.endTime.month, var.endTime.day); if (startDate > endDate) { // it's spans over multiple years if (endDate <= now) // end date is in the past so jump one year into the future for endDate - endDate = endDate.addYears(1); + endDate = ensureDay(now.year() + 1, var.endTime.month, var.endTime.day); else // end date is in the future so jump one year into the past for startDate - startDate = startDate.addYears(-1); + startDate = ensureDay(now.year() - 1, var.startTime.month, var.startTime.day); } if (startDate >= now && now >= endDate) diff --git a/launcher/ui/themes/CatPack.h b/launcher/ui/themes/CatPack.h index 20cb8f61e..b03a19f03 100644 --- a/launcher/ui/themes/CatPack.h +++ b/launcher/ui/themes/CatPack.h @@ -74,13 +74,6 @@ class FileCatPack : public BasicCatPack { class JsonCatPack : public BasicCatPack { public: struct PartialDate { - PartialDate(QString d) - { - auto sp = d.split("-"); - day = sp[0].toInt(); - if (sp.length() >= 2) - month = sp[1].toInt(); - } int month; int day; }; diff --git a/launcher/ui/themes/ThemeManager.cpp b/launcher/ui/themes/ThemeManager.cpp index ba09f6276..683642d79 100644 --- a/launcher/ui/themes/ThemeManager.cpp +++ b/launcher/ui/themes/ThemeManager.cpp @@ -22,6 +22,7 @@ #include #include #include +#include "Exception.h" #include "ui/themes/BrightTheme.h" #include "ui/themes/CatPack.h" #include "ui/themes/CustomTheme.h" @@ -43,7 +44,10 @@ ThemeManager::ThemeManager(MainWindow* mainWindow) QString ThemeManager::addTheme(std::unique_ptr theme) { QString id = theme->id(); - m_themes.emplace(id, std::move(theme)); + if (m_themes.find(id) == m_themes.end()) + m_themes.emplace(id, std::move(theme)); + else + themeWarningLog() << "Theme(" << id << ") not added to prevent id duplication"; return id; } @@ -167,7 +171,10 @@ QString ThemeManager::getCatPack(QString catName) QString ThemeManager::addCatPack(std::unique_ptr catPack) { QString id = catPack->id(); - m_catPacks.emplace(id, std::move(catPack)); + if (m_catPacks.find(id) == m_catPacks.end()) + m_catPacks.emplace(id, std::move(catPack)); + else + themeWarningLog() << "CatPack(" << id << ") not added to prevent id duplication"; return id; } @@ -206,9 +213,13 @@ void ThemeManager::initializeCatPacks() QDir dir(directoryIterator.next()); QFileInfo manifest(dir.absoluteFilePath("catpack.json")); if (manifest.isFile()) { - // Load background manifest - themeDebugLog() << "Loading background manifest from:" << manifest.absoluteFilePath(); - addCatPack(std::unique_ptr(new JsonCatPack(manifest))); + try { + // Load background manifest + themeDebugLog() << "Loading background manifest from:" << manifest.absoluteFilePath(); + addCatPack(std::unique_ptr(new JsonCatPack(manifest))); + } catch (const Exception& e) { + themeWarningLog() << "Couldn't load catpack json:" << e.cause(); + } } else { loadFiles(dir); } From 251055302eec0232a89f0466efe3e7e7f3fa7de3 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sun, 16 Jul 2023 20:53:58 +0300 Subject: [PATCH 177/216] format Signed-off-by: Trial97 --- launcher/MMCZip.cpp | 148 +++++++--------- launcher/MMCZip.h | 174 +++++++++---------- launcher/ui/dialogs/ExportInstanceDialog.cpp | 70 +++----- launcher/ui/dialogs/ExportInstanceDialog.h | 22 ++- 4 files changed, 184 insertions(+), 230 deletions(-) diff --git a/launcher/MMCZip.cpp b/launcher/MMCZip.cpp index 1a336375b..4e932a768 100644 --- a/launcher/MMCZip.cpp +++ b/launcher/MMCZip.cpp @@ -33,56 +33,48 @@ * limitations under the License. */ +#include "MMCZip.h" #include #include #include -#include "MMCZip.h" #include "FileSystem.h" #include #include // ours -bool MMCZip::mergeZipFiles(QuaZip *into, QFileInfo from, QSet &contained, const FilterFunction filter) +bool MMCZip::mergeZipFiles(QuaZip* into, QFileInfo from, QSet& contained, const FilterFunction filter) { QuaZip modZip(from.filePath()); modZip.open(QuaZip::mdUnzip); QuaZipFile fileInsideMod(&modZip); QuaZipFile zipOutFile(into); - for (bool more = modZip.goToFirstFile(); more; more = modZip.goToNextFile()) - { + for (bool more = modZip.goToFirstFile(); more; more = modZip.goToNextFile()) { QString filename = modZip.getCurrentFileName(); - if (filter && !filter(filename)) - { - qDebug() << "Skipping file " << filename << " from " - << from.fileName() << " - filtered"; + if (filter && !filter(filename)) { + qDebug() << "Skipping file " << filename << " from " << from.fileName() << " - filtered"; continue; } - if (contained.contains(filename)) - { - qDebug() << "Skipping already contained file " << filename << " from " - << from.fileName(); + if (contained.contains(filename)) { + qDebug() << "Skipping already contained file " << filename << " from " << from.fileName(); continue; } contained.insert(filename); - if (!fileInsideMod.open(QIODevice::ReadOnly)) - { + if (!fileInsideMod.open(QIODevice::ReadOnly)) { qCritical() << "Failed to open " << filename << " from " << from.fileName(); return false; } QuaZipNewInfo info_out(fileInsideMod.getActualFileName()); - if (!zipOutFile.open(QIODevice::WriteOnly, info_out)) - { + if (!zipOutFile.open(QIODevice::WriteOnly, info_out)) { qCritical() << "Failed to open " << filename << " in the jar"; fileInsideMod.close(); return false; } - if (!JlCompress::copyData(fileInsideMod, zipOutFile)) - { + if (!JlCompress::copyData(fileInsideMod, zipOutFile)) { zipOutFile.close(); fileInsideMod.close(); qCritical() << "Failed to copy data of " << filename << " into the jar"; @@ -94,10 +86,11 @@ bool MMCZip::mergeZipFiles(QuaZip *into, QFileInfo from, QSet &containe return true; } -bool MMCZip::compressDirFiles(QuaZip *zip, QString dir, QFileInfoList files, bool followSymlinks) +bool MMCZip::compressDirFiles(QuaZip* zip, QString dir, QFileInfoList files, bool followSymlinks) { QDir directory(dir); - if (!directory.exists()) return false; + if (!directory.exists()) + return false; for (auto e : files) { auto filePath = directory.relativeFilePath(e.absoluteFilePath()); @@ -109,7 +102,8 @@ bool MMCZip::compressDirFiles(QuaZip *zip, QString dir, QFileInfoList files, boo srcPath = e.canonicalFilePath(); } } - if( !JlCompress::compressFile(zip, srcPath, filePath)) return false; + if (!JlCompress::compressFile(zip, srcPath, filePath)) + return false; } return true; @@ -119,7 +113,7 @@ bool MMCZip::compressDirFiles(QString fileCompressed, QString dir, QFileInfoList { QuaZip zip(fileCompressed); QDir().mkpath(QFileInfo(fileCompressed).absolutePath()); - if(!zip.open(QuaZip::mdCreate)) { + if (!zip.open(QuaZip::mdCreate)) { QFile::remove(fileCompressed); return false; } @@ -127,7 +121,7 @@ bool MMCZip::compressDirFiles(QString fileCompressed, QString dir, QFileInfoList auto result = compressDirFiles(&zip, dir, files, followSymlinks); zip.close(); - if(zip.getZipError()!=0) { + if (zip.getZipError() != 0) { QFile::remove(fileCompressed); return false; } @@ -139,8 +133,7 @@ bool MMCZip::compressDirFiles(QString fileCompressed, QString dir, QFileInfoList bool MMCZip::createModdedJar(QString sourceJarPath, QString targetJarPath, const QList& mods) { QuaZip zipOut(targetJarPath); - if (!zipOut.open(QuaZip::mdCreate)) - { + if (!zipOut.open(QuaZip::mdCreate)) { QFile::remove(targetJarPath); qCritical() << "Failed to open the minecraft.jar for modding"; return false; @@ -151,37 +144,29 @@ bool MMCZip::createModdedJar(QString sourceJarPath, QString targetJarPath, const // Modify the jar // This needs to be done in reverse-order to ensure we respect the loading order of components - for (auto i = mods.crbegin(); i != mods.crend(); i++) - { + for (auto i = mods.crbegin(); i != mods.crend(); i++) { const auto* mod = *i; // do not merge disabled mods. if (!mod->enabled()) continue; - if (mod->type() == ResourceType::ZIPFILE) - { - if (!mergeZipFiles(&zipOut, mod->fileinfo(), addedFiles)) - { + if (mod->type() == ResourceType::ZIPFILE) { + if (!mergeZipFiles(&zipOut, mod->fileinfo(), addedFiles)) { zipOut.close(); QFile::remove(targetJarPath); qCritical() << "Failed to add" << mod->fileinfo().fileName() << "to the jar."; return false; } - } - else if (mod->type() == ResourceType::SINGLEFILE) - { + } else if (mod->type() == ResourceType::SINGLEFILE) { // FIXME: buggy - does not work with addedFiles auto filename = mod->fileinfo(); - if (!JlCompress::compressFile(&zipOut, filename.absoluteFilePath(), filename.fileName())) - { + if (!JlCompress::compressFile(&zipOut, filename.absoluteFilePath(), filename.fileName())) { zipOut.close(); QFile::remove(targetJarPath); qCritical() << "Failed to add" << mod->fileinfo().fileName() << "to the jar."; return false; } addedFiles.insert(filename.fileName()); - } - else if (mod->type() == ResourceType::FOLDER) - { + } else if (mod->type() == ResourceType::FOLDER) { // untested, but seems to be unused / not possible to reach // FIXME: buggy - does not work with addedFiles auto filename = mod->fileinfo(); @@ -197,18 +182,14 @@ bool MMCZip::createModdedJar(QString sourceJarPath, QString targetJarPath, const files.removeAll(e); } - if (!MMCZip::compressDirFiles(&zipOut, parent_dir, files)) - { + if (!MMCZip::compressDirFiles(&zipOut, parent_dir, files)) { zipOut.close(); QFile::remove(targetJarPath); qCritical() << "Failed to add" << mod->fileinfo().fileName() << "to the jar."; return false; } - qDebug() << "Adding folder " << filename.fileName() << " from " - << filename.absoluteFilePath(); - } - else - { + qDebug() << "Adding folder " << filename.fileName() << " from " << filename.absoluteFilePath(); + } else { // Make sure we do not continue launching when something is missing or undefined... zipOut.close(); QFile::remove(targetJarPath); @@ -217,8 +198,7 @@ bool MMCZip::createModdedJar(QString sourceJarPath, QString targetJarPath, const } } - if (!mergeZipFiles(&zipOut, QFileInfo(sourceJarPath), addedFiles, [](const QString key){return !key.contains("META-INF");})) - { + if (!mergeZipFiles(&zipOut, QFileInfo(sourceJarPath), addedFiles, [](const QString key) { return !key.contains("META-INF"); })) { zipOut.close(); QFile::remove(targetJarPath); qCritical() << "Failed to insert minecraft.jar contents."; @@ -227,8 +207,7 @@ bool MMCZip::createModdedJar(QString sourceJarPath, QString targetJarPath, const // Recompress the jar zipOut.close(); - if (zipOut.getZipError() != 0) - { + if (zipOut.getZipError() != 0) { QFile::remove(targetJarPath); qCritical() << "Failed to finalize minecraft.jar!"; return false; @@ -261,27 +240,23 @@ QString MMCZip::findFolderOfFileInZip(QuaZip* zip, const QString& what, const QS } // ours -bool MMCZip::findFilesInZip(QuaZip * zip, const QString & what, QStringList & result, const QString &root) +bool MMCZip::findFilesInZip(QuaZip* zip, const QString& what, QStringList& result, const QString& root) { QuaZipDir rootDir(zip, root); - for(auto fileName: rootDir.entryList(QDir::Files)) - { - if(fileName == what) - { + for (auto fileName : rootDir.entryList(QDir::Files)) { + if (fileName == what) { result.append(root); return true; } } - for(auto fileName: rootDir.entryList(QDir::Dirs)) - { + for (auto fileName : rootDir.entryList(QDir::Dirs)) { findFilesInZip(zip, what, result, root + fileName); } return !result.isEmpty(); } - // ours -std::optional MMCZip::extractSubDir(QuaZip *zip, const QString & subdir, const QString &target) +std::optional MMCZip::extractSubDir(QuaZip* zip, const QString& subdir, const QString& target) { auto target_top_dir = QUrl::fromLocalFile(target); @@ -289,16 +264,13 @@ std::optional MMCZip::extractSubDir(QuaZip *zip, const QString & su qDebug() << "Extracting subdir" << subdir << "from" << zip->getZipName() << "to" << target; auto numEntries = zip->getEntriesCount(); - if(numEntries < 0) { + if (numEntries < 0) { qWarning() << "Failed to enumerate files in archive"; return std::nullopt; - } - else if(numEntries == 0) { + } else if (numEntries == 0) { qDebug() << "Extracting empty archives seems odd..."; return extracted; - } - else if (!zip->goToFirstFile()) - { + } else if (!zip->goToFirstFile()) { qWarning() << "Failed to seek to first file in zip"; return std::nullopt; } @@ -334,7 +306,8 @@ std::optional MMCZip::extractSubDir(QuaZip *zip, const QString & su } if (!target_top_dir.isParentOf(QUrl::fromLocalFile(target_file_path))) { - qWarning() << "Extracting" << relative_file_name << "was cancelled, because it was effectively outside of the target path" << target; + qWarning() << "Extracting" << relative_file_name << "was cancelled, because it was effectively outside of the target path" + << target; return std::nullopt; } @@ -345,7 +318,8 @@ std::optional MMCZip::extractSubDir(QuaZip *zip, const QString & su } extracted.append(target_file_path); - QFile::setPermissions(target_file_path, QFileDevice::Permission::ReadUser | QFileDevice::Permission::WriteUser | QFileDevice::Permission::ExeUser); + QFile::setPermissions(target_file_path, + QFileDevice::Permission::ReadUser | QFileDevice::Permission::WriteUser | QFileDevice::Permission::ExeUser); qDebug() << "Extracted file" << relative_file_name << "to" << target_file_path; } while (zip->goToNextFile()); @@ -354,7 +328,7 @@ std::optional MMCZip::extractSubDir(QuaZip *zip, const QString & su } // ours -bool MMCZip::extractRelFile(QuaZip *zip, const QString &file, const QString &target) +bool MMCZip::extractRelFile(QuaZip* zip, const QString& file, const QString& target) { return JlCompress::extractFile(zip, file, target); } @@ -363,14 +337,14 @@ bool MMCZip::extractRelFile(QuaZip *zip, const QString &file, const QString &tar std::optional MMCZip::extractDir(QString fileCompressed, QString dir) { QuaZip zip(fileCompressed); - if (!zip.open(QuaZip::mdUnzip)) - { + if (!zip.open(QuaZip::mdUnzip)) { // check if this is a minimum size empty zip file... QFileInfo fileInfo(fileCompressed); - if(fileInfo.size() == 22) { + if (fileInfo.size() == 22) { return QStringList(); } - qWarning() << "Could not open archive for unzipping:" << fileCompressed << "Error:" << zip.getZipError();; + qWarning() << "Could not open archive for unzipping:" << fileCompressed << "Error:" << zip.getZipError(); + ; return std::nullopt; } return MMCZip::extractSubDir(&zip, "", dir); @@ -380,14 +354,14 @@ std::optional MMCZip::extractDir(QString fileCompressed, QString di std::optional MMCZip::extractDir(QString fileCompressed, QString subdir, QString dir) { QuaZip zip(fileCompressed); - if (!zip.open(QuaZip::mdUnzip)) - { + if (!zip.open(QuaZip::mdUnzip)) { // check if this is a minimum size empty zip file... QFileInfo fileInfo(fileCompressed); - if(fileInfo.size() == 22) { + if (fileInfo.size() == 22) { return QStringList(); } - qWarning() << "Could not open archive for unzipping:" << fileCompressed << "Error:" << zip.getZipError();; + qWarning() << "Could not open archive for unzipping:" << fileCompressed << "Error:" << zip.getZipError(); + ; return std::nullopt; } return MMCZip::extractSubDir(&zip, subdir, dir); @@ -397,11 +371,10 @@ std::optional MMCZip::extractDir(QString fileCompressed, QString su bool MMCZip::extractFile(QString fileCompressed, QString file, QString target) { QuaZip zip(fileCompressed); - if (!zip.open(QuaZip::mdUnzip)) - { + if (!zip.open(QuaZip::mdUnzip)) { // check if this is a minimum size empty zip file... QFileInfo fileInfo(fileCompressed); - if(fileInfo.size() == 22) { + if (fileInfo.size() == 22) { return true; } qWarning() << "Could not open archive for unzipping:" << fileCompressed << "Error:" << zip.getZipError(); @@ -410,10 +383,14 @@ bool MMCZip::extractFile(QString fileCompressed, QString file, QString target) return MMCZip::extractRelFile(&zip, file, target); } -bool MMCZip::collectFileListRecursively(const QString& rootDir, const QString& subDir, QFileInfoList *files, - MMCZip::FilterFunction excludeFilter) { +bool MMCZip::collectFileListRecursively(const QString& rootDir, + const QString& subDir, + QFileInfoList* files, + MMCZip::FilterFunction excludeFilter) +{ QDir rootDirectory(rootDir); - if (!rootDirectory.exists()) return false; + if (!rootDirectory.exists()) + return false; QDir directory; if (subDir == nullptr) @@ -421,18 +398,19 @@ bool MMCZip::collectFileListRecursively(const QString& rootDir, const QString& s else directory = QDir(subDir); - if (!directory.exists()) return false; // shouldn't ever happen + if (!directory.exists()) + return false; // shouldn't ever happen // recurse directories QFileInfoList entries = directory.entryInfoList(QDir::AllDirs | QDir::NoDotAndDotDot | QDir::Hidden); - for (const auto& e: entries) { + for (const auto& e : entries) { if (!collectFileListRecursively(rootDir, e.filePath(), files, excludeFilter)) return false; } // collect files entries = directory.entryInfoList(QDir::Files); - for (const auto& e: entries) { + for (const auto& e : entries) { QString relativeFilePath = rootDirectory.relativeFilePath(e.absoluteFilePath()); if (excludeFilter && excludeFilter(relativeFilePath)) { qDebug() << "Skipping file " << relativeFilePath; diff --git a/launcher/MMCZip.h b/launcher/MMCZip.h index 2a78f830f..c7cabdc56 100644 --- a/launcher/MMCZip.h +++ b/launcher/MMCZip.h @@ -35,110 +35,108 @@ #pragma once -#include #include #include -#include "minecraft/mod/Mod.h" +#include #include +#include "minecraft/mod/Mod.h" #include #include -namespace MMCZip -{ - using FilterFunction = std::function; +namespace MMCZip { +using FilterFunction = std::function; - /** - * Merge two zip files, using a filter function - */ - bool mergeZipFiles(QuaZip *into, QFileInfo from, QSet &contained, - const FilterFunction filter = nullptr); +/** + * Merge two zip files, using a filter function + */ +bool mergeZipFiles(QuaZip* into, QFileInfo from, QSet& contained, const FilterFunction filter = nullptr); - /** - * Compress directory, by providing a list of files to compress - * \param zip target archive - * \param dir directory that will be compressed (to compress with relative paths) - * \param files list of files to compress - * \param followSymlinks should follow symlinks when compressing file data - * \return true for success or false for failure - */ - bool compressDirFiles(QuaZip *zip, QString dir, QFileInfoList files, bool followSymlinks = false); +/** + * Compress directory, by providing a list of files to compress + * \param zip target archive + * \param dir directory that will be compressed (to compress with relative paths) + * \param files list of files to compress + * \param followSymlinks should follow symlinks when compressing file data + * \return true for success or false for failure + */ +bool compressDirFiles(QuaZip* zip, QString dir, QFileInfoList files, bool followSymlinks = false); - /** - * Compress directory, by providing a list of files to compress - * \param fileCompressed target archive file - * \param dir directory that will be compressed (to compress with relative paths) - * \param files list of files to compress - * \param followSymlinks should follow symlinks when compressing file data - * \return true for success or false for failure - */ - bool compressDirFiles(QString fileCompressed, QString dir, QFileInfoList files, bool followSymlinks = false); +/** + * Compress directory, by providing a list of files to compress + * \param fileCompressed target archive file + * \param dir directory that will be compressed (to compress with relative paths) + * \param files list of files to compress + * \param followSymlinks should follow symlinks when compressing file data + * \return true for success or false for failure + */ +bool compressDirFiles(QString fileCompressed, QString dir, QFileInfoList files, bool followSymlinks = false); - /** - * take a source jar, add mods to it, resulting in target jar - */ - bool createModdedJar(QString sourceJarPath, QString targetJarPath, const QList& mods); +/** + * take a source jar, add mods to it, resulting in target jar + */ +bool createModdedJar(QString sourceJarPath, QString targetJarPath, const QList& mods); - /** - * Find a single file in archive by file name (not path) - * - * \param ignore_paths paths to skip when recursing the search - * - * \return the path prefix where the file is - */ - QString findFolderOfFileInZip(QuaZip * zip, const QString & what, const QStringList& ignore_paths = {}, const QString &root = QString("")); +/** + * Find a single file in archive by file name (not path) + * + * \param ignore_paths paths to skip when recursing the search + * + * \return the path prefix where the file is + */ +QString findFolderOfFileInZip(QuaZip* zip, const QString& what, const QStringList& ignore_paths = {}, const QString& root = QString("")); - /** - * Find a multiple files of the same name in archive by file name - * If a file is found in a path, no deeper paths are searched - * - * \return true if anything was found - */ - bool findFilesInZip(QuaZip * zip, const QString & what, QStringList & result, const QString &root = QString()); +/** + * Find a multiple files of the same name in archive by file name + * If a file is found in a path, no deeper paths are searched + * + * \return true if anything was found + */ +bool findFilesInZip(QuaZip* zip, const QString& what, QStringList& result, const QString& root = QString()); - /** - * Extract a subdirectory from an archive - */ - std::optional extractSubDir(QuaZip *zip, const QString & subdir, const QString &target); +/** + * Extract a subdirectory from an archive + */ +std::optional extractSubDir(QuaZip* zip, const QString& subdir, const QString& target); - bool extractRelFile(QuaZip *zip, const QString & file, const QString &target); +bool extractRelFile(QuaZip* zip, const QString& file, const QString& target); - /** - * Extract a whole archive. - * - * \param fileCompressed The name of the archive. - * \param dir The directory to extract to, the current directory if left empty. - * \return The list of the full paths of the files extracted, empty on failure. - */ - std::optional extractDir(QString fileCompressed, QString dir); +/** + * Extract a whole archive. + * + * \param fileCompressed The name of the archive. + * \param dir The directory to extract to, the current directory if left empty. + * \return The list of the full paths of the files extracted, empty on failure. + */ +std::optional extractDir(QString fileCompressed, QString dir); - /** - * Extract a subdirectory from an archive - * - * \param fileCompressed The name of the archive. - * \param subdir The directory within the archive to extract - * \param dir The directory to extract to, the current directory if left empty. - * \return The list of the full paths of the files extracted, empty on failure. - */ - std::optional extractDir(QString fileCompressed, QString subdir, QString dir); +/** + * Extract a subdirectory from an archive + * + * \param fileCompressed The name of the archive. + * \param subdir The directory within the archive to extract + * \param dir The directory to extract to, the current directory if left empty. + * \return The list of the full paths of the files extracted, empty on failure. + */ +std::optional extractDir(QString fileCompressed, QString subdir, QString dir); - /** - * Extract a single file from an archive into a directory - * - * \param fileCompressed The name of the archive. - * \param file The file within the archive to extract - * \param dir The directory to extract to, the current directory if left empty. - * \return true for success or false for failure - */ - bool extractFile(QString fileCompressed, QString file, QString dir); +/** + * Extract a single file from an archive into a directory + * + * \param fileCompressed The name of the archive. + * \param file The file within the archive to extract + * \param dir The directory to extract to, the current directory if left empty. + * \return true for success or false for failure + */ +bool extractFile(QString fileCompressed, QString file, QString dir); - /** - * Populate a QFileInfoList with a directory tree recursively, while allowing to excludeFilter what shouldn't be included. - * \param rootDir directory to start off - * \param subDir subdirectory, should be nullptr for first invocation - * \param files resulting list of QFileInfo - * \param excludeFilter function to excludeFilter which files shouldn't be included (returning true means to excude) - * \return true for success or false for failure - */ - bool collectFileListRecursively(const QString &rootDir, const QString &subDir, QFileInfoList *files, FilterFunction excludeFilter); -} +/** + * Populate a QFileInfoList with a directory tree recursively, while allowing to excludeFilter what shouldn't be included. + * \param rootDir directory to start off + * \param subDir subdirectory, should be nullptr for first invocation + * \param files resulting list of QFileInfo + * \param excludeFilter function to excludeFilter which files shouldn't be included (returning true means to excude) + * \return true for success or false for failure + */ +bool collectFileListRecursively(const QString& rootDir, const QString& subDir, QFileInfoList* files, FilterFunction excludeFilter); +} // namespace MMCZip diff --git a/launcher/ui/dialogs/ExportInstanceDialog.cpp b/launcher/ui/dialogs/ExportInstanceDialog.cpp index cc41c394d..379ec79f9 100644 --- a/launcher/ui/dialogs/ExportInstanceDialog.cpp +++ b/launcher/ui/dialogs/ExportInstanceDialog.cpp @@ -72,7 +72,7 @@ ExportInstanceDialog::ExportInstanceDialog(InstancePtr instance, QWidget* parent ui->treeView->setRootIndex(proxyModel->mapFromSource(model->index(root))); ui->treeView->sortByColumn(0, Qt::AscendingOrder); - connect(proxyModel, SIGNAL(rowsInserted(QModelIndex,int,int)), SLOT(rowsInserted(QModelIndex,int,int))); + connect(proxyModel, SIGNAL(rowsInserted(QModelIndex, int, int)), SLOT(rowsInserted(QModelIndex, int, int))); model->setFilter(QDir::AllEntries | QDir::NoDotAndDotDot | QDir::AllDirs | QDir::Hidden); model->setRootPath(root); @@ -92,32 +92,26 @@ void SaveIcon(InstancePtr m_instance) auto iconKey = m_instance->iconKey(); auto iconList = APPLICATION->icons(); auto mmcIcon = iconList->icon(iconKey); - if(!mmcIcon || mmcIcon->isBuiltIn()) { + if (!mmcIcon || mmcIcon->isBuiltIn()) { return; } auto path = mmcIcon->getFilePath(); - if(!path.isNull()) { - QFileInfo inInfo (path); - FS::copy(path, FS::PathCombine(m_instance->instanceRoot(), inInfo.fileName())) (); + if (!path.isNull()) { + QFileInfo inInfo(path); + FS::copy(path, FS::PathCombine(m_instance->instanceRoot(), inInfo.fileName()))(); return; } - auto & image = mmcIcon->m_images[mmcIcon->type()]; - auto & icon = image.icon; + auto& image = mmcIcon->m_images[mmcIcon->type()]; + auto& icon = image.icon; auto sizes = icon.availableSizes(); - if(sizes.size() == 0) - { + if (sizes.size() == 0) { return; } - auto areaOf = [](QSize size) - { - return size.width() * size.height(); - }; + auto areaOf = [](QSize size) { return size.width() * size.height(); }; QSize largest = sizes[0]; // find variant with largest area - for(auto size: sizes) - { - if(areaOf(largest) < areaOf(size)) - { + for (auto size : sizes) { + if (areaOf(largest) < areaOf(size)) { largest = size; } } @@ -129,11 +123,9 @@ bool ExportInstanceDialog::doExport() { auto name = FS::RemoveInvalidFilenameChars(m_instance->name()); - const QString output = QFileDialog::getSaveFileName( - this, tr("Export %1").arg(m_instance->name()), - FS::PathCombine(QDir::homePath(), name + ".zip"), "Zip (*.zip)", nullptr); - if (output.isEmpty()) - { + const QString output = QFileDialog::getSaveFileName(this, tr("Export %1").arg(m_instance->name()), + FS::PathCombine(QDir::homePath(), name + ".zip"), "Zip (*.zip)", nullptr); + if (output.isEmpty()) { return false; } @@ -146,8 +138,7 @@ bool ExportInstanceDialog::doExport() return false; } - if (!MMCZip::compressDirFiles(output, m_instance->instanceRoot(), files, true)) - { + if (!MMCZip::compressDirFiles(output, m_instance->instanceRoot(), files, true)) { QMessageBox::warning(this, tr("Error"), tr("Unable to export instance")); return false; } @@ -157,15 +148,11 @@ bool ExportInstanceDialog::doExport() void ExportInstanceDialog::done(int result) { savePackIgnore(); - if (result == QDialog::Accepted) - { - if (doExport()) - { + if (result == QDialog::Accepted) { + if (doExport()) { QDialog::done(QDialog::Accepted); return; - } - else - { + } else { return; } } @@ -174,15 +161,12 @@ void ExportInstanceDialog::done(int result) void ExportInstanceDialog::rowsInserted(QModelIndex parent, int top, int bottom) { - //WARNING: possible off-by-one? - for(int i = top; i < bottom; i++) - { + // WARNING: possible off-by-one? + for (int i = top; i < bottom; i++) { auto node = proxyModel->index(i, 0, parent); - if(proxyModel->shouldExpand(node)) - { + if (proxyModel->shouldExpand(node)) { auto expNode = node.parent(); - if(!expNode.isValid()) - { + if (!expNode.isValid()) { continue; } ui->treeView->expand(node); @@ -199,8 +183,7 @@ void ExportInstanceDialog::loadPackIgnore() { auto filename = ignoreFileName(); QFile ignoreFile(filename); - if(!ignoreFile.open(QIODevice::ReadOnly)) - { + if (!ignoreFile.open(QIODevice::ReadOnly)) { return; } auto data = ignoreFile.readAll(); @@ -216,12 +199,9 @@ void ExportInstanceDialog::savePackIgnore() { auto data = proxyModel->blockedPaths().toStringList().join('\n').toUtf8(); auto filename = ignoreFileName(); - try - { + try { FS::write(filename, data); - } - catch (const Exception &e) - { + } catch (const Exception& e) { qWarning() << e.cause(); } } diff --git a/launcher/ui/dialogs/ExportInstanceDialog.h b/launcher/ui/dialogs/ExportInstanceDialog.h index 5e8018751..20a92807b 100644 --- a/launcher/ui/dialogs/ExportInstanceDialog.h +++ b/launcher/ui/dialogs/ExportInstanceDialog.h @@ -38,39 +38,37 @@ #include #include #include -#include "FileIgnoreProxy.h" #include "FastFileIconProvider.h" +#include "FileIgnoreProxy.h" class BaseInstance; typedef std::shared_ptr InstancePtr; -namespace Ui -{ +namespace Ui { class ExportInstanceDialog; } -class ExportInstanceDialog : public QDialog -{ +class ExportInstanceDialog : public QDialog { Q_OBJECT -public: - explicit ExportInstanceDialog(InstancePtr instance, QWidget *parent = 0); + public: + explicit ExportInstanceDialog(InstancePtr instance, QWidget* parent = 0); ~ExportInstanceDialog(); virtual void done(int result); -private: + private: bool doExport(); void loadPackIgnore(); void savePackIgnore(); QString ignoreFileName(); -private: - Ui::ExportInstanceDialog *ui; + private: + Ui::ExportInstanceDialog* ui; InstancePtr m_instance; - FileIgnoreProxy * proxyModel; + FileIgnoreProxy* proxyModel; FastFileIconProvider icons; -private slots: + private slots: void rowsInserted(QModelIndex parent, int top, int bottom); }; From cadb7142f0fe5eab16198ca8079d544456a977cc Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sun, 16 Jul 2023 20:57:57 +0300 Subject: [PATCH 178/216] Added progress bar to Prism instance export Signed-off-by: Trial97 --- launcher/MMCZip.cpp | 87 +++++++++++++++----- launcher/MMCZip.h | 47 ++++++++++- launcher/ui/dialogs/ExportInstanceDialog.cpp | 38 +++++---- launcher/ui/dialogs/ExportInstanceDialog.h | 3 +- 4 files changed, 136 insertions(+), 39 deletions(-) diff --git a/launcher/MMCZip.cpp b/launcher/MMCZip.cpp index 4e932a768..f272bc031 100644 --- a/launcher/MMCZip.cpp +++ b/launcher/MMCZip.cpp @@ -2,6 +2,7 @@ /* * PolyMC - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu + * Copyright (c) 2023 Trial97 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -41,9 +42,11 @@ #include #include +#include +namespace MMCZip { // ours -bool MMCZip::mergeZipFiles(QuaZip* into, QFileInfo from, QSet& contained, const FilterFunction filter) +bool mergeZipFiles(QuaZip* into, QFileInfo from, QSet& contained, const FilterFunction filter) { QuaZip modZip(from.filePath()); modZip.open(QuaZip::mdUnzip); @@ -86,7 +89,7 @@ bool MMCZip::mergeZipFiles(QuaZip* into, QFileInfo from, QSet& containe return true; } -bool MMCZip::compressDirFiles(QuaZip* zip, QString dir, QFileInfoList files, bool followSymlinks) +bool compressDirFiles(QuaZip* zip, QString dir, QFileInfoList files, bool followSymlinks) { QDir directory(dir); if (!directory.exists()) @@ -109,7 +112,7 @@ bool MMCZip::compressDirFiles(QuaZip* zip, QString dir, QFileInfoList files, boo return true; } -bool MMCZip::compressDirFiles(QString fileCompressed, QString dir, QFileInfoList files, bool followSymlinks) +bool compressDirFiles(QString fileCompressed, QString dir, QFileInfoList files, bool followSymlinks) { QuaZip zip(fileCompressed); QDir().mkpath(QFileInfo(fileCompressed).absolutePath()); @@ -130,7 +133,7 @@ bool MMCZip::compressDirFiles(QString fileCompressed, QString dir, QFileInfoList } // ours -bool MMCZip::createModdedJar(QString sourceJarPath, QString targetJarPath, const QList& mods) +bool createModdedJar(QString sourceJarPath, QString targetJarPath, const QList& mods) { QuaZip zipOut(targetJarPath); if (!zipOut.open(QuaZip::mdCreate)) { @@ -175,14 +178,14 @@ bool MMCZip::createModdedJar(QString sourceJarPath, QString targetJarPath, const dir.cdUp(); QString parent_dir = dir.absolutePath(); auto files = QFileInfoList(); - MMCZip::collectFileListRecursively(what_to_zip, nullptr, &files, nullptr); + collectFileListRecursively(what_to_zip, nullptr, &files, nullptr); for (auto e : files) { if (addedFiles.contains(e.filePath())) files.removeAll(e); } - if (!MMCZip::compressDirFiles(&zipOut, parent_dir, files)) { + if (!compressDirFiles(&zipOut, parent_dir, files)) { zipOut.close(); QFile::remove(targetJarPath); qCritical() << "Failed to add" << mod->fileinfo().fileName() << "to the jar."; @@ -216,7 +219,7 @@ bool MMCZip::createModdedJar(QString sourceJarPath, QString targetJarPath, const } // ours -QString MMCZip::findFolderOfFileInZip(QuaZip* zip, const QString& what, const QStringList& ignore_paths, const QString& root) +QString findFolderOfFileInZip(QuaZip* zip, const QString& what, const QStringList& ignore_paths, const QString& root) { QuaZipDir rootDir(zip, root); for (auto&& fileName : rootDir.entryList(QDir::Files)) { @@ -240,7 +243,7 @@ QString MMCZip::findFolderOfFileInZip(QuaZip* zip, const QString& what, const QS } // ours -bool MMCZip::findFilesInZip(QuaZip* zip, const QString& what, QStringList& result, const QString& root) +bool findFilesInZip(QuaZip* zip, const QString& what, QStringList& result, const QString& root) { QuaZipDir rootDir(zip, root); for (auto fileName : rootDir.entryList(QDir::Files)) { @@ -256,7 +259,7 @@ bool MMCZip::findFilesInZip(QuaZip* zip, const QString& what, QStringList& resul } // ours -std::optional MMCZip::extractSubDir(QuaZip* zip, const QString& subdir, const QString& target) +std::optional extractSubDir(QuaZip* zip, const QString& subdir, const QString& target) { auto target_top_dir = QUrl::fromLocalFile(target); @@ -328,13 +331,13 @@ std::optional MMCZip::extractSubDir(QuaZip* zip, const QString& sub } // ours -bool MMCZip::extractRelFile(QuaZip* zip, const QString& file, const QString& target) +bool extractRelFile(QuaZip* zip, const QString& file, const QString& target) { return JlCompress::extractFile(zip, file, target); } // ours -std::optional MMCZip::extractDir(QString fileCompressed, QString dir) +std::optional extractDir(QString fileCompressed, QString dir) { QuaZip zip(fileCompressed); if (!zip.open(QuaZip::mdUnzip)) { @@ -347,11 +350,11 @@ std::optional MMCZip::extractDir(QString fileCompressed, QString di ; return std::nullopt; } - return MMCZip::extractSubDir(&zip, "", dir); + return extractSubDir(&zip, "", dir); } // ours -std::optional MMCZip::extractDir(QString fileCompressed, QString subdir, QString dir) +std::optional extractDir(QString fileCompressed, QString subdir, QString dir) { QuaZip zip(fileCompressed); if (!zip.open(QuaZip::mdUnzip)) { @@ -364,11 +367,11 @@ std::optional MMCZip::extractDir(QString fileCompressed, QString su ; return std::nullopt; } - return MMCZip::extractSubDir(&zip, subdir, dir); + return extractSubDir(&zip, subdir, dir); } // ours -bool MMCZip::extractFile(QString fileCompressed, QString file, QString target) +bool extractFile(QString fileCompressed, QString file, QString target) { QuaZip zip(fileCompressed); if (!zip.open(QuaZip::mdUnzip)) { @@ -380,13 +383,10 @@ bool MMCZip::extractFile(QString fileCompressed, QString file, QString target) qWarning() << "Could not open archive for unzipping:" << fileCompressed << "Error:" << zip.getZipError(); return false; } - return MMCZip::extractRelFile(&zip, file, target); + return extractRelFile(&zip, file, target); } -bool MMCZip::collectFileListRecursively(const QString& rootDir, - const QString& subDir, - QFileInfoList* files, - MMCZip::FilterFunction excludeFilter) +bool collectFileListRecursively(const QString& rootDir, const QString& subDir, QFileInfoList* files, FilterFunction excludeFilter) { QDir rootDirectory(rootDir); if (!rootDirectory.exists()) @@ -417,7 +417,52 @@ bool MMCZip::collectFileListRecursively(const QString& rootDir, continue; } - files->append(e); // we want the original paths for MMCZip::compressDirFiles + files->append(e); // we want the original paths for compressDirFiles } return true; } + +void ExportToZipTask::executeTask() +{ + (void)QtConcurrent::run(QThreadPool::globalInstance(), [this]() { + setStatus("Adding files..."); + setProgress(0, m_files.length()); + if (!m_dir.exists()) { + emitFailed(tr("Folder doesn't exist")); + return; + } + if (!m_output->isOpen() && !m_output->open(QuaZip::mdCreate)) { + emitFailed(tr("Could not create file")); + return; + } + + for (const QFileInfo& file : m_files) { + if (!isRunning()) + return; + + auto absolute = file.absoluteFilePath(); + auto relative = m_dir.relativeFilePath(absolute); + setStatus("Compresing: " + relative); + setProgress(m_progress + 1, m_progressTotal); + if (m_followSymlinks) { + if (file.isSymLink()) + absolute = file.symLinkTarget(); + else + absolute = file.canonicalFilePath(); + } + + if (!JlCompress::compressFile(m_output, absolute, m_destinationPrefix + relative)) { + emitFailed(tr("Could not read and compress %1").arg(relative)); + return; + } + } + + m_output->close(); + if (m_output->getZipError() != 0) { + emitFailed(tr("A zip error occurred")); + return; + } + emitSucceeded(); + }); +} +} // namespace MMCZip \ No newline at end of file diff --git a/launcher/MMCZip.h b/launcher/MMCZip.h index c7cabdc56..728dd3c89 100644 --- a/launcher/MMCZip.h +++ b/launcher/MMCZip.h @@ -2,6 +2,7 @@ /* * PolyMC - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu + * Copyright (c) 2023 Trial97 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -35,14 +36,16 @@ #pragma once +#include +#include +#include #include #include #include #include -#include "minecraft/mod/Mod.h" - -#include #include +#include "minecraft/mod/Mod.h" +#include "tasks/Task.h" namespace MMCZip { using FilterFunction = std::function; @@ -139,4 +142,42 @@ bool extractFile(QString fileCompressed, QString file, QString dir); * \return true for success or false for failure */ bool collectFileListRecursively(const QString& rootDir, const QString& subDir, QFileInfoList* files, FilterFunction excludeFilter); + +class ExportToZipTask : public Task { + public: + ExportToZipTask(QuaZip* output, + QDir dir, + QFileInfoList files, + QString destinationPrefix = "", + bool followSymlinks = false, + bool cleanUp = false) + : m_output(output) + , m_dir(dir) + , m_files(files) + , m_destinationPrefix(destinationPrefix) + , m_followSymlinks(followSymlinks) + , m_cleanUp(cleanUp) + { + setAbortable(true); + }; + ExportToZipTask(QString outputPath, QString dir, QFileInfoList files, QString destinationPrefix = "", bool followSymlinks = false) + : ExportToZipTask(new QuaZip(outputPath), QDir(dir), files, destinationPrefix, followSymlinks, true){}; + + virtual ~ExportToZipTask() + { + if (m_cleanUp) + delete m_output; + } + + protected: + virtual void executeTask() override; + + private: + QuaZip* m_output; + QDir m_dir; + QFileInfoList m_files; + QString m_destinationPrefix; + bool m_followSymlinks; + bool m_cleanUp; +}; } // namespace MMCZip diff --git a/launcher/ui/dialogs/ExportInstanceDialog.cpp b/launcher/ui/dialogs/ExportInstanceDialog.cpp index 379ec79f9..1a3f8cd41 100644 --- a/launcher/ui/dialogs/ExportInstanceDialog.cpp +++ b/launcher/ui/dialogs/ExportInstanceDialog.cpp @@ -3,6 +3,7 @@ * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * Copyright (C) 2023 TheKodeToad + * Copyright (c) 2023 Trial97 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -41,6 +42,9 @@ #include #include #include "FileIgnoreProxy.h" +#include "QObjectPtr.h" +#include "ui/dialogs/CustomMessageBox.h" +#include "ui/dialogs/ProgressDialog.h" #include "ui_ExportInstanceDialog.h" #include @@ -119,14 +123,15 @@ void SaveIcon(InstancePtr m_instance) pixmap.save(FS::PathCombine(m_instance->instanceRoot(), iconKey + ".png")); } -bool ExportInstanceDialog::doExport() +void ExportInstanceDialog::doExport() { auto name = FS::RemoveInvalidFilenameChars(m_instance->name()); const QString output = QFileDialog::getSaveFileName(this, tr("Export %1").arg(m_instance->name()), FS::PathCombine(QDir::homePath(), name + ".zip"), "Zip (*.zip)", nullptr); if (output.isEmpty()) { - return false; + QDialog::done(QDialog::Rejected); + return; } SaveIcon(m_instance); @@ -135,26 +140,31 @@ bool ExportInstanceDialog::doExport() if (!MMCZip::collectFileListRecursively(m_instance->instanceRoot(), nullptr, &files, std::bind(&FileIgnoreProxy::filterFile, proxyModel, std::placeholders::_1))) { QMessageBox::warning(this, tr("Error"), tr("Unable to export instance")); - return false; + QDialog::done(QDialog::Rejected); + return; } - if (!MMCZip::compressDirFiles(output, m_instance->instanceRoot(), files, true)) { - QMessageBox::warning(this, tr("Error"), tr("Unable to export instance")); - return false; - } - return true; + auto task = makeShared(output, m_instance->instanceRoot(), files, "", true); + + connect(task.get(), &Task::failed, this, [this, output](QString reason) { + CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->show(); + QFile::remove(output); + }); + connect(task.get(), &Task::aborted, this, [output] { QFile::remove(output); }); + connect(task.get(), &Task::finished, this, [task] { task->deleteLater(); }); + + ProgressDialog progress(this); + progress.setSkipButton(true, tr("Abort")); + auto result = progress.execWithTask(task.get()); + QDialog::done(result); } void ExportInstanceDialog::done(int result) { savePackIgnore(); if (result == QDialog::Accepted) { - if (doExport()) { - QDialog::done(QDialog::Accepted); - return; - } else { - return; - } + doExport(); + return; } QDialog::done(result); } diff --git a/launcher/ui/dialogs/ExportInstanceDialog.h b/launcher/ui/dialogs/ExportInstanceDialog.h index 20a92807b..02f38f63d 100644 --- a/launcher/ui/dialogs/ExportInstanceDialog.h +++ b/launcher/ui/dialogs/ExportInstanceDialog.h @@ -2,6 +2,7 @@ /* * Prism Launcher - Minecraft Launcher * Copyright (C) 2023 TheKodeToad + * Copyright (c) 2023 Trial97 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -58,7 +59,7 @@ class ExportInstanceDialog : public QDialog { virtual void done(int result); private: - bool doExport(); + void doExport(); void loadPackIgnore(); void savePackIgnore(); QString ignoreFileName(); From 79222a56e38a696168dddcc92a970242e0f34053 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sun, 16 Jul 2023 21:12:53 +0300 Subject: [PATCH 179/216] use shared pointer Signed-off-by: Trial97 use shared pointer --- launcher/MMCZip.cpp | 2 +- launcher/MMCZip.h | 24 +++++++----------------- 2 files changed, 8 insertions(+), 18 deletions(-) diff --git a/launcher/MMCZip.cpp b/launcher/MMCZip.cpp index f272bc031..ec1c4b07d 100644 --- a/launcher/MMCZip.cpp +++ b/launcher/MMCZip.cpp @@ -451,7 +451,7 @@ void ExportToZipTask::executeTask() absolute = file.canonicalFilePath(); } - if (!JlCompress::compressFile(m_output, absolute, m_destinationPrefix + relative)) { + if (!JlCompress::compressFile(m_output.get(), absolute, m_destinationPrefix + relative)) { emitFailed(tr("Could not read and compress %1").arg(relative)); return; } diff --git a/launcher/MMCZip.h b/launcher/MMCZip.h index 728dd3c89..ded169cd9 100644 --- a/launcher/MMCZip.h +++ b/launcher/MMCZip.h @@ -43,6 +43,7 @@ #include #include #include +#include #include #include "minecraft/mod/Mod.h" #include "tasks/Task.h" @@ -145,39 +146,28 @@ bool collectFileListRecursively(const QString& rootDir, const QString& subDir, Q class ExportToZipTask : public Task { public: - ExportToZipTask(QuaZip* output, + ExportToZipTask(std::shared_ptr output, QDir dir, QFileInfoList files, QString destinationPrefix = "", - bool followSymlinks = false, - bool cleanUp = false) - : m_output(output) - , m_dir(dir) - , m_files(files) - , m_destinationPrefix(destinationPrefix) - , m_followSymlinks(followSymlinks) - , m_cleanUp(cleanUp) + bool followSymlinks = false) + : m_output(output), m_dir(dir), m_files(files), m_destinationPrefix(destinationPrefix), m_followSymlinks(followSymlinks) { setAbortable(true); }; ExportToZipTask(QString outputPath, QString dir, QFileInfoList files, QString destinationPrefix = "", bool followSymlinks = false) - : ExportToZipTask(new QuaZip(outputPath), QDir(dir), files, destinationPrefix, followSymlinks, true){}; + : ExportToZipTask(std::make_shared(outputPath), QDir(dir), files, destinationPrefix, followSymlinks){}; - virtual ~ExportToZipTask() - { - if (m_cleanUp) - delete m_output; - } + virtual ~ExportToZipTask() = default; protected: virtual void executeTask() override; private: - QuaZip* m_output; + std::shared_ptr m_output; QDir m_dir; QFileInfoList m_files; QString m_destinationPrefix; bool m_followSymlinks; - bool m_cleanUp; }; } // namespace MMCZip From 4df9df03ab2e6eddae08f95ec2d34b4e811158ed Mon Sep 17 00:00:00 2001 From: Alexandru Ionut Tripon Date: Sun, 16 Jul 2023 23:47:47 +0300 Subject: [PATCH 180/216] Update launcher/MMCZip.cpp Co-authored-by: Tayou <31988415+TayouVR@users.noreply.github.com> Signed-off-by: Alexandru Ionut Tripon --- launcher/MMCZip.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/MMCZip.cpp b/launcher/MMCZip.cpp index ec1c4b07d..0a334a83f 100644 --- a/launcher/MMCZip.cpp +++ b/launcher/MMCZip.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * Copyright (c) 2023 Trial97 * From ec41252535d9432d0b15228dc301e3a57e1c281d Mon Sep 17 00:00:00 2001 From: Alexandru Ionut Tripon Date: Sun, 16 Jul 2023 23:47:54 +0300 Subject: [PATCH 181/216] Update launcher/MMCZip.h Co-authored-by: Tayou <31988415+TayouVR@users.noreply.github.com> Signed-off-by: Alexandru Ionut Tripon --- launcher/MMCZip.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/MMCZip.h b/launcher/MMCZip.h index ded169cd9..531f4a38a 100644 --- a/launcher/MMCZip.h +++ b/launcher/MMCZip.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * Copyright (c) 2023 Trial97 * From ed2f680202316c2ecf33a8926866a47da17f44e2 Mon Sep 17 00:00:00 2001 From: seth Date: Sun, 16 Jul 2023 17:28:14 -0400 Subject: [PATCH 182/216] chore(docs): add backporting info to CONTRIBUTING.md Signed-off-by: seth --- CONTRIBUTING.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4bca126f8..b2795ce49 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -61,3 +61,10 @@ As a bonus, you can also [cryptographically sign your commits][gh-signing-commit [gh-signing-commits]: https://docs.github.com/en/authentication/managing-commit-signature-verification/signing-commits [gh-vigilant-mode]: https://docs.github.com/en/authentication/managing-commit-signature-verification/displaying-verification-statuses-for-all-of-your-commits + + +## Backporting to Release Branches + +We use [automated backports](https://github.com/PrismLauncher/PrismLauncher/blob/develop/.github/workflows/backport.yml) to merge specific contributions from develop into `release` branches. + +This is done when pull requests are merged and have labels such as `backport release-7.x` - which should be added along with the milestone for the release. From ec32618e1158beba1cf5b4c91c3835a233eceeeb Mon Sep 17 00:00:00 2001 From: Trial97 Date: Mon, 17 Jul 2023 10:20:22 +0300 Subject: [PATCH 183/216] reveted back to add years Signed-off-by: Trial97 --- launcher/ui/themes/CatPack.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/launcher/ui/themes/CatPack.cpp b/launcher/ui/themes/CatPack.cpp index ebb100a40..f0d8ddd55 100644 --- a/launcher/ui/themes/CatPack.cpp +++ b/launcher/ui/themes/CatPack.cpp @@ -105,9 +105,9 @@ QString JsonCatPack::path() QDate endDate = ensureDay(now.year(), var.endTime.month, var.endTime.day); if (startDate > endDate) { // it's spans over multiple years if (endDate <= now) // end date is in the past so jump one year into the future for endDate - endDate = ensureDay(now.year() + 1, var.endTime.month, var.endTime.day); + endDate = endDate.addYears(1); else // end date is in the future so jump one year into the past for startDate - startDate = ensureDay(now.year() - 1, var.startTime.month, var.startTime.day); + startDate = startDate.addYears(-1); } if (startDate >= now && now >= endDate) From 54a091ca597608e732f00eb7f086fe26448daea1 Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Mon, 17 Jul 2023 10:09:01 +0200 Subject: [PATCH 184/216] fix: check if any modloader is installed Signed-off-by: Sefa Eyeoglu --- launcher/minecraft/MinecraftInstance.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/launcher/minecraft/MinecraftInstance.cpp b/launcher/minecraft/MinecraftInstance.cpp index 0833d5912..83b50f0bd 100644 --- a/launcher/minecraft/MinecraftInstance.cpp +++ b/launcher/minecraft/MinecraftInstance.cpp @@ -396,8 +396,11 @@ QStringList MinecraftInstance::extraArguments() agent->library()->getApplicableFiles(runtimeContext(), jar, temp1, temp2, temp3, getLocalLibraryPath()); list.append("-javaagent:"+jar[0]+(agent->argument().isEmpty() ? "" : "="+agent->argument())); } - if (version->getModLoaders().value() & ResourceAPI::Quilt && settings()->get("DisableQuiltBeacon").toBool()) { - list.append("-Dloader.disable_beacon=true"); + + { + const auto& loaders = version->getModLoaders(); + if (loaders.has_value() && loaders.value() & ResourceAPI::Quilt && settings()->get("DisableQuiltBeacon").toBool()) + list.append("-Dloader.disable_beacon=true"); } return list; } From 2be630904f89c9308d3e0bab94eb9e5a4fa6ae03 Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Mon, 17 Jul 2023 14:33:01 +0200 Subject: [PATCH 185/216] fix: don't take modloaders by reference Co-authored-by: TheKodeToad Signed-off-by: Sefa Eyeoglu --- launcher/minecraft/MinecraftInstance.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/minecraft/MinecraftInstance.cpp b/launcher/minecraft/MinecraftInstance.cpp index 83b50f0bd..342e634f7 100644 --- a/launcher/minecraft/MinecraftInstance.cpp +++ b/launcher/minecraft/MinecraftInstance.cpp @@ -398,7 +398,7 @@ QStringList MinecraftInstance::extraArguments() } { - const auto& loaders = version->getModLoaders(); + const auto loaders = version->getModLoaders(); if (loaders.has_value() && loaders.value() & ResourceAPI::Quilt && settings()->get("DisableQuiltBeacon").toBool()) list.append("-Dloader.disable_beacon=true"); } From 2ea4a78541c5d6dc682ec76c2e0846fe11fe1cf9 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Mon, 17 Jul 2023 16:24:43 +0300 Subject: [PATCH 186/216] Upgraded ExportToZipTask Signed-off-by: Trial97 --- launcher/MMCZip.cpp | 95 ++++++++++++++++++++++++++------------------- launcher/MMCZip.h | 23 ++++++----- 2 files changed, 68 insertions(+), 50 deletions(-) diff --git a/launcher/MMCZip.cpp b/launcher/MMCZip.cpp index 0a334a83f..cc7491971 100644 --- a/launcher/MMCZip.cpp +++ b/launcher/MMCZip.cpp @@ -424,45 +424,60 @@ bool collectFileListRecursively(const QString& rootDir, const QString& subDir, Q void ExportToZipTask::executeTask() { - (void)QtConcurrent::run(QThreadPool::globalInstance(), [this]() { - setStatus("Adding files..."); - setProgress(0, m_files.length()); - if (!m_dir.exists()) { - emitFailed(tr("Folder doesn't exist")); - return; - } - if (!m_output->isOpen() && !m_output->open(QuaZip::mdCreate)) { - emitFailed(tr("Could not create file")); - return; - } - - for (const QFileInfo& file : m_files) { - if (!isRunning()) - return; - - auto absolute = file.absoluteFilePath(); - auto relative = m_dir.relativeFilePath(absolute); - setStatus("Compresing: " + relative); - setProgress(m_progress + 1, m_progressTotal); - if (m_followSymlinks) { - if (file.isSymLink()) - absolute = file.symLinkTarget(); - else - absolute = file.canonicalFilePath(); - } - - if (!JlCompress::compressFile(m_output.get(), absolute, m_destinationPrefix + relative)) { - emitFailed(tr("Could not read and compress %1").arg(relative)); - return; - } - } - - m_output->close(); - if (m_output->getZipError() != 0) { - emitFailed(tr("A zip error occurred")); - return; - } - emitSucceeded(); - }); + (void)QtConcurrent::run(QThreadPool::globalInstance(), [this]() { exportZip(); }); } + +void ExportToZipTask::exportZip() +{ + setStatus("Adding files..."); + setProgress(0, m_files.length()); + if (!m_dir.exists()) { + emitFailed(tr("Folder doesn't exist")); + return; + } + if (!m_output.isOpen() && !m_output.open(QuaZip::mdCreate)) { + emitFailed(tr("Could not create file")); + return; + } + + for (auto fileName : m_extra_files.keys()) { + if (!isRunning()) + return; + QuaZipFile indexFile(&m_output); + if (!indexFile.open(QIODevice::WriteOnly, QuaZipNewInfo(fileName))) { + emitFailed(tr("Could not create:") + fileName); + return; + } + indexFile.write(m_extra_files[fileName]); + } + + for (const QFileInfo& file : m_files) { + if (!isRunning()) + return; + + auto absolute = file.absoluteFilePath(); + auto relative = m_dir.relativeFilePath(absolute); + setStatus("Compresing: " + relative); + setProgress(m_progress + 1, m_progressTotal); + if (m_follow_symlinks) { + if (file.isSymLink()) + absolute = file.symLinkTarget(); + else + absolute = file.canonicalFilePath(); + } + + if (!m_exclude_files.contains(relative) && !JlCompress::compressFile(&m_output, absolute, m_destination_prefix + relative)) { + emitFailed(tr("Could not read and compress %1").arg(relative)); + return; + } + } + + m_output.close(); + if (m_output.getZipError() != 0) { + emitFailed(tr("A zip error occurred")); + return; + } + emitSucceeded(); +} + } // namespace MMCZip \ No newline at end of file diff --git a/launcher/MMCZip.h b/launcher/MMCZip.h index 531f4a38a..60b3490fe 100644 --- a/launcher/MMCZip.h +++ b/launcher/MMCZip.h @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -146,28 +147,30 @@ bool collectFileListRecursively(const QString& rootDir, const QString& subDir, Q class ExportToZipTask : public Task { public: - ExportToZipTask(std::shared_ptr output, - QDir dir, - QFileInfoList files, - QString destinationPrefix = "", - bool followSymlinks = false) - : m_output(output), m_dir(dir), m_files(files), m_destinationPrefix(destinationPrefix), m_followSymlinks(followSymlinks) + ExportToZipTask(QString outputPath, QDir dir, QFileInfoList files, QString destinationPrefix = "", bool followSymlinks = false) + : m_output(outputPath), m_dir(dir), m_files(files), m_destination_prefix(destinationPrefix), m_follow_symlinks(followSymlinks) { setAbortable(true); }; ExportToZipTask(QString outputPath, QString dir, QFileInfoList files, QString destinationPrefix = "", bool followSymlinks = false) - : ExportToZipTask(std::make_shared(outputPath), QDir(dir), files, destinationPrefix, followSymlinks){}; + : ExportToZipTask(outputPath, QDir(dir), files, destinationPrefix, followSymlinks){}; virtual ~ExportToZipTask() = default; + void setExcludeFiles(QStringList excludeFiles) { m_exclude_files = excludeFiles; } + void addExtraFile(QString fileName, QByteArray data) { m_extra_files.emplace(fileName, data); } + protected: virtual void executeTask() override; + void exportZip(); private: - std::shared_ptr m_output; + QuaZip m_output; QDir m_dir; QFileInfoList m_files; - QString m_destinationPrefix; - bool m_followSymlinks; + QString m_destination_prefix; + bool m_follow_symlinks; + QStringList m_exclude_files; + QHash m_extra_files; }; } // namespace MMCZip From fe73d696cb714d724948176f0bfbb356412b0f11 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Mon, 17 Jul 2023 16:57:52 +0300 Subject: [PATCH 187/216] replace emplace with insert Signed-off-by: Trial97 --- launcher/MMCZip.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/MMCZip.h b/launcher/MMCZip.h index 60b3490fe..ce76bc773 100644 --- a/launcher/MMCZip.h +++ b/launcher/MMCZip.h @@ -158,7 +158,7 @@ class ExportToZipTask : public Task { virtual ~ExportToZipTask() = default; void setExcludeFiles(QStringList excludeFiles) { m_exclude_files = excludeFiles; } - void addExtraFile(QString fileName, QByteArray data) { m_extra_files.emplace(fileName, data); } + void addExtraFile(QString fileName, QByteArray data) { m_extra_files.insert(fileName, data); } protected: virtual void executeTask() override; From b0940d696baa24ddcf29a5d3393196c1047dcd3f Mon Sep 17 00:00:00 2001 From: Trial97 Date: Mon, 17 Jul 2023 17:42:15 +0300 Subject: [PATCH 188/216] Added QFutureWatcher Signed-off-by: Trial97 abort forgot Signed-off-by: Trial97 --- launcher/MMCZip.cpp | 61 +++++++++++++------- launcher/MMCZip.h | 20 ++++++- launcher/ui/dialogs/ExportInstanceDialog.cpp | 7 +-- 3 files changed, 61 insertions(+), 27 deletions(-) diff --git a/launcher/MMCZip.cpp b/launcher/MMCZip.cpp index cc7491971..acd6bf7e4 100644 --- a/launcher/MMCZip.cpp +++ b/launcher/MMCZip.cpp @@ -423,37 +423,36 @@ bool collectFileListRecursively(const QString& rootDir, const QString& subDir, Q } void ExportToZipTask::executeTask() -{ - (void)QtConcurrent::run(QThreadPool::globalInstance(), [this]() { exportZip(); }); -} - -void ExportToZipTask::exportZip() { setStatus("Adding files..."); setProgress(0, m_files.length()); + m_build_zip_future = QtConcurrent::run(QThreadPool::globalInstance(), [this]() { return exportZip(); }); + connect(&m_build_zip_watcher, &QFutureWatcher::finished, this, &ExportToZipTask::finish); + m_build_zip_watcher.setFuture(m_build_zip_future); +} + +auto ExportToZipTask::exportZip() -> ZipResult +{ if (!m_dir.exists()) { - emitFailed(tr("Folder doesn't exist")); - return; + return ZipResult(tr("Folder doesn't exist")); } if (!m_output.isOpen() && !m_output.open(QuaZip::mdCreate)) { - emitFailed(tr("Could not create file")); - return; + return ZipResult(tr("Could not create file")); } for (auto fileName : m_extra_files.keys()) { - if (!isRunning()) - return; + if (m_build_zip_future.isCanceled()) + return ZipResult(); QuaZipFile indexFile(&m_output); if (!indexFile.open(QIODevice::WriteOnly, QuaZipNewInfo(fileName))) { - emitFailed(tr("Could not create:") + fileName); - return; + return ZipResult(tr("Could not create:") + fileName); } indexFile.write(m_extra_files[fileName]); } for (const QFileInfo& file : m_files) { - if (!isRunning()) - return; + if (m_build_zip_future.isCanceled()) + return ZipResult(); auto absolute = file.absoluteFilePath(); auto relative = m_dir.relativeFilePath(absolute); @@ -467,17 +466,39 @@ void ExportToZipTask::exportZip() } if (!m_exclude_files.contains(relative) && !JlCompress::compressFile(&m_output, absolute, m_destination_prefix + relative)) { - emitFailed(tr("Could not read and compress %1").arg(relative)); - return; + return ZipResult(tr("Could not read and compress %1").arg(relative)); } } m_output.close(); if (m_output.getZipError() != 0) { - emitFailed(tr("A zip error occurred")); - return; + return ZipResult(tr("A zip error occurred")); } - emitSucceeded(); + return ZipResult(); +} + +void ExportToZipTask::finish() +{ + if (m_build_zip_future.isCanceled()) { + QFile::remove(m_output_path); + emitAborted(); + } else if (auto result = m_build_zip_future.result(); result.has_value()) { + QFile::remove(m_output_path); + emitFailed(result.value()); + } else { + emitSucceeded(); + } +} + +bool ExportToZipTask::abort() +{ + if (m_build_zip_future.isRunning()) { + m_build_zip_future.cancel(); + // NOTE: Here we don't do `emitAborted()` because it will be done when `m_build_zip_future` actually cancels, which may not occur + // immediately. + return true; + } + return false; } } // namespace MMCZip \ No newline at end of file diff --git a/launcher/MMCZip.h b/launcher/MMCZip.h index ce76bc773..bc527ad1b 100644 --- a/launcher/MMCZip.h +++ b/launcher/MMCZip.h @@ -40,6 +40,8 @@ #include #include #include +#include +#include #include #include #include @@ -148,7 +150,12 @@ bool collectFileListRecursively(const QString& rootDir, const QString& subDir, Q class ExportToZipTask : public Task { public: ExportToZipTask(QString outputPath, QDir dir, QFileInfoList files, QString destinationPrefix = "", bool followSymlinks = false) - : m_output(outputPath), m_dir(dir), m_files(files), m_destination_prefix(destinationPrefix), m_follow_symlinks(followSymlinks) + : m_output_path(outputPath) + , m_output(outputPath) + , m_dir(dir) + , m_files(files) + , m_destination_prefix(destinationPrefix) + , m_follow_symlinks(followSymlinks) { setAbortable(true); }; @@ -160,11 +167,17 @@ class ExportToZipTask : public Task { void setExcludeFiles(QStringList excludeFiles) { m_exclude_files = excludeFiles; } void addExtraFile(QString fileName, QByteArray data) { m_extra_files.insert(fileName, data); } + typedef std::optional ZipResult; + protected: virtual void executeTask() override; - void exportZip(); + bool abort() override; + + ZipResult exportZip(); + void finish(); private: + QString m_output_path; QuaZip m_output; QDir m_dir; QFileInfoList m_files; @@ -172,5 +185,8 @@ class ExportToZipTask : public Task { bool m_follow_symlinks; QStringList m_exclude_files; QHash m_extra_files; + + QFuture m_build_zip_future; + QFutureWatcher m_build_zip_watcher; }; } // namespace MMCZip diff --git a/launcher/ui/dialogs/ExportInstanceDialog.cpp b/launcher/ui/dialogs/ExportInstanceDialog.cpp index 1a3f8cd41..d1a69b932 100644 --- a/launcher/ui/dialogs/ExportInstanceDialog.cpp +++ b/launcher/ui/dialogs/ExportInstanceDialog.cpp @@ -146,11 +146,8 @@ void ExportInstanceDialog::doExport() auto task = makeShared(output, m_instance->instanceRoot(), files, "", true); - connect(task.get(), &Task::failed, this, [this, output](QString reason) { - CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->show(); - QFile::remove(output); - }); - connect(task.get(), &Task::aborted, this, [output] { QFile::remove(output); }); + connect(task.get(), &Task::failed, this, + [this, output](QString reason) { CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->show(); }); connect(task.get(), &Task::finished, this, [task] { task->deleteLater(); }); ProgressDialog progress(this); From 1fbb41f5e2c4426b1b1e469c78cfbc7e1c4d7999 Mon Sep 17 00:00:00 2001 From: Josiah Glosson Date: Mon, 17 Jul 2023 17:07:06 -0500 Subject: [PATCH 189/216] Make Launch Offline not launch online in 1.6+ Signed-off-by: Josiah Glosson --- launcher/minecraft/auth/AuthSession.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/launcher/minecraft/auth/AuthSession.cpp b/launcher/minecraft/auth/AuthSession.cpp index 6bea74a37..2c06beaa2 100644 --- a/launcher/minecraft/auth/AuthSession.cpp +++ b/launcher/minecraft/auth/AuthSession.cpp @@ -26,6 +26,7 @@ bool AuthSession::MakeOffline(QString offline_playername) return false; } session = "-"; + access_token = "0"; player_name = offline_playername; status = PlayableOffline; return true; From 2eff1de560c9b4ac76316d2c6d812438b4488222 Mon Sep 17 00:00:00 2001 From: Dallas Strouse Date: Mon, 17 Jul 2023 00:29:24 -0500 Subject: [PATCH 190/216] Update Flatpak manifest Signed-off-by: Dallas Strouse --- .gitmodules | 3 + flatpak/libdecor.json | 22 ++++ flatpak/org.prismlauncher.PrismLauncher.yml | 115 ++++++++++++++---- ...on-t-crash-on-calls-to-focus-or-icon.patch | 24 ++++ ...ning-about-being-an-unofficial-patch.patch | 17 +++ ...007-Platform-Prefer-Wayland-over-X11.patch | 20 +++ flatpak/patches/weird_libdecor.patch | 40 ++++++ flatpak/prismlauncher | 4 +- flatpak/shared-modules | 1 + 9 files changed, 222 insertions(+), 24 deletions(-) create mode 100644 flatpak/libdecor.json create mode 100644 flatpak/patches/0003-Don-t-crash-on-calls-to-focus-or-icon.patch create mode 100644 flatpak/patches/0005-Add-warning-about-being-an-unofficial-patch.patch create mode 100644 flatpak/patches/0007-Platform-Prefer-Wayland-over-X11.patch create mode 100644 flatpak/patches/weird_libdecor.patch create mode 160000 flatpak/shared-modules diff --git a/.gitmodules b/.gitmodules index 87703fee5..0f437d277 100644 --- a/.gitmodules +++ b/.gitmodules @@ -19,3 +19,6 @@ [submodule "libraries/cmark"] path = libraries/cmark url = https://github.com/commonmark/cmark.git +[submodule "flatpak/shared-modules"] + path = flatpak/shared-modules + url = https://github.com/flathub/shared-modules.git diff --git a/flatpak/libdecor.json b/flatpak/libdecor.json new file mode 100644 index 000000000..12afad69f --- /dev/null +++ b/flatpak/libdecor.json @@ -0,0 +1,22 @@ +{ + "name": "libdecor", + "buildsystem": "meson", + "config-opts": [ + "-Ddemo=false" + ], + "sources": [ + { + "type": "git", + "url": "https://gitlab.freedesktop.org/libdecor/libdecor.git", + "commit": "73260393a97291c887e1074ab7f318e031be0ac6" + }, + { + "type": "patch", + "path": "patches/weird_libdecor.patch" + } + ], + "cleanup": [ + "/include", + "/lib/pkgconfig" + ] +} diff --git a/flatpak/org.prismlauncher.PrismLauncher.yml b/flatpak/org.prismlauncher.PrismLauncher.yml index 0524946f0..a9b9762f5 100644 --- a/flatpak/org.prismlauncher.PrismLauncher.yml +++ b/flatpak/org.prismlauncher.PrismLauncher.yml @@ -5,13 +5,6 @@ sdk: org.kde.Sdk sdk-extensions: - org.freedesktop.Sdk.Extension.openjdk17 - org.freedesktop.Sdk.Extension.openjdk8 -add-extensions: - com.valvesoftware.Steam.Utility.gamescope: - version: stable - add-ld-path: lib - no-autodownload: true - autodelete: false - directory: utils/gamescope command: prismlauncher finish-args: @@ -26,21 +19,31 @@ finish-args: # Mod drag&drop - --filesystem=xdg-download:ro +cleanup: + - /lib/libGLU* + modules: + # Might be needed by some Controller mods (see https://github.com/isXander/Controlify/issues/31) + - shared-modules/libusb/libusb.json + + # Needed for proper Wayland support + - libdecor.json + - name: prismlauncher buildsystem: cmake-ninja + builddir: true config-opts: - -DLauncher_BUILD_PLATFORM=flatpak - - -DCMAKE_BUILD_TYPE=Debug + - -DCMAKE_BUILD_TYPE=RelWithDebInfo - -DLauncher_QT_VERSION_MAJOR=5 build-options: env: JAVA_HOME: /usr/lib/sdk/openjdk17/jvm/openjdk-17 JAVA_COMPILER: /usr/lib/sdk/openjdk17/jvm/openjdk-17/bin/javac sources: - - type: dir - path: ../ - builddir: true + - type: dir + path: ../ + - name: openjdk buildsystem: simple build-commands: @@ -49,14 +52,45 @@ modules: - mv /app/jre /app/jdk/17 - /usr/lib/sdk/openjdk8/install.sh - mv /app/jre /app/jdk/8 - cleanup: [/jre] + cleanup: + - /jre + + - name: glfw + buildsystem: cmake-ninja + config-opts: + - -DCMAKE_BUILD_TYPE=RelWithDebInfo + - -DBUILD_SHARED_LIBS:BOOL=ON + - -DGLFW_USE_WAYLAND=ON + sources: + - type: git + url: https://github.com/glfw/glfw.git + commit: 3fa2360720eeba1964df3c0ecf4b5df8648a8e52 + - type: patch + path: patches/0003-Don-t-crash-on-calls-to-focus-or-icon.patch + - type: patch + path: patches/0005-Add-warning-about-being-an-unofficial-patch.patch + - type: patch + path: patches/0007-Platform-Prefer-Wayland-over-X11.patch + cleanup: + - /include + - /lib/cmake + - /lib/pkgconfig + - name: xrandr buildsystem: autotools sources: - type: archive - url: https://xorg.freedesktop.org/archive/individual/app/xrandr-1.5.1.tar.xz - sha256: 7bc76daf9d72f8aff885efad04ce06b90488a1a169d118dea8a2b661832e8762 - cleanup: [/share/man, /bin/xkeystone] + url: https://xorg.freedesktop.org/archive/individual/app/xrandr-1.5.2.tar.xz + sha256: c8bee4790d9058bacc4b6246456c58021db58a87ddda1a9d0139bf5f18f1f240 + x-checker-data: + type: anitya + project-id: 14957 + stable-only: true + url-template: https://xorg.freedesktop.org/archive/individual/app/xrandr-$version.tar.xz + cleanup: + - /share/man + - /bin/xkeystone + - name: gamemode buildsystem: meson config-opts: @@ -67,19 +101,56 @@ modules: # post-install is running inside the build dir, we need it from the source though - install -Dm755 ../data/gamemoderun -t /app/bin sources: - - type: git - url: https://github.com/FeralInteractive/gamemode - tag: "1.7" - commit: 4dc99dff76218718763a6b07fc1900fa6d1dafd9 + - type: archive + archive-type: tar-gzip + url: https://api.github.com/repos/FeralInteractive/gamemode/tarball/1.7 + sha256: 57ce73ba605d1cf12f8d13725006a895182308d93eba0f69f285648449641803 + x-checker-data: + type: json + url: https://api.github.com/repos/FeralInteractive/gamemode/releases/latest + version-query: .tag_name + url-query: .tarball_url + timestamp-query: .published_at + cleanup: + - /include + - /lib/pkgconfig + - /lib/libgamemodeauto.a + + - name: glxinfo + buildsystem: meson + config-opts: + - --bindir=/app/mesa-demos + - -Degl=disabled + - -Dglut=disabled + - -Dosmesa=disabled + - -Dvulkan=disabled + - -Dwayland=disabled + post-install: + - mv -v /app/mesa-demos/glxinfo /app/bin + sources: + - type: archive + url: https://archive.mesa3d.org/demos/mesa-demos-9.0.0.tar.xz + sha256: 3046a3d26a7b051af7ebdd257a5f23bfeb160cad6ed952329cdff1e9f1ed496b + x-checker-data: + type: anitya + project-id: 16781 + stable-only: true + url-template: https://archive.mesa3d.org/demos/mesa-demos-$version.tar.xz + cleanup: + - /include + - /mesa-demos + - /share + modules: + - shared-modules/glu/glu-9.json + - name: enhance buildsystem: simple build-commands: - - mkdir -p /app/utils/gamescope - install -Dm755 prime-run /app/bin/prime-run - mv /app/bin/prismlauncher /app/bin/prismrun - install -Dm755 prismlauncher /app/bin/prismlauncher sources: - type: file - path: ../flatpak/prime-run + path: prime-run - type: file - path: ../flatpak/prismlauncher + path: prismlauncher diff --git a/flatpak/patches/0003-Don-t-crash-on-calls-to-focus-or-icon.patch b/flatpak/patches/0003-Don-t-crash-on-calls-to-focus-or-icon.patch new file mode 100644 index 000000000..9130e856c --- /dev/null +++ b/flatpak/patches/0003-Don-t-crash-on-calls-to-focus-or-icon.patch @@ -0,0 +1,24 @@ +diff --git a/src/wl_window.c b/src/wl_window.c +index 52d3b9eb..4ac4eb5d 100644 +--- a/src/wl_window.c ++++ b/src/wl_window.c +@@ -2117,8 +2117,7 @@ void _glfwSetWindowTitleWayland(_GLFWwindow* window, const char* title) + void _glfwSetWindowIconWayland(_GLFWwindow* window, + int count, const GLFWimage* images) + { +- _glfwInputError(GLFW_FEATURE_UNAVAILABLE, +- "Wayland: The platform does not support setting the window icon"); ++ fprintf(stderr, "!!! Ignoring Error: Wayland: The platform does not support setting the window icon\n"); + } + + void _glfwGetWindowPosWayland(_GLFWwindow* window, int* xpos, int* ypos) +@@ -2361,8 +2360,7 @@ void _glfwRequestWindowAttentionWayland(_GLFWwindow* window) + + void _glfwFocusWindowWayland(_GLFWwindow* window) + { +- _glfwInputError(GLFW_FEATURE_UNAVAILABLE, +- "Wayland: The platform does not support setting the input focus"); ++ fprintf(stderr, "!!! Ignoring Error: Wayland: The platform does not support setting the input focus\n"); + } + + void _glfwSetWindowMonitorWayland(_GLFWwindow* window, diff --git a/flatpak/patches/0005-Add-warning-about-being-an-unofficial-patch.patch b/flatpak/patches/0005-Add-warning-about-being-an-unofficial-patch.patch new file mode 100644 index 000000000..b031d739f --- /dev/null +++ b/flatpak/patches/0005-Add-warning-about-being-an-unofficial-patch.patch @@ -0,0 +1,17 @@ +diff --git a/src/init.c b/src/init.c +index 06dbb3f2..a7c6da86 100644 +--- a/src/init.c ++++ b/src/init.c +@@ -449,6 +449,12 @@ GLFWAPI int glfwInit(void) + _glfw.initialized = GLFW_TRUE; + + glfwDefaultWindowHints(); ++ ++ fprintf(stderr, "!!! Patched GLFW from https://github.com/Admicos/minecraft-wayland\n" ++ "!!! If any issues with the window, or some issues with rendering, occur, " ++ "first try with the built-in GLFW, and if that solves the issue, report there first.\n" ++ "!!! Use outside Minecraft is untested, and things might break.\n"); ++ + return GLFW_TRUE; + } + diff --git a/flatpak/patches/0007-Platform-Prefer-Wayland-over-X11.patch b/flatpak/patches/0007-Platform-Prefer-Wayland-over-X11.patch new file mode 100644 index 000000000..4eeb81309 --- /dev/null +++ b/flatpak/patches/0007-Platform-Prefer-Wayland-over-X11.patch @@ -0,0 +1,20 @@ +diff --git a/src/platform.c b/src/platform.c +index c5966ae7..3e7442f9 100644 +--- a/src/platform.c ++++ b/src/platform.c +@@ -49,12 +49,12 @@ static const struct + #if defined(_GLFW_COCOA) + { GLFW_PLATFORM_COCOA, _glfwConnectCocoa }, + #endif +-#if defined(_GLFW_X11) +- { GLFW_PLATFORM_X11, _glfwConnectX11 }, +-#endif + #if defined(_GLFW_WAYLAND) + { GLFW_PLATFORM_WAYLAND, _glfwConnectWayland }, + #endif ++#if defined(_GLFW_X11) ++ { GLFW_PLATFORM_X11, _glfwConnectX11 }, ++#endif + }; + + GLFWbool _glfwSelectPlatform(int desiredID, _GLFWplatform* platform) diff --git a/flatpak/patches/weird_libdecor.patch b/flatpak/patches/weird_libdecor.patch new file mode 100644 index 000000000..3a400b820 --- /dev/null +++ b/flatpak/patches/weird_libdecor.patch @@ -0,0 +1,40 @@ +diff --git a/src/libdecor.c b/src/libdecor.c +index a9c1106..1aa38b3 100644 +--- a/src/libdecor.c ++++ b/src/libdecor.c +@@ -1391,22 +1391,32 @@ calculate_priority(const struct libdecor_plugin_description *plugin_description) + static bool + check_symbol_conflicts(const struct libdecor_plugin_description *plugin_description) + { ++ bool ret = true; + char * const *symbol; ++ void* main_prog = dlopen(NULL, RTLD_LAZY); ++ if (!main_prog) { ++ fprintf(stderr, "Plugin \"%s\" couldn't check conflicting symbols: \"%s\".\n", ++ plugin_description->description, dlerror()); ++ return false; ++ } ++ + + symbol = plugin_description->conflicting_symbols; + while (*symbol) { + dlerror(); +- dlsym (RTLD_DEFAULT, *symbol); ++ dlsym (main_prog, *symbol); + if (!dlerror()) { + fprintf(stderr, "Plugin \"%s\" uses conflicting symbol \"%s\".\n", + plugin_description->description, *symbol); +- return false; ++ ret = false; ++ break; + } + + symbol++; + } + +- return true; ++ dlclose(main_prog); ++ return ret; + } + + static struct plugin_loader * diff --git a/flatpak/prismlauncher b/flatpak/prismlauncher index bb8767113..039d890d2 100644 --- a/flatpak/prismlauncher +++ b/flatpak/prismlauncher @@ -5,7 +5,7 @@ for i in {0..9}; do test -S "$XDG_RUNTIME_DIR"/discord-ipc-"$i" || ln -sf {app/com.discordapp.Discord,"$XDG_RUNTIME_DIR"}/discord-ipc-"$i"; done -export PATH="${PATH}${PATH:+:}/app/utils/gamescope/bin:/usr/lib/extensions/vulkan/MangoHud/bin" -export LD_LIBRARY_PATH="${LD_LIBRARY_PATH}${LD_LIBRARY_PATH:+:}/usr/lib/extensions/vulkan/MangoHud/\$LIB/" +export PATH="${PATH}${PATH:+:}/usr/lib/extensions/vulkan/gamescope/bin:/usr/lib/extensions/vulkan/MangoHud/bin" +export VK_LAYER_PATH="/usr/lib/extensions/vulkan/share/vulkan/implicit_layer.d/" exec /app/bin/prismrun "$@" diff --git a/flatpak/shared-modules b/flatpak/shared-modules new file mode 160000 index 000000000..45094ca57 --- /dev/null +++ b/flatpak/shared-modules @@ -0,0 +1 @@ +Subproject commit 45094ca570be383d06df729b6972830ec63bd3df From f8fcb98c6837c0bf66c2175ea98198449c36b165 Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Tue, 18 Jul 2023 09:06:49 +0200 Subject: [PATCH 191/216] fix: generate predictable UUIDs for offline accounts Signed-off-by: Sefa Eyeoglu --- launcher/minecraft/auth/MinecraftAccount.cpp | 32 +++++++++++++++++++- launcher/minecraft/auth/MinecraftAccount.h | 2 ++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/launcher/minecraft/auth/MinecraftAccount.cpp b/launcher/minecraft/auth/MinecraftAccount.cpp index 3b050ac0f..d7b061e5e 100644 --- a/launcher/minecraft/auth/MinecraftAccount.cpp +++ b/launcher/minecraft/auth/MinecraftAccount.cpp @@ -37,6 +37,7 @@ #include "MinecraftAccount.h" +#include #include #include #include @@ -100,7 +101,7 @@ MinecraftAccountPtr MinecraftAccount::createOffline(const QString &username) account->data.yggdrasilToken.extra["clientToken"] = QUuid::createUuid().toString().remove(QRegularExpression("[{}-]")); account->data.minecraftEntitlement.ownsMinecraft = true; account->data.minecraftEntitlement.canPlayMinecraft = true; - account->data.minecraftProfile.id = QUuid::createUuid().toString().remove(QRegularExpression("[{}-]")); + account->data.minecraftProfile.id = uuidFromUsername(username).toString().remove(QRegularExpression("[{}-]")); account->data.minecraftProfile.name = username; account->data.minecraftProfile.validity = Katabasis::Validity::Certain; return account; @@ -334,3 +335,32 @@ void MinecraftAccount::incrementUses() qWarning() << "Profile" << data.profileId() << "is now in use."; } } + +QUuid MinecraftAccount::uuidFromUsername(QString username) { + auto input = QString("OfflinePlayer:%1").arg(username).toUtf8(); + + // basically a reimplementation of Java's UUID#nameUUIDFromBytes + QByteArray digest = QCryptographicHash::hash(input, QCryptographicHash::Md5); + +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) + auto bOr = [](QByteArray& array, int index, char value) { + array[index] = array.at(index) | value; + }; + auto bAnd = [](QByteArray& array, int index, char value) { + array[index] = array.at(index) & value; + }; +#else + auto bOr = [](QByteArray& array, qsizetype index, char value) { + array[index] |= value; + }; + auto bAnd = [](QByteArray& array, qsizetype index, char value) { + array[index] &= value; + }; +#endif + bAnd(digest, 6, (char) 0x0f); // clear version + bOr(digest, 6, (char) 0x30); // set to version 3 + bAnd(digest, 8, (char) 0x3f); // clear variant + bOr(digest, 8, (char) 0x80); // set to IETF variant + + return QUuid::fromRfc4122(digest); +} diff --git a/launcher/minecraft/auth/MinecraftAccount.h b/launcher/minecraft/auth/MinecraftAccount.h index 0dcaeb531..67623a5ab 100644 --- a/launcher/minecraft/auth/MinecraftAccount.h +++ b/launcher/minecraft/auth/MinecraftAccount.h @@ -98,6 +98,8 @@ public: /* construction */ static MinecraftAccountPtr loadFromJsonV2(const QJsonObject &json); static MinecraftAccountPtr loadFromJsonV3(const QJsonObject &json); + static QUuid uuidFromUsername(QString username); + //! Saves a MinecraftAccount to a JSON object and returns it. QJsonObject saveToJson() const; From 391497645ff2054dbc1eac48c8bc49133b86b319 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Tue, 18 Jul 2023 22:33:39 +0300 Subject: [PATCH 192/216] feat:made flame instace creation use metadata for recommended version Signed-off-by: Trial97 --- .../flame/FlameInstanceCreationTask.cpp | 116 ++++++++++++------ .../flame/FlameInstanceCreationTask.h | 6 +- 2 files changed, 80 insertions(+), 42 deletions(-) diff --git a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp index b57db288a..710ec06ac 100644 --- a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp +++ b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp @@ -57,15 +57,11 @@ #include #include +#include "meta/Index.h" +#include "meta/VersionList.h" #include "minecraft/World.h" #include "minecraft/mod/tasks/LocalResourceParse.h" - -const static QMap forgemap = { { "1.2.5", "3.4.9.171" }, - { "1.4.2", "6.0.1.355" }, - { "1.4.7", "6.6.2.534" }, - { "1.5.2", "7.8.1.737" } }; - static const FlameAPI api; bool FlameCreationTask::abort() @@ -259,6 +255,51 @@ bool FlameCreationTask::updateInstance() return false; } +QString FlameCreationTask::getVersionForLoader(QString uid, QString loaderType, QString version, QString mcVersion) +{ + if (version == "recommended") { + auto vlist = APPLICATION->metadataIndex()->get(uid); + if (!vlist) { + setError(tr("Failed to get local metadata index for %1").arg(uid)); + return Q_NULLPTR; + } + + if (!vlist->isLoaded()) { + vlist->load(Net::Mode::Online); + } + + for (int i = 0; i < vlist->versions().size(); i++) { + auto version = vlist->versions().at(i); + // first recommended build we find, we use. + if (!version->isRecommended()) + continue; + auto reqs = version->requiredSet(); + + // filter by minecraft version, if the loader depends on a certain version. + // not all mod loaders depend on a given Minecraft version, so we won't do this + // filtering for those loaders. + if (loaderType == "forge") { + auto iter = std::find_if(reqs.begin(), reqs.end(), [mcVersion](const Meta::Require& req) { + return req.uid == "net.minecraft" && req.equalsVersion == mcVersion; + }); + if (iter == reqs.end()) + continue; + } + return version->descriptor(); + } + + setError(tr("Failed to find version for %1 loader").arg(loaderType)); + return Q_NULLPTR; + } + + if (version == Q_NULLPTR || version.isEmpty()) { + emitFailed(tr("No loader version set for modpack!")); + return Q_NULLPTR; + } + + return version; +} + bool FlameCreationTask::createInstance() { QEventLoop loop; @@ -297,22 +338,29 @@ bool FlameCreationTask::createInstance() } } - QString forgeVersion; - QString fabricVersion; - // TODO: is Quilt relevant here? + QString loaderType; + QString loaderUid; + QString loaderVersion; + for (auto& loader : m_pack.minecraft.modLoaders) { auto id = loader.id; if (id.startsWith("forge-")) { id.remove("forge-"); - forgeVersion = id; - continue; - } - if (id.startsWith("fabric-")) { + loaderType = "forge"; + loaderUid = "net.minecraftforge"; + } else if (loaderType == "fabric") { id.remove("fabric-"); - fabricVersion = id; + loaderType = "fabric"; + loaderUid = "net.fabricmc.fabric-loader"; + } else if (loaderType == "quilt") { + id.remove("quilt-"); + loaderType = "quilt"; + loaderUid = "org.quiltmc.quilt-loader"; + } else { + logWarning(tr("Unknown mod loader in manifest: %1").arg(id)); continue; } - logWarning(tr("Unknown mod loader in manifest: %1").arg(id)); + loaderVersion = id; } QString configPath = FS::PathCombine(m_stagingPath, "instance.cfg"); @@ -329,19 +377,12 @@ bool FlameCreationTask::createInstance() auto components = instance.getPackProfile(); components->buildingFromScratch(); components->setComponentVersion("net.minecraft", mcVersion, true); - if (!forgeVersion.isEmpty()) { - // FIXME: dirty, nasty, hack. Proper solution requires dependency resolution and knowledge of the metadata. - if (forgeVersion == "recommended") { - if (forgemap.contains(mcVersion)) { - forgeVersion = forgemap[mcVersion]; - } else { - logWarning(tr("Could not map recommended Forge version for Minecraft %1").arg(mcVersion)); - } - } - components->setComponentVersion("net.minecraftforge", forgeVersion); + if (!loaderType.isEmpty()) { + auto version = getVersionForLoader(loaderUid, loaderType, loaderVersion, mcVersion); + if (version == Q_NULLPTR || version.isEmpty()) + return false; + components->setComponentVersion(loaderUid, version); } - if (!fabricVersion.isEmpty()) - components->setComponentVersion("net.fabricmc.fabric-loader", fabricVersion); if (m_instIcon != "default") { instance.setIconKey(m_instIcon); @@ -502,7 +543,7 @@ void FlameCreationTask::setupDownloadJob(QEventLoop& loop) m_files_job.reset(); setError(reason); }); - connect(m_files_job.get(), &NetJob::progress, this, [this](qint64 current, qint64 total){ + connect(m_files_job.get(), &NetJob::progress, this, [this](qint64 current, qint64 total) { setDetails(tr("%1 out of %2 complete").arg(current).arg(total)); setProgress(current, total); }); @@ -545,7 +586,6 @@ void FlameCreationTask::copyBlockedMods(QList const& blocked_mods) setAbortable(true); } - void FlameCreationTask::validateZIPResouces() { qDebug() << "Validating whether resources stored as .zip are in the right place"; @@ -569,7 +609,7 @@ void FlameCreationTask::validateZIPResouces() return localPath; }; - auto installWorld = [this](QString worldPath){ + auto installWorld = [this](QString worldPath) { qDebug() << "Installing World from" << worldPath; QFileInfo worldFileInfo(worldPath); World w(worldFileInfo); @@ -586,29 +626,29 @@ void FlameCreationTask::validateZIPResouces() QString worldPath; switch (type) { - case PackedResourceType::Mod : + case PackedResourceType::Mod: validatePath(fileName, targetFolder, "mods"); break; - case PackedResourceType::ResourcePack : + case PackedResourceType::ResourcePack: validatePath(fileName, targetFolder, "resourcepacks"); break; - case PackedResourceType::TexturePack : + case PackedResourceType::TexturePack: validatePath(fileName, targetFolder, "texturepacks"); break; - case PackedResourceType::DataPack : + case PackedResourceType::DataPack: validatePath(fileName, targetFolder, "datapacks"); break; - case PackedResourceType::ShaderPack : + case PackedResourceType::ShaderPack: // in theroy flame API can't do this but who knows, that *may* change ? // better to handle it if it *does* occure in the future validatePath(fileName, targetFolder, "shaderpacks"); break; - case PackedResourceType::WorldSave : + case PackedResourceType::WorldSave: worldPath = validatePath(fileName, targetFolder, "saves"); installWorld(worldPath); break; - case PackedResourceType::UNKNOWN : - default : + case PackedResourceType::UNKNOWN: + default: qDebug() << "Can't Identify" << fileName << "at" << localPath << ", leaving it where it is."; break; } diff --git a/launcher/modplatform/flame/FlameInstanceCreationTask.h b/launcher/modplatform/flame/FlameInstanceCreationTask.h index 0ae4735bf..603d3693e 100644 --- a/launcher/modplatform/flame/FlameInstanceCreationTask.h +++ b/launcher/modplatform/flame/FlameInstanceCreationTask.h @@ -57,10 +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_managed_id(std::move(id)), m_managed_version_id(std::move(version_id)) { setStagingPath(staging_path); setParentSettings(global_settings); @@ -78,6 +75,7 @@ class FlameCreationTask final : public InstanceCreationTask { void setupDownloadJob(QEventLoop&); void copyBlockedMods(QList const& blocked_mods); void validateZIPResouces(); + QString getVersionForLoader(QString uid, QString loaderType, QString version, QString mcVersion); private: QWidget* m_parent = nullptr; From f393aa684e74ca870eb2108e2b74a7c93a70c366 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Tue, 18 Jul 2023 23:59:43 +0300 Subject: [PATCH 193/216] wait to load metadata Signed-off-by: Trial97 --- .../flame/FlameInstanceCreationTask.cpp | 24 ++++++++++++------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp index 710ec06ac..e8453c603 100644 --- a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp +++ b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp @@ -255,17 +255,23 @@ bool FlameCreationTask::updateInstance() return false; } -QString FlameCreationTask::getVersionForLoader(QString uid, QString loaderType, QString version, QString mcVersion) +QString FlameCreationTask::getVersionForLoader(QString uid, QString loaderType, QString loaderVersion, QString mcVersion) { - if (version == "recommended") { + if (loaderVersion == "recommended") { auto vlist = APPLICATION->metadataIndex()->get(uid); if (!vlist) { setError(tr("Failed to get local metadata index for %1").arg(uid)); - return Q_NULLPTR; + return {}; } if (!vlist->isLoaded()) { - vlist->load(Net::Mode::Online); + QEventLoop loadVersionLoop; + auto task = vlist->getLoadTask(); + connect(task.get(), &Task::finished, &loadVersionLoop, &QEventLoop::quit); + if (!task->isRunning()) + task->start(); + + loadVersionLoop.exec(); } for (int i = 0; i < vlist->versions().size(); i++) { @@ -289,15 +295,15 @@ QString FlameCreationTask::getVersionForLoader(QString uid, QString loaderType, } setError(tr("Failed to find version for %1 loader").arg(loaderType)); - return Q_NULLPTR; + return {}; } - if (version == Q_NULLPTR || version.isEmpty()) { + if (loaderVersion.isEmpty()) { emitFailed(tr("No loader version set for modpack!")); - return Q_NULLPTR; + return {}; } - return version; + return loaderVersion; } bool FlameCreationTask::createInstance() @@ -379,7 +385,7 @@ bool FlameCreationTask::createInstance() components->setComponentVersion("net.minecraft", mcVersion, true); if (!loaderType.isEmpty()) { auto version = getVersionForLoader(loaderUid, loaderType, loaderVersion, mcVersion); - if (version == Q_NULLPTR || version.isEmpty()) + if (version.isEmpty()) return false; components->setComponentVersion(loaderUid, version); } From b7bccb905829eebea039a32edf93606f5fc5defa Mon Sep 17 00:00:00 2001 From: Trial97 Date: Wed, 19 Jul 2023 12:27:02 +0300 Subject: [PATCH 194/216] removed subdirectory flag Signed-off-by: Trial97 --- launcher/ui/themes/ThemeManager.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/launcher/ui/themes/ThemeManager.cpp b/launcher/ui/themes/ThemeManager.cpp index 9ed8e1297..321f7db4a 100644 --- a/launcher/ui/themes/ThemeManager.cpp +++ b/launcher/ui/themes/ThemeManager.cpp @@ -84,7 +84,7 @@ void ThemeManager::initializeThemes() QString themeFolder = QDir("./themes/").absoluteFilePath(""); themeDebugLog() << "Theme Folder Path: " << themeFolder; - QDirIterator directoryIterator(themeFolder, QDir::Dirs | QDir::NoDotAndDotDot, QDirIterator::Subdirectories); + QDirIterator directoryIterator(themeFolder, QDir::Dirs | QDir::NoDotAndDotDot); while (directoryIterator.hasNext()) { QDir dir(directoryIterator.next()); QFileInfo themeJson(dir.absoluteFilePath("theme.json")); @@ -208,7 +208,7 @@ void ThemeManager::initializeCatPacks() loadFiles(catpacksDir); - QDirIterator directoryIterator(catpacksFolder, QDir::Dirs | QDir::NoDotAndDotDot, QDirIterator::Subdirectories); + QDirIterator directoryIterator(catpacksFolder, QDir::Dirs | QDir::NoDotAndDotDot); while (directoryIterator.hasNext()) { QDir dir(directoryIterator.next()); QFileInfo manifest(dir.absoluteFilePath("catpack.json")); From f8d9cd9a0344d8afa806e7b3b73e8b3c59315d17 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Wed, 19 Jul 2023 23:08:16 +0300 Subject: [PATCH 195/216] use range for Signed-off-by: Trial97 --- launcher/modplatform/flame/FlameInstanceCreationTask.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp index e8453c603..29145d898 100644 --- a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp +++ b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp @@ -274,8 +274,7 @@ QString FlameCreationTask::getVersionForLoader(QString uid, QString loaderType, loadVersionLoop.exec(); } - for (int i = 0; i < vlist->versions().size(); i++) { - auto version = vlist->versions().at(i); + for (auto version : vlist->versions()) { // first recommended build we find, we use. if (!version->isRecommended()) continue; From 2253100ac6a5dd58f9413b8e82a474e36e0929f0 Mon Sep 17 00:00:00 2001 From: PandaNinjas Date: Sat, 22 Jul 2023 14:26:49 -0400 Subject: [PATCH 196/216] Update libnbtplusplus submodule Signed-off-by: PandaNinjas --- libraries/libnbtplusplus | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/libnbtplusplus b/libraries/libnbtplusplus index 2203af7ee..a5e8fd52b 160000 --- a/libraries/libnbtplusplus +++ b/libraries/libnbtplusplus @@ -1 +1 @@ -Subproject commit 2203af7eeb48c45398139b583615134efd8d407f +Subproject commit a5e8fd52b8bf4ab5d5bcc042b2a247867589985f From 6f6b0b9661fb2d211ea4437b54717d7fced79373 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 23 Jul 2023 00:21:25 +0000 Subject: [PATCH 197/216] 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 'libnbtplusplus': 'github:PrismLauncher/libnbtplusplus/2203af7eeb48c45398139b583615134efd8d407f' (2022-04-15) → 'github:PrismLauncher/libnbtplusplus/a5e8fd52b8bf4ab5d5bcc042b2a247867589985f' (2023-07-22) • Updated input 'nixpkgs': 'github:nixos/nixpkgs/46ed466081b9cad1125b11f11a2af5cc40b942c7' (2023-07-15) → 'github:nixos/nixpkgs/f465da166263bc0d4b39dfd4ca28b777c92d4b73' (2023-07-22) • Updated input 'pre-commit-hooks': 'github:cachix/pre-commit-hooks.nix/5e28316db471d1ac234beb70031b635437421dd6' (2023-07-14) → 'github:cachix/pre-commit-hooks.nix/eb433bff05b285258be76513add6f6c57b441775' (2023-07-18) --- flake.lock | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/flake.lock b/flake.lock index 370250c4b..13a3e0a44 100644 --- a/flake.lock +++ b/flake.lock @@ -76,11 +76,11 @@ "libnbtplusplus": { "flake": false, "locked": { - "lastModified": 1650031308, - "narHash": "sha256-TvVOjkUobYJD9itQYueELJX3wmecvEdCbJ0FinW2mL4=", + "lastModified": 1690036783, + "narHash": "sha256-A5kTgICnx+Qdq3Fir/bKTfdTt/T1NQP2SC+nhN1ENug=", "owner": "PrismLauncher", "repo": "libnbtplusplus", - "rev": "2203af7eeb48c45398139b583615134efd8d407f", + "rev": "a5e8fd52b8bf4ab5d5bcc042b2a247867589985f", "type": "github" }, "original": { @@ -91,11 +91,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1689413807, - "narHash": "sha256-exuzOvOhGAEKWQKwDuZAL4N8a1I837hH5eocaTcIbLc=", + "lastModified": 1690026219, + "narHash": "sha256-oOduRk/kzQxOBknZXTLSEYd7tk+GoKvr8wV6Ab+t4AU=", "owner": "nixos", "repo": "nixpkgs", - "rev": "46ed466081b9cad1125b11f11a2af5cc40b942c7", + "rev": "f465da166263bc0d4b39dfd4ca28b777c92d4b73", "type": "github" }, "original": { @@ -138,11 +138,11 @@ ] }, "locked": { - "lastModified": 1689328505, - "narHash": "sha256-9B3+OeUn1a/CvzE3GW6nWNwS5J7PDHTyHGlpL3wV5oA=", + "lastModified": 1689668210, + "narHash": "sha256-XAATwDkaUxH958yXLs1lcEOmU6pSEIkatY3qjqk8X0E=", "owner": "cachix", "repo": "pre-commit-hooks.nix", - "rev": "5e28316db471d1ac234beb70031b635437421dd6", + "rev": "eb433bff05b285258be76513add6f6c57b441775", "type": "github" }, "original": { From 6a01c277e8f98797e3325a2b249e59ee95f43c7e Mon Sep 17 00:00:00 2001 From: tjw123hh Date: Mon, 24 Jul 2023 20:41:22 +0800 Subject: [PATCH 198/216] Delete some incorrect tags --- launcher/ui/pages/global/APIPage.ui | 2 +- launcher/ui/pages/global/JavaPage.ui | 2 +- launcher/ui/pages/global/MinecraftPage.ui | 2 +- launcher/ui/pages/instance/InstanceSettingsPage.ui | 2 +- program_info/org.prismlauncher.PrismLauncher.desktop.in | 1 + 5 files changed, 5 insertions(+), 4 deletions(-) mode change 100644 => 100755 program_info/org.prismlauncher.PrismLauncher.desktop.in diff --git a/launcher/ui/pages/global/APIPage.ui b/launcher/ui/pages/global/APIPage.ui index 40b89d914..492741ba4 100644 --- a/launcher/ui/pages/global/APIPage.ui +++ b/launcher/ui/pages/global/APIPage.ui @@ -30,7 +30,7 @@ - Services + Services diff --git a/launcher/ui/pages/global/JavaPage.ui b/launcher/ui/pages/global/JavaPage.ui index 6749cbe41..561cf79b7 100644 --- a/launcher/ui/pages/global/JavaPage.ui +++ b/launcher/ui/pages/global/JavaPage.ui @@ -58,7 +58,7 @@ - &PermGen: + &PermGen: permGenSpinBox diff --git a/launcher/ui/pages/global/MinecraftPage.ui b/launcher/ui/pages/global/MinecraftPage.ui index a3188dccb..393b0f358 100644 --- a/launcher/ui/pages/global/MinecraftPage.ui +++ b/launcher/ui/pages/global/MinecraftPage.ui @@ -39,7 +39,7 @@ - General + General diff --git a/launcher/ui/pages/instance/InstanceSettingsPage.ui b/launcher/ui/pages/instance/InstanceSettingsPage.ui index 323890b90..245433fe8 100644 --- a/launcher/ui/pages/instance/InstanceSettingsPage.ui +++ b/launcher/ui/pages/instance/InstanceSettingsPage.ui @@ -116,7 +116,7 @@ - PermGen: + PermGen: diff --git a/program_info/org.prismlauncher.PrismLauncher.desktop.in b/program_info/org.prismlauncher.PrismLauncher.desktop.in old mode 100644 new mode 100755 index 20fabe9d4..c85c2573f --- a/program_info/org.prismlauncher.PrismLauncher.desktop.in +++ b/program_info/org.prismlauncher.PrismLauncher.desktop.in @@ -1,3 +1,4 @@ +#!/usr/bin/env xdg-open [Desktop Entry] Version=1.0 Name=Prism Launcher From f505d43fc0399d944cad9e51ab6cc7189052cba1 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Mon, 24 Jul 2023 13:43:26 +0100 Subject: [PATCH 199/216] Fix token "0" being replaced Signed-off-by: TheKodeToad --- launcher/minecraft/MinecraftInstance.cpp | 2 +- launcher/minecraft/auth/AccountData.cpp | 4 ++++ launcher/minecraft/auth/MinecraftAccount.cpp | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/launcher/minecraft/MinecraftInstance.cpp b/launcher/minecraft/MinecraftInstance.cpp index 342e634f7..3bcd4df8c 100644 --- a/launcher/minecraft/MinecraftInstance.cpp +++ b/launcher/minecraft/MinecraftInstance.cpp @@ -843,7 +843,7 @@ QMap MinecraftInstance::createCensorFilterFromSession(AuthSess { addToFilter(sessionRef.session, tr("")); } - if (sessionRef.access_token != "offline") { + if (sessionRef.access_token != "0") { addToFilter(sessionRef.access_token, tr("")); } if(sessionRef.client_token.size()) { diff --git a/launcher/minecraft/auth/AccountData.cpp b/launcher/minecraft/auth/AccountData.cpp index 44f7e2563..0b78cb0c1 100644 --- a/launcher/minecraft/auth/AccountData.cpp +++ b/launcher/minecraft/auth/AccountData.cpp @@ -374,6 +374,10 @@ bool AccountData::resumeStateFromV3(QJsonObject data) { } yggdrasilToken = tokenFromJSONV3(data, "ygg"); + // versions before 7.2 used "offline" as the offline token + if (yggdrasilToken.token == "offline") + yggdrasilToken.token = "0"; + minecraftProfile = profileFromJSONV3(data, "profile"); if(!entitlementFromJSONV3(data, minecraftEntitlement)) { if(minecraftProfile.validity != Katabasis::Validity::None) { diff --git a/launcher/minecraft/auth/MinecraftAccount.cpp b/launcher/minecraft/auth/MinecraftAccount.cpp index d7b061e5e..5d279af1c 100644 --- a/launcher/minecraft/auth/MinecraftAccount.cpp +++ b/launcher/minecraft/auth/MinecraftAccount.cpp @@ -94,7 +94,7 @@ MinecraftAccountPtr MinecraftAccount::createOffline(const QString &username) { auto account = makeShared(); account->data.type = AccountType::Offline; - account->data.yggdrasilToken.token = "offline"; + account->data.yggdrasilToken.token = "0"; account->data.yggdrasilToken.validity = Katabasis::Validity::Certain; account->data.yggdrasilToken.issueInstant = QDateTime::currentDateTimeUtc(); account->data.yggdrasilToken.extra["userName"] = username; From 4ab630b832db9adb6b2b77a229cb845e63fc9336 Mon Sep 17 00:00:00 2001 From: tjw123hh <56749271+tjw123hh@users.noreply.github.com> Date: Mon, 24 Jul 2023 20:50:11 +0800 Subject: [PATCH 201/216] Update org.prismlauncher.PrismLauncher.desktop.in Signed-off-by: tjw123hh <56749271+tjw123hh@users.noreply.github.com> --- program_info/org.prismlauncher.PrismLauncher.desktop.in | 1 - 1 file changed, 1 deletion(-) diff --git a/program_info/org.prismlauncher.PrismLauncher.desktop.in b/program_info/org.prismlauncher.PrismLauncher.desktop.in index c85c2573f..20fabe9d4 100755 --- a/program_info/org.prismlauncher.PrismLauncher.desktop.in +++ b/program_info/org.prismlauncher.PrismLauncher.desktop.in @@ -1,4 +1,3 @@ -#!/usr/bin/env xdg-open [Desktop Entry] Version=1.0 Name=Prism Launcher From 280f041acb449d8eafc138c48339b258a6e99c64 Mon Sep 17 00:00:00 2001 From: tjw123hh Date: Tue, 25 Jul 2023 17:35:31 +0800 Subject: [PATCH 202/216] Delete some incorrect `notr="true"` tags Signed-off-by: tjw123hh --- launcher/ui/pages/global/LauncherPage.h | 2 +- program_info/org.prismlauncher.PrismLauncher.desktop.in | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/launcher/ui/pages/global/LauncherPage.h b/launcher/ui/pages/global/LauncherPage.h index 33f66f1be..e06d98971 100644 --- a/launcher/ui/pages/global/LauncherPage.h +++ b/launcher/ui/pages/global/LauncherPage.h @@ -62,7 +62,7 @@ public: QString displayName() const override { - return "Launcher"; + return tr("Launcher"); } QIcon icon() const override { diff --git a/program_info/org.prismlauncher.PrismLauncher.desktop.in b/program_info/org.prismlauncher.PrismLauncher.desktop.in index c85c2573f..20fabe9d4 100755 --- a/program_info/org.prismlauncher.PrismLauncher.desktop.in +++ b/program_info/org.prismlauncher.PrismLauncher.desktop.in @@ -1,4 +1,3 @@ -#!/usr/bin/env xdg-open [Desktop Entry] Version=1.0 Name=Prism Launcher From b4159d30fc24ce248804bd0abd5a68934f3d4739 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Tue, 25 Jul 2023 15:17:20 +0100 Subject: [PATCH 203/216] Revert permission change Signed-off-by: TheKodeToad --- program_info/org.prismlauncher.PrismLauncher.desktop.in | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 program_info/org.prismlauncher.PrismLauncher.desktop.in diff --git a/program_info/org.prismlauncher.PrismLauncher.desktop.in b/program_info/org.prismlauncher.PrismLauncher.desktop.in old mode 100755 new mode 100644 From 3c35d647b87f774877b7c090186622801bd75f10 Mon Sep 17 00:00:00 2001 From: seth Date: Tue, 25 Jul 2023 19:04:22 -0400 Subject: [PATCH 204/216] feat(ci): init garnix.yaml Signed-off-by: seth --- garnix.yaml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 garnix.yaml diff --git a/garnix.yaml b/garnix.yaml new file mode 100644 index 000000000..755396f72 --- /dev/null +++ b/garnix.yaml @@ -0,0 +1,5 @@ +builds: + exclude: [] + include: + - "devShells.*-linux.*" + - "packages.*-linux.*" From fbf29274e8c0f9b362e1630c3cee1199a889fa9f Mon Sep 17 00:00:00 2001 From: seth Date: Tue, 25 Jul 2023 19:22:48 -0400 Subject: [PATCH 205/216] chore(ci): remove nix job we're using garnix now Signed-off-by: seth --- .github/workflows/build.yml | 30 ------------------------------ 1 file changed, 30 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index bbfe4ab44..c710d54bd 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -586,33 +586,3 @@ jobs: with: bundle: "Prism Launcher.flatpak" manifest-path: flatpak/org.prismlauncher.PrismLauncher.yml - - nix: - runs-on: ubuntu-latest - strategy: - matrix: - package: - - prismlauncher - - prismlauncher-qt5 - steps: - - name: Clone repository - if: inputs.build_type == 'Debug' - uses: actions/checkout@v3 - with: - submodules: 'true' - - name: Install nix - if: inputs.build_type == 'Debug' - uses: cachix/install-nix-action@v22 - with: - install_url: https://nixos.org/nix/install - extra_nix_config: | - auto-optimise-store = true - experimental-features = nix-command flakes - - uses: cachix/cachix-action@v12 - if: inputs.build_type == 'Debug' - with: - name: prismlauncher - authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}' - - name: Build - if: inputs.build_type == 'Debug' - run: nix build .#${{ matrix.package }} --print-build-logs From 361583edfcf7e647b7bdf6ba9b82dd810a50b845 Mon Sep 17 00:00:00 2001 From: LostLuma Date: Wed, 26 Jul 2023 03:08:38 +0200 Subject: [PATCH 206/216] Ignore cache files when exporting instances Signed-off-by: LostLuma --- launcher/ui/dialogs/ExportInstanceDialog.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/launcher/ui/dialogs/ExportInstanceDialog.cpp b/launcher/ui/dialogs/ExportInstanceDialog.cpp index d1a69b932..f17a57792 100644 --- a/launcher/ui/dialogs/ExportInstanceDialog.cpp +++ b/launcher/ui/dialogs/ExportInstanceDialog.cpp @@ -70,6 +70,7 @@ ExportInstanceDialog::ExportInstanceDialog(InstancePtr instance, QWidget* parent auto prefix = QDir(instance->instanceRoot()).relativeFilePath(instance->gameRoot()); proxyModel->ignoreFilesWithPath().insert({ FS::PathCombine(prefix, "logs"), FS::PathCombine(prefix, "crash-reports") }); proxyModel->ignoreFilesWithName().append({ ".DS_Store", "thumbs.db", "Thumbs.db" }); + proxyModel->blockedPaths().insert({ FS::PathCombine(prefix, ".cache"), FS::PathCombine(prefix, ".fabric") }); loadPackIgnore(); ui->treeView->setModel(proxyModel); From 6f652e1d2fbe362387c886bf7047f425cc25004d Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Wed, 26 Jul 2023 14:38:32 +0200 Subject: [PATCH 207/216] chore: update information for downstreams Signed-off-by: Sefa Eyeoglu --- README.md | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 993f02f5d..f4a1d3d29 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,7 @@ Feel free to create a GitHub issue if you find a bug or want to suggest a new fe - **Our Matrix space:** -[![PrismLauncher Space](https://img.shields.io/matrix/prismlauncher:matrix.org?style=for-the-badge&label=Matrix%20Space&logo=matrix&color=purple)](https://prismlauncher.org/matrix) +[![Prism Launcher Space](https://img.shields.io/matrix/prismlauncher:matrix.org?style=for-the-badge&label=Matrix%20Space&logo=matrix&color=purple)](https://prismlauncher.org/matrix) - **Our Subreddit:** @@ -50,7 +50,7 @@ Feel free to create a GitHub issue if you find a bug or want to suggest a new fe ## Translations -The translation effort for PrismLauncher is hosted on [Weblate](https://hosted.weblate.org/projects/prismlauncher/launcher/) and information about translating Prism Launcher is available at +The translation effort for Prism Launcher is hosted on [Weblate](https://hosted.weblate.org/projects/prismlauncher/launcher/) and information about translating Prism Launcher is available at ## Building @@ -82,14 +82,16 @@ Thanks to the awesome people over at [MacStadium](https://www.macstadium.com/), ## Forking/Redistributing/Custom builds policy -We don't care what you do with your fork/custom build as long as you follow the terms of the [license](LICENSE) (this is a legal responsibility), and if you made code changes rather than just packaging a custom build, please do the following as a basic courtesy: +You are free to fork, redistribute and provide cusstom builds as long as you follow the terms of the [license](LICENSE) (this is a legal responsibility), and if you made code changes rather than just packaging a custom build, please do the following as a basic courtesy: -- Make it clear that your fork is not PrismLauncher and is not endorsed by or affiliated with the PrismLauncher project (). -- Go through [CMakeLists.txt](CMakeLists.txt) and change PrismLauncher's API keys to your own or set them to empty strings (`""`) to disable them (this way the program will still compile but the functionality requiring those keys will be disabled). +- Make it clear that your fork is not Prism Launcher and is not endorsed by or affiliated with the Prism Launcher project (). +- Go through [CMakeLists.txt](CMakeLists.txt) and change Prism Launcher's API keys to your own or set them to empty strings (`""`) to disable them (this way the program will still compile but the functionality requiring those keys will be disabled). If you have any questions or want any clarification on the above conditions please make an issue and ask us. -Be aware that if you build this software without removing the provided API keys in [CMakeLists.txt](CMakeLists.txt) you are accepting the following terms and conditions: +If you are just building Prism Launcher for your distribution, please make sure to set the `Launcher_BUILD_PLATFORM` to a slug representing your distribution. Examples are `archlinux`, `fedora` and `nixpkgs`. + +Note that if you build this software without removing the provided API keys in [CMakeLists.txt](CMakeLists.txt) you are accepting the following terms and conditions: - [Microsoft Identity Platform Terms of Use](https://docs.microsoft.com/en-us/legal/microsoft-identity-platform/terms-of-use) - [CurseForge 3rd Party API Terms and Conditions](https://support.curseforge.com/en/support/solutions/articles/9000207405-curse-forge-3rd-party-api-terms-and-conditions) From 4ad448993c01a41a6af23b1154c5ae64649eef91 Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Wed, 26 Jul 2023 14:48:53 +0200 Subject: [PATCH 208/216] fix: fix typo in README Co-authored-by: Tayou <31988415+TayouVR@users.noreply.github.com> Signed-off-by: Sefa Eyeoglu --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f4a1d3d29..641622b5c 100644 --- a/README.md +++ b/README.md @@ -82,7 +82,7 @@ Thanks to the awesome people over at [MacStadium](https://www.macstadium.com/), ## Forking/Redistributing/Custom builds policy -You are free to fork, redistribute and provide cusstom builds as long as you follow the terms of the [license](LICENSE) (this is a legal responsibility), and if you made code changes rather than just packaging a custom build, please do the following as a basic courtesy: +You are free to fork, redistribute and provide custom builds as long as you follow the terms of the [license](LICENSE) (this is a legal responsibility), and if you made code changes rather than just packaging a custom build, please do the following as a basic courtesy: - Make it clear that your fork is not Prism Launcher and is not endorsed by or affiliated with the Prism Launcher project (). - Go through [CMakeLists.txt](CMakeLists.txt) and change Prism Launcher's API keys to your own or set them to empty strings (`""`) to disable them (this way the program will still compile but the functionality requiring those keys will be disabled). From a9fefb2eebf8ded7322b778d9a3f36bfc65cf113 Mon Sep 17 00:00:00 2001 From: LostLuma Date: Wed, 26 Jul 2023 15:22:22 +0200 Subject: [PATCH 209/216] Address review comments Signed-off-by: LostLuma --- launcher/ui/dialogs/ExportInstanceDialog.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/launcher/ui/dialogs/ExportInstanceDialog.cpp b/launcher/ui/dialogs/ExportInstanceDialog.cpp index f17a57792..7b64467ac 100644 --- a/launcher/ui/dialogs/ExportInstanceDialog.cpp +++ b/launcher/ui/dialogs/ExportInstanceDialog.cpp @@ -70,7 +70,8 @@ ExportInstanceDialog::ExportInstanceDialog(InstancePtr instance, QWidget* parent auto prefix = QDir(instance->instanceRoot()).relativeFilePath(instance->gameRoot()); proxyModel->ignoreFilesWithPath().insert({ FS::PathCombine(prefix, "logs"), FS::PathCombine(prefix, "crash-reports") }); proxyModel->ignoreFilesWithName().append({ ".DS_Store", "thumbs.db", "Thumbs.db" }); - proxyModel->blockedPaths().insert({ FS::PathCombine(prefix, ".cache"), FS::PathCombine(prefix, ".fabric") }); + proxyModel->blockedPaths().insert( + { FS::PathCombine(prefix, ".cache"), FS::PathCombine(prefix, ".fabric"), FS::PathCombine(prefix, ".quilt") }); loadPackIgnore(); ui->treeView->setModel(proxyModel); From 1974bb7e59803fc9fc219a8d7f59896320bd58ea Mon Sep 17 00:00:00 2001 From: seth Date: Wed, 26 Jul 2023 14:34:11 -0400 Subject: [PATCH 210/216] chore(ci): cleanup garnix.yaml Signed-off-by: seth --- garnix.yaml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/garnix.yaml b/garnix.yaml index 755396f72..3bf145248 100644 --- a/garnix.yaml +++ b/garnix.yaml @@ -1,5 +1,6 @@ builds: exclude: [] include: - - "devShells.*-linux.*" - - "packages.*-linux.*" + - "checks.x86_64-linux.*" + - "devShells.*.*" + - "packages.*.*" From 342a0d0091fafece11f2b18e38c3786f112ac20b Mon Sep 17 00:00:00 2001 From: seth Date: Wed, 26 Jul 2023 14:47:47 -0400 Subject: [PATCH 211/216] fix(nix): disable x86_64-darwin Signed-off-by: seth --- nix/default.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nix/default.nix b/nix/default.nix index 7bad1440c..47172927a 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -24,9 +24,9 @@ # Supported systems. systems = [ "x86_64-linux" - "x86_64-darwin" "aarch64-linux" - # Disabled due to qtbase being currently broken for "aarch64-darwin." + # Disabled due to our packages not supporting darwin yet. + # "x86_64-darwin" # "aarch64-darwin" ]; } From f7ffbcca6c5490e24ee74486cfc6698a38512561 Mon Sep 17 00:00:00 2001 From: seth Date: Wed, 26 Jul 2023 14:45:30 -0400 Subject: [PATCH 212/216] chore(docs): correct markdownlint warnings Signed-off-by: seth --- CONTRIBUTING.md | 5 ++--- libraries/README.md | 2 +- nix/NIX.md | 10 ++++++++-- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b2795ce49..072916772 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -19,7 +19,7 @@ In an effort to ensure that the code you contribute is actually compatible with This can be done by appending `-s` to your `git commit` call, or by manually appending the following text to your commit message: -``` +```text Signed-off-by: Author name @@ -27,7 +27,7 @@ Signed-off-by: Author name By signing off your work, you agree to the terms below: -``` +```text Developer's Certificate of Origin 1.1 By making a contribution to this project, I certify that: @@ -62,7 +62,6 @@ As a bonus, you can also [cryptographically sign your commits][gh-signing-commit [gh-signing-commits]: https://docs.github.com/en/authentication/managing-commit-signature-verification/signing-commits [gh-vigilant-mode]: https://docs.github.com/en/authentication/managing-commit-signature-verification/displaying-verification-statuses-for-all-of-your-commits - ## Backporting to Release Branches We use [automated backports](https://github.com/PrismLauncher/PrismLauncher/blob/develop/.github/workflows/backport.yml) to merge specific contributions from develop into `release` branches. diff --git a/libraries/README.md b/libraries/README.md index 4da11314d..e75a381ee 100644 --- a/libraries/README.md +++ b/libraries/README.md @@ -61,7 +61,7 @@ The `standard` and `legacy` launchers are available. Example (some parts have been censored): -``` +```text mod legacyjavafixer-1.0 mainClass net.minecraft.launchwrapper.Launch param --username diff --git a/nix/NIX.md b/nix/NIX.md index 980d20e87..aa945acc6 100644 --- a/nix/NIX.md +++ b/nix/NIX.md @@ -53,7 +53,8 @@ home.packages = [ pkgs.prismlauncher ]; ### Without flakes-enabled nix -#### Using channels +
    +Using channels ```sh nix-channel --add https://github.com/PrismLauncher/PrismLauncher/archive/master.tar.gz prismlauncher @@ -61,7 +62,10 @@ nix-channel --update prismlauncher nix-env -iA prismlauncher ``` -#### Using the overlay +
    + +
    +Using the overlay ```nix # In your configuration.nix: @@ -74,6 +78,8 @@ nix-env -iA prismlauncher } ``` +
    + ## Running ad-hoc If you're on a flakes-enabled nix you can run the launcher in one-line From af59c4171344d6727c8d67205cc02406729250a3 Mon Sep 17 00:00:00 2001 From: seth Date: Wed, 26 Jul 2023 16:20:30 -0400 Subject: [PATCH 213/216] fix: typo in task.h Signed-off-by: seth --- launcher/InstanceImportTask.cpp | 6 +++--- launcher/InstanceList.cpp | 2 +- launcher/ResourceDownloadTask.cpp | 2 +- launcher/launch/steps/Update.cpp | 2 +- launcher/minecraft/MinecraftLoadAndCheck.cpp | 2 +- launcher/minecraft/MinecraftUpdate.cpp | 4 ++-- launcher/minecraft/update/AssetUpdateTask.cpp | 4 ++-- launcher/minecraft/update/FMLLibrariesTask.cpp | 2 +- launcher/minecraft/update/LibrariesTask.cpp | 2 +- launcher/modplatform/atlauncher/ATLPackInstallTask.cpp | 4 ++-- launcher/modplatform/flame/FileResolvingTask.cpp | 6 +++--- launcher/modplatform/flame/FlameInstanceCreationTask.cpp | 4 ++-- launcher/modplatform/flame/FlamePackExportTask.cpp | 2 +- launcher/modplatform/legacy_ftb/PackInstallTask.cpp | 2 +- .../modplatform/modrinth/ModrinthInstanceCreationTask.cpp | 2 +- launcher/modplatform/technic/SingleZipPackInstallTask.cpp | 2 +- launcher/modplatform/technic/SolderPackInstallTask.cpp | 2 +- launcher/tasks/Task.cpp | 2 +- launcher/tasks/Task.h | 2 +- 19 files changed, 27 insertions(+), 27 deletions(-) diff --git a/launcher/InstanceImportTask.cpp b/launcher/InstanceImportTask.cpp index 352848f02..d6a96deb1 100644 --- a/launcher/InstanceImportTask.cpp +++ b/launcher/InstanceImportTask.cpp @@ -99,7 +99,7 @@ void InstanceImportTask::executeTask() connect(m_filesNetJob.get(), &NetJob::succeeded, this, &InstanceImportTask::downloadSucceeded); connect(m_filesNetJob.get(), &NetJob::progress, this, &InstanceImportTask::downloadProgressChanged); - connect(m_filesNetJob.get(), &NetJob::stepProgress, this, &InstanceImportTask::propogateStepProgress); + connect(m_filesNetJob.get(), &NetJob::stepProgress, this, &InstanceImportTask::propagateStepProgress); connect(m_filesNetJob.get(), &NetJob::failed, this, &InstanceImportTask::downloadFailed); connect(m_filesNetJob.get(), &NetJob::aborted, this, &InstanceImportTask::downloadAborted); @@ -293,7 +293,7 @@ void InstanceImportTask::processFlame() }); connect(inst_creation_task.get(), &Task::failed, this, &InstanceImportTask::emitFailed); connect(inst_creation_task.get(), &Task::progress, this, &InstanceImportTask::setProgress); - connect(inst_creation_task.get(), &Task::stepProgress, this, &InstanceImportTask::propogateStepProgress); + connect(inst_creation_task.get(), &Task::stepProgress, this, &InstanceImportTask::propagateStepProgress); connect(inst_creation_task.get(), &Task::status, this, &InstanceImportTask::setStatus); connect(inst_creation_task.get(), &Task::details, this, &InstanceImportTask::setDetails); @@ -385,7 +385,7 @@ void InstanceImportTask::processModrinth() }); connect(inst_creation_task, &Task::failed, this, &InstanceImportTask::emitFailed); connect(inst_creation_task, &Task::progress, this, &InstanceImportTask::setProgress); - connect(inst_creation_task, &Task::stepProgress, this, &InstanceImportTask::propogateStepProgress); + connect(inst_creation_task, &Task::stepProgress, this, &InstanceImportTask::propagateStepProgress); connect(inst_creation_task, &Task::status, this, &InstanceImportTask::setStatus); connect(inst_creation_task, &Task::details, this, &InstanceImportTask::setDetails); connect(inst_creation_task, &Task::finished, inst_creation_task, &InstanceCreationTask::deleteLater); diff --git a/launcher/InstanceList.cpp b/launcher/InstanceList.cpp index b4c520cd9..0485db19e 100644 --- a/launcher/InstanceList.cpp +++ b/launcher/InstanceList.cpp @@ -799,7 +799,7 @@ class InstanceStaging : public Task { connect(child, &Task::status, this, &InstanceStaging::setStatus); connect(child, &Task::details, this, &InstanceStaging::setDetails); connect(child, &Task::progress, this, &InstanceStaging::setProgress); - connect(child, &Task::stepProgress, this, &InstanceStaging::propogateStepProgress); + connect(child, &Task::stepProgress, this, &InstanceStaging::propagateStepProgress); connect(&m_backoffTimer, &QTimer::timeout, this, &InstanceStaging::childSucceded); } diff --git a/launcher/ResourceDownloadTask.cpp b/launcher/ResourceDownloadTask.cpp index 06c03c779..8bb9b64e9 100644 --- a/launcher/ResourceDownloadTask.cpp +++ b/launcher/ResourceDownloadTask.cpp @@ -54,7 +54,7 @@ ResourceDownloadTask::ResourceDownloadTask(ModPlatform::IndexedPack::Ptr pack, m_filesNetJob->addNetAction(Net::Download::makeFile(m_pack_version.downloadUrl, dir.absoluteFilePath(getFilename()))); connect(m_filesNetJob.get(), &NetJob::succeeded, this, &ResourceDownloadTask::downloadSucceeded); connect(m_filesNetJob.get(), &NetJob::progress, this, &ResourceDownloadTask::downloadProgressChanged); - connect(m_filesNetJob.get(), &NetJob::stepProgress, this, &ResourceDownloadTask::propogateStepProgress); + connect(m_filesNetJob.get(), &NetJob::stepProgress, this, &ResourceDownloadTask::propagateStepProgress); connect(m_filesNetJob.get(), &NetJob::failed, this, &ResourceDownloadTask::downloadFailed); addTask(m_filesNetJob); diff --git a/launcher/launch/steps/Update.cpp b/launcher/launch/steps/Update.cpp index 77c8a18ea..8df2bc67c 100644 --- a/launcher/launch/steps/Update.cpp +++ b/launcher/launch/steps/Update.cpp @@ -28,7 +28,7 @@ void Update::executeTask() { connect(m_updateTask.get(), &Task::finished, this, &Update::updateFinished); connect(m_updateTask.get(), &Task::progress, this, &Update::setProgress); - connect(m_updateTask.get(), &Task::stepProgress, this, &Update::propogateStepProgress); + connect(m_updateTask.get(), &Task::stepProgress, this, &Update::propagateStepProgress); connect(m_updateTask.get(), &Task::status, this, &Update::setStatus); connect(m_updateTask.get(), &Task::details, this, &Update::setDetails); emit progressReportingRequest(); diff --git a/launcher/minecraft/MinecraftLoadAndCheck.cpp b/launcher/minecraft/MinecraftLoadAndCheck.cpp index 1c3f6fb71..2a3698798 100644 --- a/launcher/minecraft/MinecraftLoadAndCheck.cpp +++ b/launcher/minecraft/MinecraftLoadAndCheck.cpp @@ -22,7 +22,7 @@ void MinecraftLoadAndCheck::executeTask() connect(m_task.get(), &Task::failed, this, &MinecraftLoadAndCheck::subtaskFailed); connect(m_task.get(), &Task::aborted, this, [this]{ subtaskFailed(tr("Aborted")); }); connect(m_task.get(), &Task::progress, this, &MinecraftLoadAndCheck::progress); - connect(m_task.get(), &Task::stepProgress, this, &MinecraftLoadAndCheck::propogateStepProgress); + connect(m_task.get(), &Task::stepProgress, this, &MinecraftLoadAndCheck::propagateStepProgress); connect(m_task.get(), &Task::status, this, &MinecraftLoadAndCheck::setStatus); } diff --git a/launcher/minecraft/MinecraftUpdate.cpp b/launcher/minecraft/MinecraftUpdate.cpp index 35430bb0f..236d0224b 100644 --- a/launcher/minecraft/MinecraftUpdate.cpp +++ b/launcher/minecraft/MinecraftUpdate.cpp @@ -100,7 +100,7 @@ void MinecraftUpdate::next() disconnect(task.get(), &Task::failed, this, &MinecraftUpdate::subtaskFailed); disconnect(task.get(), &Task::aborted, this, &Task::abort); disconnect(task.get(), &Task::progress, this, &MinecraftUpdate::progress); - disconnect(task.get(), &Task::stepProgress, this, &MinecraftUpdate::propogateStepProgress); + disconnect(task.get(), &Task::stepProgress, this, &MinecraftUpdate::propagateStepProgress); disconnect(task.get(), &Task::status, this, &MinecraftUpdate::setStatus); disconnect(task.get(), &Task::details, this, &MinecraftUpdate::setDetails); } @@ -120,7 +120,7 @@ void MinecraftUpdate::next() connect(task.get(), &Task::failed, this, &MinecraftUpdate::subtaskFailed); connect(task.get(), &Task::aborted, this, &Task::abort); connect(task.get(), &Task::progress, this, &MinecraftUpdate::progress); - connect(task.get(), &Task::stepProgress, this, &MinecraftUpdate::propogateStepProgress); + connect(task.get(), &Task::stepProgress, this, &MinecraftUpdate::propagateStepProgress); connect(task.get(), &Task::status, this, &MinecraftUpdate::setStatus); connect(task.get(), &Task::details, this, &MinecraftUpdate::setDetails); // if the task is already running, do not start it again diff --git a/launcher/minecraft/update/AssetUpdateTask.cpp b/launcher/minecraft/update/AssetUpdateTask.cpp index 31fd5eb11..fda85ba8a 100644 --- a/launcher/minecraft/update/AssetUpdateTask.cpp +++ b/launcher/minecraft/update/AssetUpdateTask.cpp @@ -45,7 +45,7 @@ void AssetUpdateTask::executeTask() connect(downloadJob.get(), &NetJob::failed, this, &AssetUpdateTask::assetIndexFailed); connect(downloadJob.get(), &NetJob::aborted, this, [this]{ emitFailed(tr("Aborted")); }); connect(downloadJob.get(), &NetJob::progress, this, &AssetUpdateTask::progress); - connect(downloadJob.get(), &NetJob::stepProgress, this, &AssetUpdateTask::propogateStepProgress); + connect(downloadJob.get(), &NetJob::stepProgress, this, &AssetUpdateTask::propagateStepProgress); qDebug() << m_inst->name() << ": Starting asset index download"; downloadJob->start(); @@ -84,7 +84,7 @@ void AssetUpdateTask::assetIndexFinished() connect(downloadJob.get(), &NetJob::failed, this, &AssetUpdateTask::assetsFailed); connect(downloadJob.get(), &NetJob::aborted, this, [this]{ emitFailed(tr("Aborted")); }); connect(downloadJob.get(), &NetJob::progress, this, &AssetUpdateTask::progress); - connect(downloadJob.get(), &NetJob::stepProgress, this, &AssetUpdateTask::propogateStepProgress); + connect(downloadJob.get(), &NetJob::stepProgress, this, &AssetUpdateTask::propagateStepProgress); downloadJob->start(); return; } diff --git a/launcher/minecraft/update/FMLLibrariesTask.cpp b/launcher/minecraft/update/FMLLibrariesTask.cpp index 75e5c5720..d9fa0595d 100644 --- a/launcher/minecraft/update/FMLLibrariesTask.cpp +++ b/launcher/minecraft/update/FMLLibrariesTask.cpp @@ -75,7 +75,7 @@ void FMLLibrariesTask::executeTask() connect(dljob.get(), &NetJob::failed, this, &FMLLibrariesTask::fmllibsFailed); connect(dljob.get(), &NetJob::aborted, this, [this]{ emitFailed(tr("Aborted")); }); connect(dljob.get(), &NetJob::progress, this, &FMLLibrariesTask::progress); - connect(dljob.get(), &NetJob::stepProgress, this, &FMLLibrariesTask::propogateStepProgress); + connect(dljob.get(), &NetJob::stepProgress, this, &FMLLibrariesTask::propagateStepProgress); downloadJob.reset(dljob); downloadJob->start(); } diff --git a/launcher/minecraft/update/LibrariesTask.cpp b/launcher/minecraft/update/LibrariesTask.cpp index 415b9a660..9d1c02957 100644 --- a/launcher/minecraft/update/LibrariesTask.cpp +++ b/launcher/minecraft/update/LibrariesTask.cpp @@ -70,7 +70,7 @@ void LibrariesTask::executeTask() connect(downloadJob.get(), &NetJob::failed, this, &LibrariesTask::jarlibFailed); connect(downloadJob.get(), &NetJob::aborted, this, [this]{ emitFailed(tr("Aborted")); }); connect(downloadJob.get(), &NetJob::progress, this, &LibrariesTask::progress); - connect(downloadJob.get(), &NetJob::stepProgress, this, &LibrariesTask::propogateStepProgress); + connect(downloadJob.get(), &NetJob::stepProgress, this, &LibrariesTask::propagateStepProgress); downloadJob->start(); } diff --git a/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp b/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp index 22ea02da2..82a51c274 100644 --- a/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp +++ b/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp @@ -684,7 +684,7 @@ void PackInstallTask::installConfigs() abortable = true; setProgress(current, total); }); - connect(jobPtr.get(), &NetJob::stepProgress, this, &PackInstallTask::propogateStepProgress); + connect(jobPtr.get(), &NetJob::stepProgress, this, &PackInstallTask::propagateStepProgress); connect(jobPtr.get(), &NetJob::aborted, [&]{ abortable = false; jobPtr.reset(); @@ -852,7 +852,7 @@ void PackInstallTask::downloadMods() abortable = true; setProgress(current, total); }); - connect(jobPtr.get(), &NetJob::stepProgress, this, &PackInstallTask::propogateStepProgress); + connect(jobPtr.get(), &NetJob::stepProgress, this, &PackInstallTask::propagateStepProgress); connect(jobPtr.get(), &NetJob::aborted, [&] { abortable = false; diff --git a/launcher/modplatform/flame/FileResolvingTask.cpp b/launcher/modplatform/flame/FileResolvingTask.cpp index 34bd401d3..ae168bbd6 100644 --- a/launcher/modplatform/flame/FileResolvingTask.cpp +++ b/launcher/modplatform/flame/FileResolvingTask.cpp @@ -52,7 +52,7 @@ void Flame::FileResolvingTask::executeTask() stepProgress(*step_progress); emitFailed(reason); }); - connect(m_dljob.get(), &NetJob::stepProgress, this, &FileResolvingTask::propogateStepProgress); + connect(m_dljob.get(), &NetJob::stepProgress, this, &FileResolvingTask::propagateStepProgress); connect(m_dljob.get(), &NetJob::progress, this, [this, step_progress](qint64 current, qint64 total) { qDebug() << "Resolve slug progress" << current << total; step_progress->update(current, total); @@ -118,7 +118,7 @@ void Flame::FileResolvingTask::netJobFinished() stepProgress(*step_progress); emitFailed(reason); }); - connect(m_checkJob.get(), &NetJob::stepProgress, this, &FileResolvingTask::propogateStepProgress); + connect(m_checkJob.get(), &NetJob::stepProgress, this, &FileResolvingTask::propagateStepProgress); connect(m_checkJob.get(), &NetJob::progress, this, [this, step_progress](qint64 current, qint64 total) { qDebug() << "Resolve slug progress" << current << total; step_progress->update(current, total); @@ -195,7 +195,7 @@ void Flame::FileResolvingTask::modrinthCheckFinished() stepProgress(*step_progress); emitFailed(reason); }); - connect(m_slugJob.get(), &NetJob::stepProgress, this, &FileResolvingTask::propogateStepProgress); + connect(m_slugJob.get(), &NetJob::stepProgress, this, &FileResolvingTask::propagateStepProgress); connect(m_slugJob.get(), &NetJob::progress, this, [this, step_progress](qint64 current, qint64 total) { qDebug() << "Resolve slug progress" << current << total; step_progress->update(current, total); diff --git a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp index 29145d898..e17cf1c2e 100644 --- a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp +++ b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp @@ -432,7 +432,7 @@ bool FlameCreationTask::createInstance() }); 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::propogateStepProgress); + 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(); @@ -552,7 +552,7 @@ void FlameCreationTask::setupDownloadJob(QEventLoop& loop) setDetails(tr("%1 out of %2 complete").arg(current).arg(total)); setProgress(current, total); }); - connect(m_files_job.get(), &NetJob::stepProgress, this, &FlameCreationTask::propogateStepProgress); + connect(m_files_job.get(), &NetJob::stepProgress, this, &FlameCreationTask::propagateStepProgress); connect(m_files_job.get(), &NetJob::finished, &loop, &QEventLoop::quit); setStatus(tr("Downloading mods...")); diff --git a/launcher/modplatform/flame/FlamePackExportTask.cpp b/launcher/modplatform/flame/FlamePackExportTask.cpp index ac0da2142..87bf780ce 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.cpp +++ b/launcher/modplatform/flame/FlamePackExportTask.cpp @@ -166,7 +166,7 @@ void FlamePackExportTask::collectHashes() stepProgress(*progressStep); emitFailed(reason); }); - connect(hashingTask.get(), &Task::stepProgress, this, &FlamePackExportTask::propogateStepProgress); + connect(hashingTask.get(), &Task::stepProgress, this, &FlamePackExportTask::propagateStepProgress); connect(hashingTask.get(), &Task::progress, this, [this, progressStep](qint64 current, qint64 total) { progressStep->update(current, total); diff --git a/launcher/modplatform/legacy_ftb/PackInstallTask.cpp b/launcher/modplatform/legacy_ftb/PackInstallTask.cpp index a4c78397b..1afe57830 100644 --- a/launcher/modplatform/legacy_ftb/PackInstallTask.cpp +++ b/launcher/modplatform/legacy_ftb/PackInstallTask.cpp @@ -81,7 +81,7 @@ void PackInstallTask::downloadPack() connect(netJobContainer.get(), &NetJob::succeeded, this, &PackInstallTask::unzip); connect(netJobContainer.get(), &NetJob::failed, this, &PackInstallTask::emitFailed); - connect(netJobContainer.get(), &NetJob::stepProgress, this, &PackInstallTask::propogateStepProgress); + connect(netJobContainer.get(), &NetJob::stepProgress, this, &PackInstallTask::propagateStepProgress); connect(netJobContainer.get(), &NetJob::aborted, this, &PackInstallTask::emitAborted); netJobContainer->start(); diff --git a/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp b/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp index 76f072773..bd0b828c6 100644 --- a/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp +++ b/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp @@ -267,7 +267,7 @@ bool ModrinthCreationTask::createInstance() setDetails(tr("%1 out of %2 complete").arg(current).arg(total)); setProgress(current, total); }); - connect(m_files_job.get(), &NetJob::stepProgress, this, &ModrinthCreationTask::propogateStepProgress); + connect(m_files_job.get(), &NetJob::stepProgress, this, &ModrinthCreationTask::propagateStepProgress); setStatus(tr("Downloading mods...")); m_files_job->start(); diff --git a/launcher/modplatform/technic/SingleZipPackInstallTask.cpp b/launcher/modplatform/technic/SingleZipPackInstallTask.cpp index f07ca24af..ab91c4668 100644 --- a/launcher/modplatform/technic/SingleZipPackInstallTask.cpp +++ b/launcher/modplatform/technic/SingleZipPackInstallTask.cpp @@ -50,7 +50,7 @@ void Technic::SingleZipPackInstallTask::executeTask() auto job = m_filesNetJob.get(); connect(job, &NetJob::succeeded, this, &Technic::SingleZipPackInstallTask::downloadSucceeded); connect(job, &NetJob::progress, this, &Technic::SingleZipPackInstallTask::downloadProgressChanged); - connect(job, &NetJob::stepProgress, this, &Technic::SingleZipPackInstallTask::propogateStepProgress); + connect(job, &NetJob::stepProgress, this, &Technic::SingleZipPackInstallTask::propagateStepProgress); connect(job, &NetJob::failed, this, &Technic::SingleZipPackInstallTask::downloadFailed); m_filesNetJob->start(); } diff --git a/launcher/modplatform/technic/SolderPackInstallTask.cpp b/launcher/modplatform/technic/SolderPackInstallTask.cpp index 6a05d17ae..cc1d261e2 100644 --- a/launcher/modplatform/technic/SolderPackInstallTask.cpp +++ b/launcher/modplatform/technic/SolderPackInstallTask.cpp @@ -126,7 +126,7 @@ void Technic::SolderPackInstallTask::fileListSucceeded() connect(m_filesNetJob.get(), &NetJob::succeeded, this, &Technic::SolderPackInstallTask::downloadSucceeded); connect(m_filesNetJob.get(), &NetJob::progress, this, &Technic::SolderPackInstallTask::downloadProgressChanged); - connect(m_filesNetJob.get(), &NetJob::stepProgress, this, &Technic::SolderPackInstallTask::propogateStepProgress); + connect(m_filesNetJob.get(), &NetJob::stepProgress, this, &Technic::SolderPackInstallTask::propagateStepProgress); connect(m_filesNetJob.get(), &NetJob::failed, this, &Technic::SolderPackInstallTask::downloadFailed); connect(m_filesNetJob.get(), &NetJob::aborted, this, &Technic::SolderPackInstallTask::downloadAborted); m_filesNetJob->start(); diff --git a/launcher/tasks/Task.cpp b/launcher/tasks/Task.cpp index 29c55cd48..fd82ec001 100644 --- a/launcher/tasks/Task.cpp +++ b/launcher/tasks/Task.cpp @@ -161,7 +161,7 @@ void Task::emitSucceeded() emit finished(); } -void Task::propogateStepProgress(TaskStepProgress const& task_progress) +void Task::propagateStepProgress(TaskStepProgress const& task_progress) { emit stepProgress(task_progress); } diff --git a/launcher/tasks/Task.h b/launcher/tasks/Task.h index 6d8bbbb46..57177697e 100644 --- a/launcher/tasks/Task.h +++ b/launcher/tasks/Task.h @@ -167,7 +167,7 @@ class Task : public QObject, public QRunnable { virtual void emitAborted(); virtual void emitFailed(QString reason = ""); - virtual void propogateStepProgress(TaskStepProgress const& task_progress); + virtual void propagateStepProgress(TaskStepProgress const& task_progress); public slots: void setStatus(const QString& status); From 1e82cb6a7c9c7e8d0a9bfa3d2505b4b8eb132944 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Wed, 26 Jul 2023 23:56:01 +0300 Subject: [PATCH 214/216] fix: add support for QByteArray inifile Signed-off-by: Trial97 --- .../minecraft/mod/tasks/LocalModParseTask.cpp | 9 ++++---- launcher/settings/INIFile.cpp | 23 +++++++++++++++---- launcher/settings/INIFile.h | 1 + 3 files changed, 24 insertions(+), 9 deletions(-) diff --git a/launcher/minecraft/mod/tasks/LocalModParseTask.cpp b/launcher/minecraft/mod/tasks/LocalModParseTask.cpp index 264019f84..60389753e 100644 --- a/launcher/minecraft/mod/tasks/LocalModParseTask.cpp +++ b/launcher/minecraft/mod/tasks/LocalModParseTask.cpp @@ -1,9 +1,9 @@ #include "LocalModParseTask.h" +#include #include #include #include -#include #include #include #include @@ -369,12 +369,11 @@ ModDetails ReadQuiltModInfo(QByteArray contents) details.icon_file = icon.toString(); } } - } return details; } -ModDetails ReadForgeInfo(QString fileName) +ModDetails ReadForgeInfo(QByteArray contents) { ModDetails details; // Read the data @@ -382,7 +381,7 @@ ModDetails ReadForgeInfo(QString fileName) details.mod_id = "Forge"; details.homeurl = "http://www.minecraftforge.net/forum/"; INIFile ini; - if (!ini.loadFile(fileName)) + if (!ini.loadFile(contents)) return details; QString major = ini.get("forge.major.number", "0").toString(); @@ -554,7 +553,7 @@ bool processZIP(Mod& mod, ProcessingLevel level) return false; } - details = ReadForgeInfo(file.getFileName()); + details = ReadForgeInfo(file.readAll()); file.close(); zip.close(); diff --git a/launcher/settings/INIFile.cpp b/launcher/settings/INIFile.cpp index d16256b96..4fb11ed35 100644 --- a/launcher/settings/INIFile.cpp +++ b/launcher/settings/INIFile.cpp @@ -37,11 +37,12 @@ #include "settings/INIFile.h" #include -#include -#include -#include -#include #include +#include +#include +#include +#include +#include #include @@ -71,6 +72,7 @@ bool INIFile::saveFile(QString fileName) return true; } + QString unescape(QString orig) { QString out; @@ -185,6 +187,19 @@ bool INIFile::loadFile(QString fileName) return true; } +bool INIFile::loadFile(QByteArray data) +{ + QTemporaryFile file; + if (!file.open()) + return false; + file.write(data); + file.flush(); + file.close(); + auto loaded = loadFile(file.fileName()); + file.remove(); + return loaded; +} + QVariant INIFile::get(QString key, QVariant def) const { if (!this->contains(key)) diff --git a/launcher/settings/INIFile.h b/launcher/settings/INIFile.h index 0d5c05ebb..4ee543cf1 100644 --- a/launcher/settings/INIFile.h +++ b/launcher/settings/INIFile.h @@ -50,6 +50,7 @@ public: explicit INIFile(); bool loadFile(QString fileName); + bool loadFile(QByteArray data); bool saveFile(QString fileName); QVariant get(QString key, QVariant def) const; From 4a9ea832ff63a3f1f6f779b35b8a7a3e705fc6a3 Mon Sep 17 00:00:00 2001 From: LostLuma Date: Thu, 27 Jul 2023 01:42:14 +0200 Subject: [PATCH 215/216] Ignore cache files entirely, also apply to modpack export Signed-off-by: LostLuma --- launcher/ui/dialogs/ExportInstanceDialog.cpp | 2 +- launcher/ui/dialogs/ExportPackDialog.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/launcher/ui/dialogs/ExportInstanceDialog.cpp b/launcher/ui/dialogs/ExportInstanceDialog.cpp index 7b64467ac..d6a503ccd 100644 --- a/launcher/ui/dialogs/ExportInstanceDialog.cpp +++ b/launcher/ui/dialogs/ExportInstanceDialog.cpp @@ -70,7 +70,7 @@ ExportInstanceDialog::ExportInstanceDialog(InstancePtr instance, QWidget* parent auto prefix = QDir(instance->instanceRoot()).relativeFilePath(instance->gameRoot()); proxyModel->ignoreFilesWithPath().insert({ FS::PathCombine(prefix, "logs"), FS::PathCombine(prefix, "crash-reports") }); proxyModel->ignoreFilesWithName().append({ ".DS_Store", "thumbs.db", "Thumbs.db" }); - proxyModel->blockedPaths().insert( + proxyModel->ignoreFilesWithPath().insert( { FS::PathCombine(prefix, ".cache"), FS::PathCombine(prefix, ".fabric"), FS::PathCombine(prefix, ".quilt") }); loadPackIgnore(); diff --git a/launcher/ui/dialogs/ExportPackDialog.cpp b/launcher/ui/dialogs/ExportPackDialog.cpp index 2abe2805b..ad8db5ffb 100644 --- a/launcher/ui/dialogs/ExportPackDialog.cpp +++ b/launcher/ui/dialogs/ExportPackDialog.cpp @@ -61,7 +61,7 @@ ExportPackDialog::ExportPackDialog(InstancePtr instance, QWidget* parent, ModPla // use the game root - everything outside cannot be exported const QDir root(instance->gameRoot()); proxy = new FileIgnoreProxy(instance->gameRoot(), this); - proxy->ignoreFilesWithPath().insert({ "logs", "crash-reports" }); + proxy->ignoreFilesWithPath().insert({ "logs", "crash-reports", ".cache", ".fabric", ".quilt" }); proxy->ignoreFilesWithName().append({ ".DS_Store", "thumbs.db", "Thumbs.db" }); proxy->setSourceModel(model); From d1513732be63a0aed8f97c5bcf1bd5ecd94a423c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 30 Jul 2023 00:20:33 +0000 Subject: [PATCH 216/216] 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/f465da166263bc0d4b39dfd4ca28b777c92d4b73' (2023-07-22) → 'github:nixos/nixpkgs/d2b52322f35597c62abf56de91b0236746b2a03d' (2023-07-29) • Updated input 'pre-commit-hooks': 'github:cachix/pre-commit-hooks.nix/eb433bff05b285258be76513add6f6c57b441775' (2023-07-18) → 'github:cachix/pre-commit-hooks.nix/1e2443dd3f669eb65433b2fc26a3065e05a7dc9c' (2023-07-29) --- flake.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/flake.lock b/flake.lock index 13a3e0a44..af7ecae7c 100644 --- a/flake.lock +++ b/flake.lock @@ -91,11 +91,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1690026219, - "narHash": "sha256-oOduRk/kzQxOBknZXTLSEYd7tk+GoKvr8wV6Ab+t4AU=", + "lastModified": 1690630721, + "narHash": "sha256-Y04onHyBQT4Erfr2fc82dbJTfXGYrf4V0ysLUYnPOP8=", "owner": "nixos", "repo": "nixpkgs", - "rev": "f465da166263bc0d4b39dfd4ca28b777c92d4b73", + "rev": "d2b52322f35597c62abf56de91b0236746b2a03d", "type": "github" }, "original": { @@ -138,11 +138,11 @@ ] }, "locked": { - "lastModified": 1689668210, - "narHash": "sha256-XAATwDkaUxH958yXLs1lcEOmU6pSEIkatY3qjqk8X0E=", + "lastModified": 1690628027, + "narHash": "sha256-OTSbA2hM6VmxyZ/4siYPANffMBzIsKu04GLjXcv8ST0=", "owner": "cachix", "repo": "pre-commit-hooks.nix", - "rev": "eb433bff05b285258be76513add6f6c57b441775", + "rev": "1e2443dd3f669eb65433b2fc26a3065e05a7dc9c", "type": "github" }, "original": {