From 7f32c6464d84181fc8947f632da340a863dc53d6 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Tue, 1 Nov 2022 16:58:22 +0000 Subject: [PATCH 01/14] Initial better mod browser link implementation Signed-off-by: TheKodeToad --- launcher/ui/dialogs/ModDownloadDialog.cpp | 5 ++ launcher/ui/dialogs/ModDownloadDialog.h | 2 + launcher/ui/pages/modplatform/ModPage.cpp | 63 +++++++++++++++++-- launcher/ui/pages/modplatform/ModPage.h | 1 + launcher/ui/pages/modplatform/ModPage.ui | 4 +- .../pages/modplatform/flame/FlameModPage.cpp | 19 +++++- .../ui/pages/modplatform/flame/FlameModPage.h | 2 + .../modplatform/modrinth/ModrinthModPage.cpp | 2 +- 8 files changed, 87 insertions(+), 11 deletions(-) diff --git a/launcher/ui/dialogs/ModDownloadDialog.cpp b/launcher/ui/dialogs/ModDownloadDialog.cpp index d740c8cb..38b4ffcf 100644 --- a/launcher/ui/dialogs/ModDownloadDialog.cpp +++ b/launcher/ui/dialogs/ModDownloadDialog.cpp @@ -187,3 +187,8 @@ void ModDownloadDialog::selectedPageChanged(BasePage* previous, BasePage* select // Same effect as having a global search bar selected_page->setSearchTerm(prev_page->getSearchTerm()); } + +bool ModDownloadDialog::selectPage(QString pageId) +{ + return m_container->selectPage(pageId); +} \ No newline at end of file diff --git a/launcher/ui/dialogs/ModDownloadDialog.h b/launcher/ui/dialogs/ModDownloadDialog.h index 18a5f0f3..125cb776 100644 --- a/launcher/ui/dialogs/ModDownloadDialog.h +++ b/launcher/ui/dialogs/ModDownloadDialog.h @@ -53,6 +53,8 @@ public: const QList getTasks(); const std::shared_ptr &mods; + bool selectPage(QString pageId); + public slots: void confirm(); void accept() override; diff --git a/launcher/ui/pages/modplatform/ModPage.cpp b/launcher/ui/pages/modplatform/ModPage.cpp index f2c1746f..7f62fff1 100644 --- a/launcher/ui/pages/modplatform/ModPage.cpp +++ b/launcher/ui/pages/modplatform/ModPage.cpp @@ -2,6 +2,7 @@ /* * PolyMC - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu + * Copyright (C) 2022 TheKodeToad * * 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 @@ -37,6 +38,7 @@ #include "Application.h" #include "ui_ModPage.h" +#include #include #include @@ -80,6 +82,8 @@ ModPage::ModPage(ModDownloadDialog* dialog, BaseInstance* instance, ModAPI* api) ui->packView->setItemDelegate(new ProjectItemDelegate(this)); ui->packView->installEventFilter(this); + + connect(ui->packDescription, &QTextBrowser::anchorClicked, this, &ModPage::openUrl); } ModPage::~ModPage() @@ -158,8 +162,8 @@ void ModPage::triggerSearch() { auto changed = m_filter_widget->changed(); m_filter = m_filter_widget->getFilter(); - - if(changed){ + + if (changed) { ui->packView->clearSelection(); ui->packDescription->clear(); ui->versionSelectionBox->clear(); @@ -241,6 +245,54 @@ void ModPage::onModSelected() ui->packView->adjustSize(); } +void ModPage::openUrl(const QUrl& url) +{ + // do not allow other url schemes for security reasons + if (!(url.scheme() == "http" || url.scheme() == "https")) { + qWarning() << "Unsupported scheme" << url.scheme(); + return; + } + + // detect mod URLs and search instead + int prefixLength; + const char* page; + + if ((url.host() == "modrinth.com" || url.host() == "www.modrinth.com") + && url.path().startsWith("/mod/")) { + prefixLength = 5; + page = "modrinth"; + } + else if (APPLICATION->capabilities() & Application::SupportsFlame + && url.host() == "www.curseforge.com" + && url.path().toLower().startsWith("/minecraft/mc-mods/")) { + prefixLength = 19; + page = "curseforge"; + } + else + prefixLength = 0; + + if (prefixLength != 0) { + QString slug = url.path().mid(prefixLength); + + // remove trailing slash(es) + while (slug.endsWith('/')) + slug.remove(slug.length() - 1, 1); + + // ensure that the path doesn't contain any further slashes, + // and the user isn't opening the same mod; they probably + // intended to view in their web browser + if (!slug.isEmpty() && !slug.contains('/') && slug != current.slug) { + ui->searchEdit->setText(slug); + dialog->selectPage(page); + triggerSearch(); + return; + } + } + + // open in the user's web browser + QDesktopServices::openUrl(url); +} + /******** Make changes to the UI ********/ @@ -270,8 +322,8 @@ void ModPage::updateModVersions(int prev_count) if ((valid || m_filter->versions.empty()) && !optedOut(version)) ui->versionSelectionBox->addItem(version.version, QVariant(i)); } - if (ui->versionSelectionBox->count() == 0 && prev_count != 0) { - ui->versionSelectionBox->addItem(tr("No valid version found!"), QVariant(-1)); + if (ui->versionSelectionBox->count() == 0 && prev_count != 0) { + ui->versionSelectionBox->addItem(tr("No valid version found!"), QVariant(-1)); ui->modSelectionButton->setText(tr("Cannot select invalid version :(")); } @@ -317,8 +369,7 @@ void ModPage::updateUi() text += "
" + tr(" by ") + authorStrs.join(", "); } - - if(current.extraDataLoaded) { + if (current.extraDataLoaded) { if (!current.extraData.donate.isEmpty()) { text += "

" + tr("Donate information: "); auto donateToStr = [](ModPlatform::DonationData& donate) -> QString { diff --git a/launcher/ui/pages/modplatform/ModPage.h b/launcher/ui/pages/modplatform/ModPage.h index ae3d7e77..c9ccbaf2 100644 --- a/launcher/ui/pages/modplatform/ModPage.h +++ b/launcher/ui/pages/modplatform/ModPage.h @@ -82,6 +82,7 @@ class ModPage : public QWidget, public BasePage { void onSelectionChanged(QModelIndex first, QModelIndex second); void onVersionSelectionChanged(QString data); void onModSelected(); + virtual void openUrl(const QUrl& url); protected: Ui::ModPage* ui = nullptr; diff --git a/launcher/ui/pages/modplatform/ModPage.ui b/launcher/ui/pages/modplatform/ModPage.ui index 943f02aa..94365aa5 100644 --- a/launcher/ui/pages/modplatform/ModPage.ui +++ b/launcher/ui/pages/modplatform/ModPage.ui @@ -16,10 +16,10 @@ - true + false - true + false diff --git a/launcher/ui/pages/modplatform/flame/FlameModPage.cpp b/launcher/ui/pages/modplatform/flame/FlameModPage.cpp index fd6e32ff..a4b7b5a1 100644 --- a/launcher/ui/pages/modplatform/flame/FlameModPage.cpp +++ b/launcher/ui/pages/modplatform/flame/FlameModPage.cpp @@ -39,7 +39,7 @@ #include "FlameModModel.h" #include "ui/dialogs/ModDownloadDialog.h" -FlameModPage::FlameModPage(ModDownloadDialog* dialog, BaseInstance* instance) +FlameModPage::FlameModPage(ModDownloadDialog* dialog, BaseInstance* instance) : ModPage(dialog, instance, new FlameAPI()) { listModel = new FlameMod::ListModel(this); @@ -53,7 +53,7 @@ FlameModPage::FlameModPage(ModDownloadDialog* dialog, BaseInstance* instance) ui->sortByBox->addItem(tr("Sort by Author")); ui->sortByBox->addItem(tr("Sort by Downloads")); - // sometimes Qt just ignores virtual slots and doesn't work as intended it seems, + // sometimes Qt just ignores virtual slots and doesn't work as intended it seems, // so it's best not to connect them in the parent's contructor... connect(ui->sortByBox, SIGNAL(currentIndexChanged(int)), this, SLOT(triggerSearch())); connect(ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &FlameModPage::onSelectionChanged); @@ -78,3 +78,18 @@ bool FlameModPage::optedOut(ModPlatform::IndexedVersion& ver) const // other mod providers start loading before being selected, at least with // my Qt, so we need to implement this in every derived class... auto FlameModPage::shouldDisplay() const -> bool { return true; } + +void FlameModPage::openUrl(const QUrl& url) +{ + if (url.scheme().isEmpty()) { + QString query = url.query(QUrl::FullyDecoded); + if (query.startsWith("remoteUrl=")) { + // attempt to resolve url from warning page + query.remove(0, 10); + ModPage::openUrl({QUrl::fromPercentEncoding(query.toUtf8())}); // double decoding is necessary + return; + } + } + + ModPage::openUrl(url); +} \ No newline at end of file diff --git a/launcher/ui/pages/modplatform/flame/FlameModPage.h b/launcher/ui/pages/modplatform/flame/FlameModPage.h index 50dedd6f..aef9c698 100644 --- a/launcher/ui/pages/modplatform/flame/FlameModPage.h +++ b/launcher/ui/pages/modplatform/flame/FlameModPage.h @@ -64,4 +64,6 @@ class FlameModPage : public ModPage { bool optedOut(ModPlatform::IndexedVersion& ver) const override; auto shouldDisplay() const -> bool override; + + void openUrl(const QUrl& url) override; }; diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthModPage.cpp b/launcher/ui/pages/modplatform/modrinth/ModrinthModPage.cpp index 62e417c8..c531ea90 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthModPage.cpp +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthModPage.cpp @@ -53,7 +53,7 @@ ModrinthModPage::ModrinthModPage(ModDownloadDialog* dialog, BaseInstance* instan ui->sortByBox->addItem(tr("Sort by Last Updated")); ui->sortByBox->addItem(tr("Sort by Newest")); - // sometimes Qt just ignores virtual slots and doesn't work as intended it seems, + // sometimes Qt just ignores virtual slots and doesn't work as intended it seems, // so it's best not to connect them in the parent's constructor... connect(ui->sortByBox, SIGNAL(currentIndexChanged(int)), this, SLOT(triggerSearch())); connect(ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &ModrinthModPage::onSelectionChanged); From b9547adce7c7222a2d3c8dc455e7619f2be7a221 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Tue, 1 Nov 2022 17:02:24 +0000 Subject: [PATCH 02/14] Add more license headers Signed-off-by: TheKodeToad --- launcher/ui/dialogs/ModDownloadDialog.cpp | 1 + launcher/ui/dialogs/ModDownloadDialog.h | 1 + launcher/ui/pages/modplatform/flame/FlameModPage.cpp | 1 + launcher/ui/pages/modplatform/flame/FlameModPage.h | 1 + 4 files changed, 4 insertions(+) diff --git a/launcher/ui/dialogs/ModDownloadDialog.cpp b/launcher/ui/dialogs/ModDownloadDialog.cpp index 38b4ffcf..7f6f450c 100644 --- a/launcher/ui/dialogs/ModDownloadDialog.cpp +++ b/launcher/ui/dialogs/ModDownloadDialog.cpp @@ -2,6 +2,7 @@ /* * PolyMC - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu + * Copyright (C) 2022 TheKodeToad * * 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/dialogs/ModDownloadDialog.h b/launcher/ui/dialogs/ModDownloadDialog.h index 125cb776..6227b58e 100644 --- a/launcher/ui/dialogs/ModDownloadDialog.h +++ b/launcher/ui/dialogs/ModDownloadDialog.h @@ -2,6 +2,7 @@ /* * PolyMC - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu + * Copyright (C) 2022 TheKodeToad * * 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/modplatform/flame/FlameModPage.cpp b/launcher/ui/pages/modplatform/flame/FlameModPage.cpp index a4b7b5a1..faf12cea 100644 --- a/launcher/ui/pages/modplatform/flame/FlameModPage.cpp +++ b/launcher/ui/pages/modplatform/flame/FlameModPage.cpp @@ -2,6 +2,7 @@ /* * PolyMC - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu + * Copyright (C) 2022 TheKodeToad * * 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/modplatform/flame/FlameModPage.h b/launcher/ui/pages/modplatform/flame/FlameModPage.h index aef9c698..da4fcdff 100644 --- a/launcher/ui/pages/modplatform/flame/FlameModPage.h +++ b/launcher/ui/pages/modplatform/flame/FlameModPage.h @@ -2,6 +2,7 @@ /* * PolyMC - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu + * Copyright (C) 2022 TheKodeToad * * 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 d03ae34b61b6c61d0afd4a5ba0d27347c87b0726 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Tue, 1 Nov 2022 17:19:54 +0000 Subject: [PATCH 03/14] Auto-select first result Signed-off-by: TheKodeToad --- launcher/ui/pages/modplatform/ModPage.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/launcher/ui/pages/modplatform/ModPage.cpp b/launcher/ui/pages/modplatform/ModPage.cpp index 7f62fff1..780750a8 100644 --- a/launcher/ui/pages/modplatform/ModPage.cpp +++ b/launcher/ui/pages/modplatform/ModPage.cpp @@ -261,8 +261,7 @@ void ModPage::openUrl(const QUrl& url) && url.path().startsWith("/mod/")) { prefixLength = 5; page = "modrinth"; - } - else if (APPLICATION->capabilities() & Application::SupportsFlame + } else if (APPLICATION->capabilities() & Application::SupportsFlame && url.host() == "www.curseforge.com" && url.path().toLower().startsWith("/minecraft/mc-mods/")) { prefixLength = 19; @@ -282,9 +281,14 @@ void ModPage::openUrl(const QUrl& url) // and the user isn't opening the same mod; they probably // intended to view in their web browser if (!slug.isEmpty() && !slug.contains('/') && slug != current.slug) { - ui->searchEdit->setText(slug); dialog->selectPage(page); + ui->searchEdit->setText(slug); + triggerSearch(); + connect(listModel->activeJob(), &Task::finished, [this] { + ui->packView->setCurrentIndex(listModel->index(0)); + }); + return; } } From 6c7d04043984c0c2c25d2cd646be223786defdc3 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Tue, 1 Nov 2022 18:12:27 +0000 Subject: [PATCH 04/14] Hacky tweaks Signed-off-by: TheKodeToad --- launcher/ui/dialogs/ModDownloadDialog.cpp | 13 ++++++++++--- launcher/ui/dialogs/ModDownloadDialog.h | 4 ++++ launcher/ui/pages/modplatform/ModPage.cpp | 10 ++++++---- 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/launcher/ui/dialogs/ModDownloadDialog.cpp b/launcher/ui/dialogs/ModDownloadDialog.cpp index 7f6f450c..876f015a 100644 --- a/launcher/ui/dialogs/ModDownloadDialog.cpp +++ b/launcher/ui/dialogs/ModDownloadDialog.cpp @@ -132,6 +132,8 @@ QList ModDownloadDialog::getPages() if (APPLICATION->capabilities() & Application::SupportsFlame) pages.append(FlameModPage::create(this, m_instance)); + m_selected_page = dynamic_cast(pages[0]); + return pages; } @@ -179,17 +181,22 @@ void ModDownloadDialog::selectedPageChanged(BasePage* previous, BasePage* select return; } - auto* selected_page = dynamic_cast(selected); - if (!selected_page) { + m_selected_page = dynamic_cast(selected); + if (!m_selected_page) { qCritical() << "Page '" << selected->displayName() << "' in ModDownloadDialog is not a ModPage!"; return; } // Same effect as having a global search bar - selected_page->setSearchTerm(prev_page->getSearchTerm()); + m_selected_page->setSearchTerm(prev_page->getSearchTerm()); } bool ModDownloadDialog::selectPage(QString pageId) { return m_container->selectPage(pageId); +} + +ModPage* ModDownloadDialog::getSelectedPage() +{ + return m_selected_page; } \ No newline at end of file diff --git a/launcher/ui/dialogs/ModDownloadDialog.h b/launcher/ui/dialogs/ModDownloadDialog.h index 6227b58e..c637a70a 100644 --- a/launcher/ui/dialogs/ModDownloadDialog.h +++ b/launcher/ui/dialogs/ModDownloadDialog.h @@ -25,6 +25,7 @@ #include "ModDownloadTask.h" #include "minecraft/mod/ModFolderModel.h" #include "ui/pages/BasePageProvider.h" +#include "ui/pages/modplatform/ModPage.h" namespace Ui { @@ -56,6 +57,8 @@ public: bool selectPage(QString pageId); + ModPage* getSelectedPage(); + public slots: void confirm(); void accept() override; @@ -69,6 +72,7 @@ private: PageContainer * m_container = nullptr; QDialogButtonBox * m_buttons = nullptr; QVBoxLayout *m_verticalLayout = nullptr; + ModPage *m_selected_page = nullptr; QHash modTask; BaseInstance *m_instance; diff --git a/launcher/ui/pages/modplatform/ModPage.cpp b/launcher/ui/pages/modplatform/ModPage.cpp index 780750a8..6a53e25e 100644 --- a/launcher/ui/pages/modplatform/ModPage.cpp +++ b/launcher/ui/pages/modplatform/ModPage.cpp @@ -282,11 +282,13 @@ void ModPage::openUrl(const QUrl& url) // intended to view in their web browser if (!slug.isEmpty() && !slug.contains('/') && slug != current.slug) { dialog->selectPage(page); - ui->searchEdit->setText(slug); - triggerSearch(); - connect(listModel->activeJob(), &Task::finished, [this] { - ui->packView->setCurrentIndex(listModel->index(0)); + ModPage* newPage = dialog->getSelectedPage(); + newPage->ui->searchEdit->setText(slug); + newPage->triggerSearch(); + + connect(newPage->listModel->activeJob(), &Task::finished, [newPage] { + newPage->ui->packView->setCurrentIndex(newPage->listModel->index(0)); }); return; From c890aa18f7b24bbb0429456d8c4a9cbb1c8d2bb1 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Tue, 1 Nov 2022 18:25:54 +0000 Subject: [PATCH 05/14] Only select correct mod Signed-off-by: TheKodeToad --- launcher/ui/pages/modplatform/ModPage.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/launcher/ui/pages/modplatform/ModPage.cpp b/launcher/ui/pages/modplatform/ModPage.cpp index 6a53e25e..231e98f6 100644 --- a/launcher/ui/pages/modplatform/ModPage.cpp +++ b/launcher/ui/pages/modplatform/ModPage.cpp @@ -262,7 +262,7 @@ void ModPage::openUrl(const QUrl& url) prefixLength = 5; page = "modrinth"; } else if (APPLICATION->capabilities() & Application::SupportsFlame - && url.host() == "www.curseforge.com" + && (url.host() == "curseforge.com" || url.host() == "www.curseforge.com") && url.path().toLower().startsWith("/minecraft/mc-mods/")) { prefixLength = 19; page = "curseforge"; @@ -287,8 +287,15 @@ void ModPage::openUrl(const QUrl& url) newPage->ui->searchEdit->setText(slug); newPage->triggerSearch(); - connect(newPage->listModel->activeJob(), &Task::finished, [newPage] { - newPage->ui->packView->setCurrentIndex(newPage->listModel->index(0)); + connect(newPage->listModel->activeJob(), &Task::finished, [slug, newPage] { + for (int row = 0; row < newPage->listModel->rowCount({}); row++) { + QModelIndex index = newPage->listModel->index(row); + auto pack = newPage->listModel->data(index, Qt::UserRole).value(); + if (pack.slug == slug) { + newPage->ui->packView->setCurrentIndex(index); + break; + } + } }); return; From d1626d20bd4fdeeb1e9cf0f00d862fc75ddaa663 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Tue, 1 Nov 2022 18:30:11 +0000 Subject: [PATCH 06/14] Slight cleanup Signed-off-by: TheKodeToad --- launcher/ui/pages/modplatform/ModPage.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/launcher/ui/pages/modplatform/ModPage.cpp b/launcher/ui/pages/modplatform/ModPage.cpp index 231e98f6..9bb56290 100644 --- a/launcher/ui/pages/modplatform/ModPage.cpp +++ b/launcher/ui/pages/modplatform/ModPage.cpp @@ -287,12 +287,15 @@ void ModPage::openUrl(const QUrl& url) newPage->ui->searchEdit->setText(slug); newPage->triggerSearch(); - connect(newPage->listModel->activeJob(), &Task::finished, [slug, newPage] { - for (int row = 0; row < newPage->listModel->rowCount({}); row++) { - QModelIndex index = newPage->listModel->index(row); - auto pack = newPage->listModel->data(index, Qt::UserRole).value(); + ModPlatform::ListModel* model = newPage->listModel; + QListView* view = newPage->ui->packView; + + connect(model->activeJob(), &Task::finished, [slug, model, view] { + for (int row = 0; row < model->rowCount({}); row++) { + QModelIndex index = model->index(row); + ModPlatform::IndexedPack pack = model->data(index, Qt::UserRole).value(); if (pack.slug == slug) { - newPage->ui->packView->setCurrentIndex(index); + view->setCurrentIndex(index); break; } } From 576867605dc09b1d117598908d41482e168fbc95 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Tue, 1 Nov 2022 18:40:12 +0000 Subject: [PATCH 07/14] Add another fallback Signed-off-by: TheKodeToad --- launcher/ui/pages/modplatform/ModPage.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/launcher/ui/pages/modplatform/ModPage.cpp b/launcher/ui/pages/modplatform/ModPage.cpp index 9bb56290..f269fc72 100644 --- a/launcher/ui/pages/modplatform/ModPage.cpp +++ b/launcher/ui/pages/modplatform/ModPage.cpp @@ -290,15 +290,18 @@ void ModPage::openUrl(const QUrl& url) ModPlatform::ListModel* model = newPage->listModel; QListView* view = newPage->ui->packView; - connect(model->activeJob(), &Task::finished, [slug, model, view] { + connect(model->activeJob(), &Task::finished, [url, slug, model, view] { for (int row = 0; row < model->rowCount({}); row++) { QModelIndex index = model->index(row); ModPlatform::IndexedPack pack = model->data(index, Qt::UserRole).value(); if (pack.slug == slug) { view->setCurrentIndex(index); - break; + return; } } + + // The final fallback. + QDesktopServices::openUrl(url); }); return; From 8dfa3393dc59a386123c84dd30287bf9f1d17faf Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Wed, 2 Nov 2022 08:43:42 +0000 Subject: [PATCH 08/14] Formatting and forward-declaration Signed-off-by: TheKodeToad --- launcher/ui/dialogs/ModDownloadDialog.cpp | 10 ++++----- launcher/ui/dialogs/ModDownloadDialog.h | 25 +++++++++++------------ launcher/ui/pages/modplatform/ModPage.cpp | 13 +++++------- 3 files changed, 22 insertions(+), 26 deletions(-) diff --git a/launcher/ui/dialogs/ModDownloadDialog.cpp b/launcher/ui/dialogs/ModDownloadDialog.cpp index 876f015a..0a0e61e3 100644 --- a/launcher/ui/dialogs/ModDownloadDialog.cpp +++ b/launcher/ui/dialogs/ModDownloadDialog.cpp @@ -132,7 +132,7 @@ QList ModDownloadDialog::getPages() if (APPLICATION->capabilities() & Application::SupportsFlame) pages.append(FlameModPage::create(this, m_instance)); - m_selected_page = dynamic_cast(pages[0]); + m_selectedPage = dynamic_cast(pages[0]); return pages; } @@ -181,14 +181,14 @@ void ModDownloadDialog::selectedPageChanged(BasePage* previous, BasePage* select return; } - m_selected_page = dynamic_cast(selected); - if (!m_selected_page) { + m_selectedPage = dynamic_cast(selected); + if (!m_selectedPage) { qCritical() << "Page '" << selected->displayName() << "' in ModDownloadDialog is not a ModPage!"; return; } // Same effect as having a global search bar - m_selected_page->setSearchTerm(prev_page->getSearchTerm()); + m_selectedPage->setSearchTerm(prev_page->getSearchTerm()); } bool ModDownloadDialog::selectPage(QString pageId) @@ -198,5 +198,5 @@ bool ModDownloadDialog::selectPage(QString pageId) ModPage* ModDownloadDialog::getSelectedPage() { - return m_selected_page; + return m_selectedPage; } \ No newline at end of file diff --git a/launcher/ui/dialogs/ModDownloadDialog.h b/launcher/ui/dialogs/ModDownloadDialog.h index c637a70a..29bdcf82 100644 --- a/launcher/ui/dialogs/ModDownloadDialog.h +++ b/launcher/ui/dialogs/ModDownloadDialog.h @@ -25,7 +25,6 @@ #include "ModDownloadTask.h" #include "minecraft/mod/ModFolderModel.h" #include "ui/pages/BasePageProvider.h" -#include "ui/pages/modplatform/ModPage.h" namespace Ui { @@ -34,13 +33,14 @@ class ModDownloadDialog; class PageContainer; class QDialogButtonBox; +class ModPage; class ModrinthModPage; class ModDownloadDialog final : public QDialog, public BasePageProvider { Q_OBJECT -public: + public: explicit ModDownloadDialog(const std::shared_ptr& mods, QWidget* parent, BaseInstance* instance); ~ModDownloadDialog() override = default; @@ -53,27 +53,26 @@ public: bool isModSelected(QString name) const; const QList getTasks(); - const std::shared_ptr &mods; + const std::shared_ptr& mods; bool selectPage(QString pageId); - ModPage* getSelectedPage(); -public slots: + public slots: void confirm(); void accept() override; void reject() override; -private slots: + private slots: void selectedPageChanged(BasePage* previous, BasePage* selected); -private: - Ui::ModDownloadDialog *ui = nullptr; - PageContainer * m_container = nullptr; - QDialogButtonBox * m_buttons = nullptr; - QVBoxLayout *m_verticalLayout = nullptr; - ModPage *m_selected_page = nullptr; + private: + Ui::ModDownloadDialog* ui = nullptr; + PageContainer* m_container = nullptr; + QDialogButtonBox* m_buttons = nullptr; + QVBoxLayout* m_verticalLayout = nullptr; + ModPage* m_selectedPage = nullptr; QHash modTask; - BaseInstance *m_instance; + BaseInstance* m_instance; }; diff --git a/launcher/ui/pages/modplatform/ModPage.cpp b/launcher/ui/pages/modplatform/ModPage.cpp index f269fc72..af16eaef 100644 --- a/launcher/ui/pages/modplatform/ModPage.cpp +++ b/launcher/ui/pages/modplatform/ModPage.cpp @@ -257,17 +257,15 @@ void ModPage::openUrl(const QUrl& url) int prefixLength; const char* page; - if ((url.host() == "modrinth.com" || url.host() == "www.modrinth.com") - && url.path().startsWith("/mod/")) { + if ((url.host() == "modrinth.com" || url.host() == "www.modrinth.com") && url.path().startsWith("/mod/")) { prefixLength = 5; page = "modrinth"; - } else if (APPLICATION->capabilities() & Application::SupportsFlame - && (url.host() == "curseforge.com" || url.host() == "www.curseforge.com") - && url.path().toLower().startsWith("/minecraft/mc-mods/")) { + } else if (APPLICATION->capabilities() & Application::SupportsFlame && + (url.host() == "curseforge.com" || url.host() == "www.curseforge.com") && + url.path().toLower().startsWith("/minecraft/mc-mods/")) { prefixLength = 19; page = "curseforge"; - } - else + } else prefixLength = 0; if (prefixLength != 0) { @@ -312,7 +310,6 @@ void ModPage::openUrl(const QUrl& url) QDesktopServices::openUrl(url); } - /******** Make changes to the UI ********/ void ModPage::retranslate() From 6c45a990ef6b50e909368c3dfd41566ec5ca6986 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Wed, 2 Nov 2022 09:13:44 +0000 Subject: [PATCH 09/14] A good use of auto Signed-off-by: TheKodeToad --- launcher/ui/pages/modplatform/ModPage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/ui/pages/modplatform/ModPage.cpp b/launcher/ui/pages/modplatform/ModPage.cpp index af16eaef..f245bfc2 100644 --- a/launcher/ui/pages/modplatform/ModPage.cpp +++ b/launcher/ui/pages/modplatform/ModPage.cpp @@ -291,7 +291,7 @@ void ModPage::openUrl(const QUrl& url) connect(model->activeJob(), &Task::finished, [url, slug, model, view] { for (int row = 0; row < model->rowCount({}); row++) { QModelIndex index = model->index(row); - ModPlatform::IndexedPack pack = model->data(index, Qt::UserRole).value(); + auto pack = model->data(index, Qt::UserRole).value(); if (pack.slug == slug) { view->setCurrentIndex(index); return; From a1ed8154f75378a25ea20781d481fb971f616dc8 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Wed, 2 Nov 2022 09:31:39 +0000 Subject: [PATCH 10/14] Another fix Signed-off-by: TheKodeToad --- launcher/ui/pages/modplatform/ModPage.cpp | 36 +++++++++++++---------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/launcher/ui/pages/modplatform/ModPage.cpp b/launcher/ui/pages/modplatform/ModPage.cpp index f245bfc2..f347d817 100644 --- a/launcher/ui/pages/modplatform/ModPage.cpp +++ b/launcher/ui/pages/modplatform/ModPage.cpp @@ -282,27 +282,31 @@ void ModPage::openUrl(const QUrl& url) dialog->selectPage(page); ModPage* newPage = dialog->getSelectedPage(); - newPage->ui->searchEdit->setText(slug); - newPage->triggerSearch(); + QLineEdit* searchEdit = newPage->ui->searchEdit; - ModPlatform::ListModel* model = newPage->listModel; - QListView* view = newPage->ui->packView; + if (searchEdit->text() != slug) { + searchEdit->setText(slug); + newPage->triggerSearch(); - connect(model->activeJob(), &Task::finished, [url, slug, model, view] { - for (int row = 0; row < model->rowCount({}); row++) { - QModelIndex index = model->index(row); - auto pack = model->data(index, Qt::UserRole).value(); - if (pack.slug == slug) { - view->setCurrentIndex(index); - return; + ModPlatform::ListModel* model = newPage->listModel; + QListView* view = newPage->ui->packView; + + connect(model->activeJob(), &Task::finished, [url, slug, model, view] { + for (int row = 0; row < model->rowCount({}); row++) { + QModelIndex index = model->index(row); + auto pack = model->data(index, Qt::UserRole).value(); + if (pack.slug == slug) { + view->setCurrentIndex(index); + return; + } } - } - // The final fallback. - QDesktopServices::openUrl(url); - }); + // The final fallback. + QDesktopServices::openUrl(url); + }); - return; + return; + } } } From a29d88c31305deda4136df9ad5046aed60a91afd Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Wed, 2 Nov 2022 09:59:52 +0000 Subject: [PATCH 11/14] Even more fixes Signed-off-by: TheKodeToad --- launcher/ui/pages/modplatform/ModPage.cpp | 54 +++++++++++++---------- 1 file changed, 30 insertions(+), 24 deletions(-) diff --git a/launcher/ui/pages/modplatform/ModPage.cpp b/launcher/ui/pages/modplatform/ModPage.cpp index f347d817..6ec283fc 100644 --- a/launcher/ui/pages/modplatform/ModPage.cpp +++ b/launcher/ui/pages/modplatform/ModPage.cpp @@ -254,19 +254,20 @@ void ModPage::openUrl(const QUrl& url) } // detect mod URLs and search instead - int prefixLength; + int prefixLength = 0; const char* page; if ((url.host() == "modrinth.com" || url.host() == "www.modrinth.com") && url.path().startsWith("/mod/")) { prefixLength = 5; page = "modrinth"; } else if (APPLICATION->capabilities() & Application::SupportsFlame && - (url.host() == "curseforge.com" || url.host() == "www.curseforge.com") && - url.path().toLower().startsWith("/minecraft/mc-mods/")) { - prefixLength = 19; + (url.host() == "curseforge.com" || url.host().endsWith(".curseforge.com"))) { + if (url.path().toLower().startsWith("/minecraft/mc-mods/")) + prefixLength = 19; + else if (url.path().toLower().startsWith("/projects/")) + prefixLength = 10; page = "curseforge"; - } else - prefixLength = 0; + } if (prefixLength != 0) { QString slug = url.path().mid(prefixLength); @@ -282,31 +283,36 @@ void ModPage::openUrl(const QUrl& url) dialog->selectPage(page); ModPage* newPage = dialog->getSelectedPage(); + QLineEdit* searchEdit = newPage->ui->searchEdit; + ModPlatform::ListModel* model = newPage->listModel; + QListView* view = newPage->ui->packView; - if (searchEdit->text() != slug) { - searchEdit->setText(slug); - newPage->triggerSearch(); + auto jump = [url, slug, model, view] { + for (int row = 0; row < model->rowCount({}); row++) { + QModelIndex index = model->index(row); + auto pack = model->data(index, Qt::UserRole).value(); - ModPlatform::ListModel* model = newPage->listModel; - QListView* view = newPage->ui->packView; - - connect(model->activeJob(), &Task::finished, [url, slug, model, view] { - for (int row = 0; row < model->rowCount({}); row++) { - QModelIndex index = model->index(row); - auto pack = model->data(index, Qt::UserRole).value(); - if (pack.slug == slug) { - view->setCurrentIndex(index); - return; - } + if (pack.slug == slug) { + view->setCurrentIndex(index); + return; } + } - // The final fallback. - QDesktopServices::openUrl(url); - }); + // The final fallback. + QDesktopServices::openUrl(url); + }; - return; + searchEdit->setText(slug); + newPage->triggerSearch(); + + if (!model->activeJob()) + jump(); + else { + connect(model->activeJob(), &Task::finished, jump); } + + return; } } From cb796dbdfbe2099bc77911c01c8633d9f28aedac Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Wed, 2 Nov 2022 16:38:32 +0000 Subject: [PATCH 12/14] Remove unnecessary block Signed-off-by: TheKodeToad --- launcher/ui/pages/modplatform/ModPage.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/launcher/ui/pages/modplatform/ModPage.cpp b/launcher/ui/pages/modplatform/ModPage.cpp index 6ec283fc..ec6f488f 100644 --- a/launcher/ui/pages/modplatform/ModPage.cpp +++ b/launcher/ui/pages/modplatform/ModPage.cpp @@ -308,9 +308,8 @@ void ModPage::openUrl(const QUrl& url) if (!model->activeJob()) jump(); - else { + else connect(model->activeJob(), &Task::finished, jump); - } return; } From 16e3b786fc04ffd8d510bfb2a60157648825954f Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Sun, 6 Nov 2022 10:08:54 +0000 Subject: [PATCH 13/14] Implement Scrumplex's suggestions Signed-off-by: TheKodeToad --- launcher/ui/dialogs/ModDownloadDialog.cpp | 4 +- launcher/ui/dialogs/ModDownloadDialog.h | 2 +- launcher/ui/pages/modplatform/ModPage.cpp | 46 ++++++++----------- .../pages/modplatform/flame/FlameModPage.cpp | 5 +- .../ui/pages/modplatform/flame/FlameModPage.h | 2 +- 5 files changed, 27 insertions(+), 32 deletions(-) diff --git a/launcher/ui/dialogs/ModDownloadDialog.cpp b/launcher/ui/dialogs/ModDownloadDialog.cpp index 0a0e61e3..24d23ba9 100644 --- a/launcher/ui/dialogs/ModDownloadDialog.cpp +++ b/launcher/ui/dialogs/ModDownloadDialog.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) 2022 TheKodeToad * @@ -199,4 +199,4 @@ bool ModDownloadDialog::selectPage(QString pageId) ModPage* ModDownloadDialog::getSelectedPage() { return m_selectedPage; -} \ No newline at end of file +} diff --git a/launcher/ui/dialogs/ModDownloadDialog.h b/launcher/ui/dialogs/ModDownloadDialog.h index 29bdcf82..fcf6f4fc 100644 --- a/launcher/ui/dialogs/ModDownloadDialog.h +++ b/launcher/ui/dialogs/ModDownloadDialog.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) 2022 TheKodeToad * diff --git a/launcher/ui/pages/modplatform/ModPage.cpp b/launcher/ui/pages/modplatform/ModPage.cpp index ec6f488f..2f5f95bf 100644 --- a/launcher/ui/pages/modplatform/ModPage.cpp +++ b/launcher/ui/pages/modplatform/ModPage.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) 2022 TheKodeToad * @@ -43,6 +43,7 @@ #include #include +#include #include "minecraft/MinecraftInstance.h" #include "minecraft/PackProfile.h" @@ -254,32 +255,25 @@ void ModPage::openUrl(const QUrl& url) } // detect mod URLs and search instead - int prefixLength = 0; + static const QRegularExpression modrinth(QRegularExpression::anchoredPattern("(?:www\\.)?modrinth\\.com\\/mod\\/([^\\/]+)\\/?")), + curseForge(QRegularExpression::anchoredPattern("(?:www\\.)?curseforge\\.com\\/minecraft\\/mc-mods\\/([^\\/]+)\\/?")), + curseForgeOld(QRegularExpression::anchoredPattern("minecraft\\.curseforge\\.com\\/projects\\/([^\\/]+)\\/?")); + + const QString address = url.host() + url.path(); + QRegularExpressionMatch match; const char* page; - if ((url.host() == "modrinth.com" || url.host() == "www.modrinth.com") && url.path().startsWith("/mod/")) { - prefixLength = 5; + if ((match = modrinth.match(address)).hasMatch()) page = "modrinth"; - } else if (APPLICATION->capabilities() & Application::SupportsFlame && - (url.host() == "curseforge.com" || url.host().endsWith(".curseforge.com"))) { - if (url.path().toLower().startsWith("/minecraft/mc-mods/")) - prefixLength = 19; - else if (url.path().toLower().startsWith("/projects/")) - prefixLength = 10; + else if (APPLICATION->capabilities() & Application::SupportsFlame && + ((match = curseForge.match(address)).hasMatch() || (match = curseForgeOld.match(address)).hasMatch())) page = "curseforge"; - } - if (prefixLength != 0) { - QString slug = url.path().mid(prefixLength); + if (match.hasMatch()) { + const QString slug = match.captured(1); - // remove trailing slash(es) - while (slug.endsWith('/')) - slug.remove(slug.length() - 1, 1); - - // ensure that the path doesn't contain any further slashes, - // and the user isn't opening the same mod; they probably - // intended to view in their web browser - if (!slug.isEmpty() && !slug.contains('/') && slug != current.slug) { + // ensure the user isn't opening the same mod + if (slug != current.slug) { dialog->selectPage(page); ModPage* newPage = dialog->getSelectedPage(); @@ -290,8 +284,8 @@ void ModPage::openUrl(const QUrl& url) auto jump = [url, slug, model, view] { for (int row = 0; row < model->rowCount({}); row++) { - QModelIndex index = model->index(row); - auto pack = model->data(index, Qt::UserRole).value(); + const QModelIndex index = model->index(row); + const auto pack = model->data(index, Qt::UserRole).value(); if (pack.slug == slug) { view->setCurrentIndex(index); @@ -306,10 +300,10 @@ void ModPage::openUrl(const QUrl& url) searchEdit->setText(slug); newPage->triggerSearch(); - if (!model->activeJob()) - jump(); - else + if (model->activeJob()) connect(model->activeJob(), &Task::finished, jump); + else + jump(); return; } diff --git a/launcher/ui/pages/modplatform/flame/FlameModPage.cpp b/launcher/ui/pages/modplatform/flame/FlameModPage.cpp index faf12cea..bad78c97 100644 --- a/launcher/ui/pages/modplatform/flame/FlameModPage.cpp +++ b/launcher/ui/pages/modplatform/flame/FlameModPage.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) 2022 TheKodeToad * @@ -84,6 +84,7 @@ void FlameModPage::openUrl(const QUrl& url) { if (url.scheme().isEmpty()) { QString query = url.query(QUrl::FullyDecoded); + if (query.startsWith("remoteUrl=")) { // attempt to resolve url from warning page query.remove(0, 10); @@ -93,4 +94,4 @@ void FlameModPage::openUrl(const QUrl& url) } ModPage::openUrl(url); -} \ No newline at end of file +} diff --git a/launcher/ui/pages/modplatform/flame/FlameModPage.h b/launcher/ui/pages/modplatform/flame/FlameModPage.h index da4fcdff..58479ab9 100644 --- a/launcher/ui/pages/modplatform/flame/FlameModPage.h +++ b/launcher/ui/pages/modplatform/flame/FlameModPage.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) 2022 TheKodeToad * From 99ed0b6c2ca67733a574a13cd215ec5c46c4dcfa Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Thu, 10 Nov 2022 11:14:58 +0000 Subject: [PATCH 14/14] Implement flowln's suggestions Signed-off-by: TheKodeToad --- launcher/ui/pages/modplatform/ModPage.cpp | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/launcher/ui/pages/modplatform/ModPage.cpp b/launcher/ui/pages/modplatform/ModPage.cpp index 2f5f95bf..234f9f36 100644 --- a/launcher/ui/pages/modplatform/ModPage.cpp +++ b/launcher/ui/pages/modplatform/ModPage.cpp @@ -40,10 +40,10 @@ #include #include +#include #include #include -#include #include "minecraft/MinecraftInstance.h" #include "minecraft/PackProfile.h" @@ -246,6 +246,10 @@ void ModPage::onModSelected() ui->packView->adjustSize(); } +static const QRegularExpression modrinth(QRegularExpression::anchoredPattern("(?:www\\.)?modrinth\\.com\\/mod\\/([^\\/]+)\\/?")); +static const QRegularExpression curseForge(QRegularExpression::anchoredPattern("(?:www\\.)?curseforge\\.com\\/minecraft\\/mc-mods\\/([^\\/]+)\\/?")); +static const QRegularExpression curseForgeOld(QRegularExpression::anchoredPattern("minecraft\\.curseforge\\.com\\/projects\\/([^\\/]+)\\/?")); + void ModPage::openUrl(const QUrl& url) { // do not allow other url schemes for security reasons @@ -255,19 +259,22 @@ void ModPage::openUrl(const QUrl& url) } // detect mod URLs and search instead - static const QRegularExpression modrinth(QRegularExpression::anchoredPattern("(?:www\\.)?modrinth\\.com\\/mod\\/([^\\/]+)\\/?")), - curseForge(QRegularExpression::anchoredPattern("(?:www\\.)?curseforge\\.com\\/minecraft\\/mc-mods\\/([^\\/]+)\\/?")), - curseForgeOld(QRegularExpression::anchoredPattern("minecraft\\.curseforge\\.com\\/projects\\/([^\\/]+)\\/?")); const QString address = url.host() + url.path(); QRegularExpressionMatch match; const char* page; - if ((match = modrinth.match(address)).hasMatch()) + match = modrinth.match(address); + if (match.hasMatch()) page = "modrinth"; - else if (APPLICATION->capabilities() & Application::SupportsFlame && - ((match = curseForge.match(address)).hasMatch() || (match = curseForgeOld.match(address)).hasMatch())) - page = "curseforge"; + else if (APPLICATION->capabilities() & Application::SupportsFlame) { + match = curseForge.match(address); + if (!match.hasMatch()) + match = curseForgeOld.match(address); + + if (match.hasMatch()) + page = "curseforge"; + } if (match.hasMatch()) { const QString slug = match.captured(1);