diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index 7d4430fd2..874372889 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -975,8 +975,10 @@ SET(LAUNCHER_SOURCES ui/pages/modplatform/ResourcePackModel.cpp # Needed for MOC to find them without a corresponding .cpp + ui/pages/modplatform/TexturePackPage.cpp ui/pages/modplatform/TexturePackPage.h ui/pages/modplatform/TexturePackModel.cpp + ui/pages/modplatform/TexturePackModel.h ui/pages/modplatform/ShaderPackPage.cpp ui/pages/modplatform/ShaderPackModel.cpp diff --git a/launcher/modplatform/ResourceAPI.h b/launcher/modplatform/ResourceAPI.h index 51b6d4b50..c43c98fa2 100644 --- a/launcher/modplatform/ResourceAPI.h +++ b/launcher/modplatform/ResourceAPI.h @@ -156,4 +156,8 @@ class ResourceAPI { */ virtual void loadExtraPackInfo(ModPlatform::IndexedPack&, QJsonObject&) const = 0; + + virtual std::pair getModCategories() = 0; + + virtual QList loadModCategories(const QByteArray& response) = 0; }; diff --git a/launcher/modplatform/flame/FlameAPI.h b/launcher/modplatform/flame/FlameAPI.h index 607b32cab..b9ce77a1c 100644 --- a/launcher/modplatform/flame/FlameAPI.h +++ b/launcher/modplatform/flame/FlameAPI.h @@ -7,7 +7,6 @@ #include #include #include "BuildConfig.h" -#include "Json.h" #include "Version.h" #include "modplatform/ModIndex.h" #include "modplatform/ResourceAPI.h" @@ -29,12 +28,12 @@ class FlameAPI : public ResourceAPI { std::pair getFile(const QString& addonId, const QString& fileId) const; static std::pair getCategories(ModPlatform::ResourceType type); - static std::pair getModCategories(); - static QList loadModCategories(const QByteArray& response); + std::pair getModCategories() override; + QList loadModCategories(const QByteArray& response) override; QList getSortingMethods() const override; - static inline bool validateModLoaders(ModPlatform::ModLoaderTypes loaders) + static bool validateModLoaders(ModPlatform::ModLoaderTypes loaders) { return loaders & (ModPlatform::NeoForge | ModPlatform::Forge | ModPlatform::Fabric | ModPlatform::Quilt); } @@ -84,7 +83,7 @@ class FlameAPI : public ResourceAPI { return 0; } - static const QStringList getModLoaderStrings(const ModPlatform::ModLoaderTypes types) + static QStringList getModLoaderStrings(const ModPlatform::ModLoaderTypes types) { QStringList l; for (auto loader : { ModPlatform::NeoForge, ModPlatform::Forge, ModPlatform::Fabric, ModPlatform::Quilt }) { @@ -95,7 +94,7 @@ class FlameAPI : public ResourceAPI { return l; } - static const QString getModLoaderFilters(ModPlatform::ModLoaderTypes types) { return "[" + getModLoaderStrings(types).join(',') + "]"; } + static QString getModLoaderFilters(ModPlatform::ModLoaderTypes types) { return "[" + getModLoaderStrings(types).join(',') + "]"; } public: std::optional getSearchURL(const SearchArgs& args) const override @@ -104,22 +103,27 @@ class FlameAPI : public ResourceAPI { get_arguments.append(QString("classId=%1").arg(getClassId(args.type))); get_arguments.append(QString("index=%1").arg(args.offset)); get_arguments.append("pageSize=25"); - if (args.search.has_value()) + if (args.search.has_value()) { get_arguments.append(QString("searchFilter=%1").arg(args.search.value())); - if (args.sorting.has_value()) + } + if (args.sorting.has_value()) { get_arguments.append(QString("sortField=%1").arg(args.sorting.value().index)); + } get_arguments.append("sortOrder=desc"); if (args.loaders.has_value()) { ModPlatform::ModLoaderTypes loaders = args.loaders.value(); loaders &= ~static_cast(ModPlatform::ModLoaderType::DataPack); - if (loaders != 0) + if (loaders != 0) { get_arguments.append(QString("modLoaderTypes=%1").arg(getModLoaderFilters(loaders))); + } } - if (args.categoryIds.has_value() && !args.categoryIds->empty()) + if (args.categoryIds.has_value() && !args.categoryIds->empty()) { get_arguments.append(QString("categoryIds=[%1]").arg(args.categoryIds->join(","))); + } - if (args.versions.has_value() && !args.versions.value().empty()) + if (args.versions.has_value() && !args.versions.value().empty()) { get_arguments.append(QString("gameVersion=%1").arg(args.versions.value().front().toString())); + } return BuildConfig.FLAME_BASE_URL + "/mods/search?gameId=432&" + get_arguments.join('&'); } @@ -129,8 +133,9 @@ class FlameAPI : public ResourceAPI { auto addonId = args.pack->addonId.toString(); QString url = QString(BuildConfig.FLAME_BASE_URL + "/mods/%1/files?pageSize=10000").arg(addonId); - if (args.mcVersions.has_value()) + if (args.mcVersions.has_value()) { url += QString("&gameVersion=%1").arg(args.mcVersions.value().front().toString()); + } if (args.loaders.has_value() && args.loaders.value() != ModPlatform::ModLoaderType::DataPack && ModPlatform::hasSingleModLoaderSelected(args.loaders.value())) { @@ -157,7 +162,7 @@ class FlameAPI : public ResourceAPI { } return {}; }; - void loadExtraPackInfo(ModPlatform::IndexedPack& m, [[maybe_unused]] QJsonObject&) const override { FlameMod::loadBody(m); } + void loadExtraPackInfo(ModPlatform::IndexedPack& m, [[maybe_unused]] QJsonObject& /*unused*/) const override { FlameMod::loadBody(m); } private: std::optional getInfoURL(const QString& id) const override { return QString(BuildConfig.FLAME_BASE_URL + "/mods/%1").arg(id); } diff --git a/launcher/modplatform/modrinth/ModrinthAPI.h b/launcher/modplatform/modrinth/ModrinthAPI.h index 731ac1b09..5f81384c2 100644 --- a/launcher/modplatform/modrinth/ModrinthAPI.h +++ b/launcher/modplatform/modrinth/ModrinthAPI.h @@ -30,9 +30,9 @@ class ModrinthAPI : public ResourceAPI { std::pair getProjects(QStringList addonIds) const override; - static std::pair getModCategories(); - static QList loadCategories(const QByteArray& response, const QString& projectType); - static QList loadModCategories(const QByteArray& response); + std::pair getModCategories() override; + static QList loadCategories(const QByteArray& response, QString projectType); + QList loadModCategories(const QByteArray& response) override; public: auto getSortingMethods() const -> QList override; @@ -180,7 +180,7 @@ class ModrinthAPI : public ResourceAPI { return BuildConfig.MODRINTH_PROD_URL + "/project/" + id; }; - auto getMultipleModInfoURL(const QStringList& ids) const -> QString + static auto getMultipleModInfoURL(const QStringList& ids) -> QString { return BuildConfig.MODRINTH_PROD_URL + QString("/projects?ids=[\"%1\"]").arg(ids.join("\",\"")); }; diff --git a/launcher/ui/dialogs/ResourceDownloadDialog.cpp b/launcher/ui/dialogs/ResourceDownloadDialog.cpp index bcb30c761..f863e3edc 100644 --- a/launcher/ui/dialogs/ResourceDownloadDialog.cpp +++ b/launcher/ui/dialogs/ResourceDownloadDialog.cpp @@ -308,12 +308,12 @@ QList ModDownloadDialog::getPages() auto loaders = static_cast(m_instance)->getPackProfile()->getSupportedModLoaders().value(); if (ModrinthAPI::validateModLoaders(loaders)) { - auto* page = ModrinthModPage::create(this, *m_instance); + auto* page = Modrinth::createModPage(this, *m_instance); page->setSuppressInitialSearch(m_suppressInitialSearch); pages.append(page); } if (APPLICATION->capabilities() & Application::SupportsFlame && FlameAPI::validateModLoaders(loaders)) { - auto* page = FlameModPage::create(this, *m_instance); + auto* page = Flame::createModPage(this, *m_instance); page->setSuppressInitialSearch(m_suppressInitialSearch); pages.append(page); } @@ -356,11 +356,11 @@ QList ResourcePackDownloadDialog::getPages() { QList pages; - auto* modrinthPage = ModrinthResourcePackPage::create(this, *m_instance); + auto* modrinthPage = Modrinth::createResourcePackResourcePage(this, *m_instance); modrinthPage->setSuppressInitialSearch(m_suppressInitialSearch); pages.append(modrinthPage); if (APPLICATION->capabilities() & Application::SupportsFlame) { - auto* flamePage = FlameResourcePackPage::create(this, *m_instance); + auto* flamePage = Flame::createResourcePackResourcePage(this, *m_instance); flamePage->setSuppressInitialSearch(m_suppressInitialSearch); pages.append(flamePage); } @@ -388,11 +388,11 @@ QList TexturePackDownloadDialog::getPages() { QList pages; - auto* modrinthPage = ModrinthTexturePackPage::create(this, *m_instance); + auto* modrinthPage =Modrinth::createTexturePackResourcePage(this, *m_instance); modrinthPage->setSuppressInitialSearch(m_suppressInitialSearch); pages.append(modrinthPage); if (APPLICATION->capabilities() & Application::SupportsFlame) { - auto* flamePage = FlameTexturePackPage::create(this, *m_instance); + auto* flamePage = Flame::createTexturePackResourcePage(this, *m_instance); flamePage->setSuppressInitialSearch(m_suppressInitialSearch); pages.append(flamePage); } @@ -419,11 +419,11 @@ ShaderPackDownloadDialog::ShaderPackDownloadDialog(QWidget* parent, QList ShaderPackDownloadDialog::getPages() { QList pages; - auto* modrinthPage = ModrinthShaderPackPage::create(this, *m_instance); + auto* modrinthPage = Modrinth::createShaderPackResourcePage(this, *m_instance); modrinthPage->setSuppressInitialSearch(m_suppressInitialSearch); pages.append(modrinthPage); if (APPLICATION->capabilities() & Application::SupportsFlame) { - auto* flamePage = FlameShaderPackPage::create(this, *m_instance); + auto* flamePage = Flame::createShaderPackResourcePage(this, *m_instance); flamePage->setSuppressInitialSearch(m_suppressInitialSearch); pages.append(flamePage); } @@ -467,11 +467,11 @@ DataPackDownloadDialog::DataPackDownloadDialog(QWidget* parent, QList DataPackDownloadDialog::getPages() { QList pages; - auto* modrinthPage = ModrinthDataPackPage::create(this, *m_instance); + auto* modrinthPage =Modrinth::createDataPackResourcePage(this, *m_instance); modrinthPage->setSuppressInitialSearch(m_suppressInitialSearch); pages.append(modrinthPage); if (APPLICATION->capabilities() & Application::SupportsFlame) { - auto* flamePage = FlameDataPackPage::create(this, *m_instance); + auto* flamePage = Flame::createDataPackResourcePage(this, *m_instance); flamePage->setSuppressInitialSearch(m_suppressInitialSearch); pages.append(flamePage); } diff --git a/launcher/ui/pages/modplatform/DataPackPage.cpp b/launcher/ui/pages/modplatform/DataPackPage.cpp index 82892b318..c865ea7a8 100644 --- a/launcher/ui/pages/modplatform/DataPackPage.cpp +++ b/launcher/ui/pages/modplatform/DataPackPage.cpp @@ -14,12 +14,52 @@ namespace ResourceDownload { -DataPackResourcePage::DataPackResourcePage(DataPackDownloadDialog* dialog, BaseInstance& instance) : ResourcePage(dialog, instance) {} +static ResourceDescriptor prepareDataPackDescriptor() +{ + QMap urlHandlers; + urlHandlers.insert(QRegularExpression::anchoredPattern("(?:www\\.)?modrinth\\.com\\/resourcepack\\/([^\\/]+)\\/?"), "modrinth"); + urlHandlers.insert(QRegularExpression::anchoredPattern("(?:www\\.)?curseforge\\.com\\/minecraft\\/texture-packs\\/([^\\/]+)\\/?"), + "curseforge"); + urlHandlers.insert(QRegularExpression::anchoredPattern("minecraft\\.curseforge\\.com\\/projects\\/([^\\/]+)\\/?"), "curseforge"); + return { + .helpPage = {}, + //: The singular version of 'data packs' + .resourceString = QObject::tr("data pack"), + //: The plural version of 'data pack' + .resourcesString = QObject::tr("data packs"), + .supportsFiltering = false, + .isIndexed = true, + .urlHandlers = urlHandlers, + }; +} + +DataPackResourcePage::DataPackResourcePage(DataPackDownloadDialog* dialog, BaseInstance& instance, ResourceProviderData p, ResourceAPI* api) + : ResourcePage(dialog, instance, prepareDataPackDescriptor(), p) +{ + m_model = new DataPackResourceModel(instance, api, debugName(), metaEntryBase()); + m_ui->packView->setModel(m_model); + + addSortings(); + + // 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(m_model, &ResourceModel::versionListUpdated, this, &ResourcePage::versionListUpdated); + connect(m_model, &ResourceModel::projectInfoUpdated, this, &ResourcePage::updateUi); + connect(m_model, &QAbstractListModel::modelReset, this, &ResourcePage::modelReset); + + connect(m_ui->sortByBox, &QComboBox::currentIndexChanged, this, &DataPackResourcePage::triggerSearch); + connect(m_ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &DataPackResourcePage::onSelectionChanged); + connect(m_ui->versionSelectionBox, &QComboBox::currentIndexChanged, this, &DataPackResourcePage::onVersionSelectionChanged); + connect(m_ui->resourceSelectionButton, &QPushButton::clicked, this, &DataPackResourcePage::onResourceSelected); + + m_ui->packDescription->setMetaEntry(metaEntryBase()); +} /******** Callbacks to events in the UI (set up in the derived classes) ********/ void DataPackResourcePage::triggerSearch() { + m_ui->packView->selectionModel()->setCurrentIndex({}, QItemSelectionModel::SelectionFlag::ClearAndSelect); m_ui->packView->clearSelection(); m_ui->packDescription->clear(); m_ui->versionSelectionBox->clear(); @@ -30,14 +70,4 @@ void DataPackResourcePage::triggerSearch() m_fetchProgress.watch(m_model->activeSearchJob().get()); } -QMap DataPackResourcePage::urlHandlers() const -{ - QMap map; - map.insert(QRegularExpression::anchoredPattern("(?:www\\.)?modrinth\\.com\\/resourcepack\\/([^\\/]+)\\/?"), "modrinth"); - map.insert(QRegularExpression::anchoredPattern("(?:www\\.)?curseforge\\.com\\/minecraft\\/texture-packs\\/([^\\/]+)\\/?"), - "curseforge"); - map.insert(QRegularExpression::anchoredPattern("minecraft\\.curseforge\\.com\\/projects\\/([^\\/]+)\\/?"), "curseforge"); - return map; -} - } // namespace ResourceDownload diff --git a/launcher/ui/pages/modplatform/DataPackPage.h b/launcher/ui/pages/modplatform/DataPackPage.h index 431fc9a05..661fb6f2a 100644 --- a/launcher/ui/pages/modplatform/DataPackPage.h +++ b/launcher/ui/pages/modplatform/DataPackPage.h @@ -5,45 +5,16 @@ #pragma once -#include "ui/pages/modplatform/DataPackModel.h" #include "ui/pages/modplatform/ResourcePage.h" -namespace Ui { -class ResourcePage; -} - namespace ResourceDownload { class DataPackDownloadDialog; - class DataPackResourcePage : public ResourcePage { Q_OBJECT public: - template - static T* create(DataPackDownloadDialog* dialog, BaseInstance& instance) - { - auto page = new T(dialog, instance); - auto model = static_cast(page->getModel()); - - connect(model, &ResourceModel::versionListUpdated, page, &ResourcePage::versionListUpdated); - connect(model, &ResourceModel::projectInfoUpdated, page, &ResourcePage::updateUi); - connect(model, &QAbstractListModel::modelReset, page, &ResourcePage::modelReset); - - return page; - } - - //: The plural version of 'data pack' - inline QString resourcesString() const override { return tr("data packs"); } - //: The singular version of 'data packs' - inline QString resourceString() const override { return tr("data pack"); } - - bool supportsFiltering() const override { return false; }; - - QMap urlHandlers() const override; - - protected: - DataPackResourcePage(DataPackDownloadDialog* dialog, BaseInstance& instance); + DataPackResourcePage(DataPackDownloadDialog* dialog, BaseInstance& instance, ResourceProviderData p, ResourceAPI* api); protected slots: void triggerSearch() override; diff --git a/launcher/ui/pages/modplatform/ModPage.cpp b/launcher/ui/pages/modplatform/ModPage.cpp index 1cdce5e33..c89cda209 100644 --- a/launcher/ui/pages/modplatform/ModPage.cpp +++ b/launcher/ui/pages/modplatform/ModPage.cpp @@ -40,38 +40,75 @@ #include "ModPage.h" #include "ui_ResourcePage.h" -#include -#include #include #include +#include #include "Application.h" -#include "ResourceDownloadTask.h" - -#include "minecraft/MinecraftInstance.h" - #include "ui/dialogs/ResourceDownloadDialog.h" -namespace ResourceDownload { - -ModPage::ModPage(ModDownloadDialog* dialog, BaseInstance& instance) : ResourcePage(dialog, instance) +namespace { +ResourceDownload::ResourceDescriptor prepareModDescriptor() { + QMap urlHandlers; + urlHandlers.insert(QRegularExpression::anchoredPattern(R"((?:www\.)?modrinth\.com\/mod\/([^\/]+)\/?)"), "modrinth"); + urlHandlers.insert(QRegularExpression::anchoredPattern(R"((?:www\.)?curseforge\.com\/minecraft\/mc-mods\/([^\/]+)\/?)"), "curseforge"); + urlHandlers.insert(QRegularExpression::anchoredPattern(R"(minecraft\.curseforge\.com\/projects\/([^\/]+)\/?)"), "curseforge"); + return { + .helpPage = "Mod-platform", + //: The singular version of 'mods' + .resourceString = QObject::tr("mod"), + //: The plural version of 'mod' + .resourcesString = QObject::tr("mods"), + .supportsFiltering = true, + .isIndexed = true, + .urlHandlers = urlHandlers, + }; +} +} // namespace + +namespace ResourceDownload { +ModPage::ModPage(ModDownloadDialog* dialog, BaseInstance& instance, ResourceProviderData p, ResourceAPI* api, ModFilterWidget* filterWidget) + : ResourcePage(dialog, instance, prepareModDescriptor(), std::move(p)), m_api(api) +{ + auto* model = new ModModel(instance, api, debugName(), metaEntryBase()); + m_model = model; + m_ui->packView->setModel(m_model); + + addSortings(); + + // 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... + setFilterWidget(filterWidget); + model->setFilter(getFilter()); + + connect(m_model, &ResourceModel::versionListUpdated, this, &ResourcePage::versionListUpdated); + connect(m_model, &ResourceModel::projectInfoUpdated, this, &ResourcePage::updateUi); + connect(m_model, &QAbstractListModel::modelReset, this, &ResourcePage::modelReset); + + connect(m_ui->sortByBox, &QComboBox::currentIndexChanged, this, &ModPage::triggerSearch); + connect(m_ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &ModPage::onSelectionChanged); + connect(m_ui->versionSelectionBox, &QComboBox::currentIndexChanged, this, &ModPage::onVersionSelectionChanged); + connect(m_ui->resourceSelectionButton, &QPushButton::clicked, this, &ModPage::onResourceSelected); + + m_ui->packDescription->setMetaEntry(metaEntryBase()); connect(m_ui->resourceFilterButton, &QPushButton::clicked, this, &ModPage::filterMods); } -void ModPage::setFilterWidget(std::unique_ptr& widget) +void ModPage::setFilterWidget(ModFilterWidget* widget) { if (m_filter_widget) { disconnect(m_filter_widget.get(), nullptr, nullptr, nullptr); } - auto* old = m_ui->splitter->replaceWidget(0, widget.get()); + auto* old = m_ui->splitter->replaceWidget(0, widget); // because we replaced the widget we also need to delete it + if (old) { + old->deleteLater(); + } - delete old; - - m_filter_widget.swap(widget); + m_filter_widget.reset(widget); m_filter = m_filter_widget->getFilter(); @@ -100,24 +137,14 @@ void ModPage::triggerSearch() m_fetchProgress.watch(m_model->activeSearchJob().get()); } -QMap ModPage::urlHandlers() const +void ModPage::prepareProviderCategories() { - QMap map; - map.insert(QRegularExpression::anchoredPattern("(?:www\\.)?modrinth\\.com\\/mod\\/([^\\/]+)\\/?"), "modrinth"); - map.insert(QRegularExpression::anchoredPattern("(?:www\\.)?curseforge\\.com\\/minecraft\\/mc-mods\\/([^\\/]+)\\/?"), "curseforge"); - map.insert(QRegularExpression::anchoredPattern("minecraft\\.curseforge\\.com\\/projects\\/([^\\/]+)\\/?"), "curseforge"); - return map; -} - -/******** Make changes to the UI ********/ - -void ModPage::addResourceToPage(ModPlatform::IndexedPack::Ptr pack, - ModPlatform::IndexedVersion& version, - ResourceFolderModel* baseModel, - QString downloadReason) -{ - bool isIndexed = !APPLICATION->settings()->get("ModMetadataDisabled").toBool(); - m_model->addPack(pack, version, baseModel, isIndexed, downloadReason); -} - + auto [task, response] = m_api->getModCategories(); + m_categoriesTask = task; + connect(m_categoriesTask.get(), &Task::succeeded, [this, response]() { + auto categories = m_api->loadModCategories(*response); + m_filter_widget->setCategories(categories); + }); + m_categoriesTask->start(); +}; } // namespace ResourceDownload diff --git a/launcher/ui/pages/modplatform/ModPage.h b/launcher/ui/pages/modplatform/ModPage.h index 7f75995a3..5cebcd07e 100644 --- a/launcher/ui/pages/modplatform/ModPage.h +++ b/launcher/ui/pages/modplatform/ModPage.h @@ -6,16 +6,10 @@ #include -#include "modplatform/ModIndex.h" - #include "ui/pages/modplatform/ModModel.h" #include "ui/pages/modplatform/ResourcePage.h" #include "ui/widgets/ModFilterWidget.h" -namespace Ui { -class ResourcePage; -} - namespace ResourceDownload { class ModDownloadDialog; @@ -25,45 +19,13 @@ class ModPage : public ResourcePage { Q_OBJECT public: - template - static T* create(ModDownloadDialog* dialog, BaseInstance& instance) - { - auto page = new T(dialog, instance); - auto* model = static_cast(page->getModel()); + auto getFilter() const -> const std::shared_ptr { return m_filter; } - auto filterWidget = page->createFilterWidget(); - page->setFilterWidget(filterWidget); - model->setFilter(page->getFilter()); - - connect(model, &ResourceModel::versionListUpdated, page, &ResourcePage::versionListUpdated); - connect(model, &ResourceModel::projectInfoUpdated, page, &ResourcePage::updateUi); - connect(model, &QAbstractListModel::modelReset, page, &ResourcePage::modelReset); - - return page; - } - - //: The plural version of 'mod' - QString resourcesString() const override { return tr("mods"); } - //: The singular version of 'mods' - QString resourceString() const override { return tr("mod"); } - - QMap urlHandlers() const override; - - void addResourceToPage(ModPlatform::IndexedPack::Ptr /*unused*/, - ModPlatform::IndexedVersion& /*unused*/, - ResourceFolderModel* /*unused*/, - QString downloadReason = "standalone") override; - - virtual std::unique_ptr createFilterWidget() = 0; - - bool supportsFiltering() const override { return true; }; - auto getFilter() const -> std::shared_ptr { return m_filter; } - void setFilterWidget(std::unique_ptr&); + ModPage(ModDownloadDialog* dialog, BaseInstance& instance, ResourceProviderData p, ResourceAPI* api, ModFilterWidget* filterWidget); protected: - ModPage(ModDownloadDialog* dialog, BaseInstance& instance); - - virtual void prepareProviderCategories() {}; + void prepareProviderCategories(); + void setFilterWidget(ModFilterWidget*); protected slots: virtual void filterMods(); @@ -72,6 +34,8 @@ class ModPage : public ResourcePage { protected: std::unique_ptr m_filter_widget; std::shared_ptr m_filter; + Task::Ptr m_categoriesTask; + ResourceAPI* m_api = nullptr; }; } // namespace ResourceDownload diff --git a/launcher/ui/pages/modplatform/ResourcePackPage.cpp b/launcher/ui/pages/modplatform/ResourcePackPage.cpp index 8a7ed2720..092511e83 100644 --- a/launcher/ui/pages/modplatform/ResourcePackPage.cpp +++ b/launcher/ui/pages/modplatform/ResourcePackPage.cpp @@ -13,8 +13,49 @@ namespace ResourceDownload { -ResourcePackResourcePage::ResourcePackResourcePage(ResourceDownloadDialog* dialog, BaseInstance& instance) : ResourcePage(dialog, instance) -{} +static ResourceDescriptor prepareResourcePackDescriptor() +{ + QMap urlHandlers; + urlHandlers.insert(QRegularExpression::anchoredPattern("(?:www\\.)?modrinth\\.com\\/resourcepack\\/([^\\/]+)\\/?"), "modrinth"); + urlHandlers.insert(QRegularExpression::anchoredPattern("(?:www\\.)?curseforge\\.com\\/minecraft\\/texture-packs\\/([^\\/]+)\\/?"), + "curseforge"); + urlHandlers.insert(QRegularExpression::anchoredPattern("minecraft\\.curseforge\\.com\\/projects\\/([^\\/]+)\\/?"), "curseforge"); + return { + .helpPage = {}, + //: The singular version of 'resource packs' + .resourceString = QObject::tr("resource pack"), + //: The plural version of 'resource pack' + .resourcesString = QObject::tr("resource packs"), + .supportsFiltering = false, + .isIndexed = true, + .urlHandlers = urlHandlers, + }; +} + +ResourcePackResourcePage::ResourcePackResourcePage(ResourceDownloadDialog* dialog, + BaseInstance& instance, + ResourceProviderData p, + ResourceAPI* api) + : ResourcePage(dialog, instance, prepareResourcePackDescriptor(), p) +{ + m_model = new ResourcePackResourceModel(instance, api, debugName(), metaEntryBase()); + m_ui->packView->setModel(m_model); + + addSortings(); + + // 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(m_model, &ResourceModel::versionListUpdated, this, &ResourcePage::versionListUpdated); + connect(m_model, &ResourceModel::projectInfoUpdated, this, &ResourcePage::updateUi); + connect(m_model, &QAbstractListModel::modelReset, this, &ResourcePage::modelReset); + + connect(m_ui->sortByBox, &QComboBox::currentIndexChanged, this, &ResourcePackResourcePage::triggerSearch); + connect(m_ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &ResourcePackResourcePage::onSelectionChanged); + connect(m_ui->versionSelectionBox, &QComboBox::currentIndexChanged, this, &ResourcePackResourcePage::onVersionSelectionChanged); + connect(m_ui->resourceSelectionButton, &QPushButton::clicked, this, &ResourcePackResourcePage::onResourceSelected); + + m_ui->packDescription->setMetaEntry(metaEntryBase()); +} /******** Callbacks to events in the UI (set up in the derived classes) ********/ @@ -31,14 +72,4 @@ void ResourcePackResourcePage::triggerSearch() m_fetchProgress.watch(m_model->activeSearchJob().get()); } -QMap ResourcePackResourcePage::urlHandlers() const -{ - QMap map; - map.insert(QRegularExpression::anchoredPattern("(?:www\\.)?modrinth\\.com\\/resourcepack\\/([^\\/]+)\\/?"), "modrinth"); - map.insert(QRegularExpression::anchoredPattern("(?:www\\.)?curseforge\\.com\\/minecraft\\/texture-packs\\/([^\\/]+)\\/?"), - "curseforge"); - map.insert(QRegularExpression::anchoredPattern("minecraft\\.curseforge\\.com\\/projects\\/([^\\/]+)\\/?"), "curseforge"); - return map; -} - } // namespace ResourceDownload diff --git a/launcher/ui/pages/modplatform/ResourcePackPage.h b/launcher/ui/pages/modplatform/ResourcePackPage.h index f8d4d5bf9..7c36977ba 100644 --- a/launcher/ui/pages/modplatform/ResourcePackPage.h +++ b/launcher/ui/pages/modplatform/ResourcePackPage.h @@ -4,13 +4,8 @@ #pragma once -#include "ui/pages/modplatform/ResourcePackModel.h" #include "ui/pages/modplatform/ResourcePage.h" -namespace Ui { -class ResourcePage; -} - namespace ResourceDownload { class ResourcePackDownloadDialog; @@ -19,32 +14,7 @@ class ResourcePackResourcePage : public ResourcePage { Q_OBJECT public: - template - static T* create(ResourcePackDownloadDialog* dialog, BaseInstance& instance) - { - auto page = new T(dialog, instance); - auto model = static_cast(page->getModel()); - - connect(model, &ResourceModel::versionListUpdated, page, &ResourcePage::versionListUpdated); - connect(model, &ResourceModel::projectInfoUpdated, page, &ResourcePage::updateUi); - connect(model, &QAbstractListModel::modelReset, page, &ResourcePage::modelReset); - - return page; - } - - //: The plural version of 'resource pack' - inline QString resourcesString() const override { return tr("resource packs"); } - //: The singular version of 'resource packs' - inline QString resourceString() const override { return tr("resource pack"); } - - bool supportsFiltering() const override { return false; }; - - QMap urlHandlers() const override; - - inline auto helpPage() const -> QString override { return "resourcepack-platform"; } - - protected: - ResourcePackResourcePage(ResourceDownloadDialog* dialog, BaseInstance& instance); + ResourcePackResourcePage(ResourceDownloadDialog* dialog, BaseInstance& instance, ResourceProviderData p, ResourceAPI* api); protected slots: void triggerSearch() override; diff --git a/launcher/ui/pages/modplatform/ResourcePage.cpp b/launcher/ui/pages/modplatform/ResourcePage.cpp index 8baa0bbec..e85f9b411 100644 --- a/launcher/ui/pages/modplatform/ResourcePage.cpp +++ b/launcher/ui/pages/modplatform/ResourcePage.cpp @@ -57,8 +57,17 @@ namespace ResourceDownload { -ResourcePage::ResourcePage(ResourceDownloadDialog* parent, BaseInstance& baseInstance) - : QWidget(parent), m_baseInstance(baseInstance), m_ui(new Ui::ResourcePage), m_parentDialog(parent), m_fetchProgress(this, false) +ResourcePage::ResourcePage(ResourceDownloadDialog* parent, + BaseInstance& baseInstance, + ResourceDescriptor desc, + ResourceProviderData provider) + : QWidget(parent) + , m_baseInstance(baseInstance) + , m_ui(new Ui::ResourcePage) + , m_parentDialog(parent) + , m_fetchProgress(this, false) + , m_desc(std::move(desc)) + , m_provider(std::move(provider)) { m_ui->setupUi(this); @@ -400,7 +409,7 @@ void ResourcePage::addResourceToPage(ModPlatform::IndexedPack::Ptr pack, ResourceFolderModel* baseModel, QString downloadReason) { - bool isIndexed = !APPLICATION->settings()->get("ModMetadataDisabled").toBool(); + bool isIndexed = m_desc.isIndexed && !APPLICATION->settings()->get("ModMetadataDisabled").toBool(); m_model->addPack(std::move(pack), ver, baseModel, isIndexed, std::move(downloadReason)); } @@ -488,8 +497,18 @@ void ResourcePage::onResourceToggle(const QModelIndex& index) } } -void ResourcePage::openUrl(const QUrl& url) +void ResourcePage::openUrl(const QUrl& _url) { + auto url = _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); + url = QUrl::fromPercentEncoding(query.toUtf8()); // double decoding is necessary + } + } // do not allow other url schemes for security reasons if (!(url.scheme() == "http" || url.scheme() == "https")) { qWarning() << "Unsupported scheme" << url.scheme(); diff --git a/launcher/ui/pages/modplatform/ResourcePage.h b/launcher/ui/pages/modplatform/ResourcePage.h index 03895dcd4..1777dab28 100644 --- a/launcher/ui/pages/modplatform/ResourcePage.h +++ b/launcher/ui/pages/modplatform/ResourcePage.h @@ -25,6 +25,24 @@ namespace ResourceDownload { class ResourceDownloadDialog; class ResourceModel; +struct ResourceProviderData { + QString displayName; + QIcon icon; + QString id; + QString metaEntryBase; + QString debugName; +}; + +struct ResourceDescriptor { + QString helpPage; + QString resourceString = QObject::tr("resource"); + QString resourcesString = QObject::tr("resources"); + + bool supportsFiltering = false; + bool isIndexed = true; + QMap urlHandlers; +}; + class ResourcePage : public QWidget, public BasePage { Q_OBJECT public: @@ -32,23 +50,23 @@ class ResourcePage : public QWidget, public BasePage { ~ResourcePage() override; /* Affects what the user sees */ - auto displayName() const -> QString override = 0; - auto icon() const -> QIcon override = 0; - auto id() const -> QString override = 0; - auto helpPage() const -> QString override = 0; - bool shouldDisplay() const override = 0; + auto displayName() const -> QString override { return m_provider.displayName; }; + auto icon() const -> QIcon override { return m_provider.icon; }; + auto id() const -> QString override { return m_provider.id; }; + auto helpPage() const -> QString override { return m_desc.helpPage; }; + bool shouldDisplay() const override { return true; }; /* Used internally */ - virtual auto metaEntryBase() const -> QString = 0; - virtual auto debugName() const -> QString = 0; + virtual auto metaEntryBase() const -> QString { return m_provider.metaEntryBase; }; + virtual auto debugName() const -> QString { return m_provider.debugName; }; //: The plural version of 'resource' - virtual QString resourcesString() const { return tr("resources"); } + virtual QString resourcesString() const { return m_desc.resourcesString; } //: The singular version of 'resources' - virtual QString resourceString() const { return tr("resource"); } + virtual QString resourceString() const { return m_desc.resourceString; } /* Features this resource's page supports */ - virtual bool supportsFiltering() const = 0; + virtual bool supportsFiltering() const { return m_desc.supportsFiltering; }; void retranslate() override; void openedImpl() override; @@ -65,7 +83,10 @@ class ResourcePage : public QWidget, public BasePage { auto getModel() const -> ResourceModel* { return m_model; } protected: - ResourcePage(ResourceDownloadDialog* parent, BaseInstance&); + ResourcePage(ResourceDownloadDialog* parent, + BaseInstance& baseInstance, + ResourceDescriptor desc = {}, + ResourceProviderData provider = {}); void addSortings(); @@ -100,7 +121,7 @@ class ResourcePage : public QWidget, public BasePage { void onResourceToggle(const QModelIndex& index); /** Associates regex expressions to pages in the order they're given in the map. */ - virtual QMap urlHandlers() const = 0; + virtual QMap urlHandlers() const { return m_desc.urlHandlers; }; virtual void openUrl(const QUrl&); public: @@ -123,6 +144,9 @@ class ResourcePage : public QWidget, public BasePage { QSet m_enableQueue; + ResourceDescriptor m_desc; + ResourceProviderData m_provider; + private: bool m_suppressInitialSearch = false; }; diff --git a/launcher/ui/pages/modplatform/ShaderPackPage.cpp b/launcher/ui/pages/modplatform/ShaderPackPage.cpp index ec5fe7967..319340477 100644 --- a/launcher/ui/pages/modplatform/ShaderPackPage.cpp +++ b/launcher/ui/pages/modplatform/ShaderPackPage.cpp @@ -3,19 +3,59 @@ // SPDX-License-Identifier: GPL-3.0-only #include "ShaderPackPage.h" -#include "modplatform/ModIndex.h" #include "ui_ResourcePage.h" #include "ShaderPackModel.h" -#include "Application.h" #include "ui/dialogs/ResourceDownloadDialog.h" #include namespace ResourceDownload { -ShaderPackResourcePage::ShaderPackResourcePage(ShaderPackDownloadDialog* dialog, BaseInstance& instance) : ResourcePage(dialog, instance) {} +static ResourceDescriptor prepareShaderPackDescriptor() +{ + QMap urlHandlers; + urlHandlers.insert(QRegularExpression::anchoredPattern("(?:www\\.)?modrinth\\.com\\/shaders\\/([^\\/]+)\\/?"), "modrinth"); + urlHandlers.insert(QRegularExpression::anchoredPattern("(?:www\\.)?curseforge\\.com\\/minecraft\\/customization\\/([^\\/]+)\\/?"), + "curseforge"); + urlHandlers.insert(QRegularExpression::anchoredPattern("minecraft\\.curseforge\\.com\\/projects\\/([^\\/]+)\\/?"), "curseforge"); + return { + .helpPage = {}, + //: The singular version of 'shader packs' + .resourceString = QObject::tr("shader pack"), + //: The plural version of 'shader pack' + .resourcesString = QObject::tr("shader packs"), + .supportsFiltering = false, + .isIndexed = true, + .urlHandlers = urlHandlers, + }; +} + +ShaderPackResourcePage::ShaderPackResourcePage(ShaderPackDownloadDialog* dialog, + BaseInstance& instance, + ResourceProviderData p, + ResourceAPI* api) + : ResourcePage(dialog, instance, prepareShaderPackDescriptor(), p) +{ + m_model = new ShaderPackResourceModel(instance, api, debugName(), metaEntryBase()); + m_ui->packView->setModel(m_model); + + addSortings(); + + // 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(m_model, &ResourceModel::versionListUpdated, this, &ResourcePage::versionListUpdated); + connect(m_model, &ResourceModel::projectInfoUpdated, this, &ResourcePage::updateUi); + connect(m_model, &QAbstractListModel::modelReset, this, &ResourcePage::modelReset); + + connect(m_ui->sortByBox, &QComboBox::currentIndexChanged, this, &ShaderPackResourcePage::triggerSearch); + connect(m_ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &ShaderPackResourcePage::onSelectionChanged); + connect(m_ui->versionSelectionBox, &QComboBox::currentIndexChanged, this, &ShaderPackResourcePage::onVersionSelectionChanged); + connect(m_ui->resourceSelectionButton, &QPushButton::clicked, this, &ShaderPackResourcePage::onResourceSelected); + + m_ui->packDescription->setMetaEntry(metaEntryBase()); +} /******** Callbacks to events in the UI (set up in the derived classes) ********/ @@ -32,22 +72,4 @@ void ShaderPackResourcePage::triggerSearch() m_fetchProgress.watch(m_model->activeSearchJob().get()); } -QMap ShaderPackResourcePage::urlHandlers() const -{ - QMap map; - map.insert(QRegularExpression::anchoredPattern("(?:www\\.)?modrinth\\.com\\/shaders\\/([^\\/]+)\\/?"), "modrinth"); - map.insert(QRegularExpression::anchoredPattern(R"((?:www\.)?curseforge\.com\/minecraft\/customization\/([^\/]+)\/?)"), "curseforge"); - map.insert(QRegularExpression::anchoredPattern(R"(minecraft\.curseforge\.com\/projects\/([^\/]+)\/?)"), "curseforge"); - return map; -} - -void ShaderPackResourcePage::addResourceToPage(ModPlatform::IndexedPack::Ptr pack, - ModPlatform::IndexedVersion& version, - ResourceFolderModel* baseModel, - QString downloadReason) -{ - bool isIndexed = !APPLICATION->settings()->get("ModMetadataDisabled").toBool(); - m_model->addPack(pack, version, baseModel, isIndexed, downloadReason); -} - } // namespace ResourceDownload diff --git a/launcher/ui/pages/modplatform/ShaderPackPage.h b/launcher/ui/pages/modplatform/ShaderPackPage.h index 37e3cadef..c5d5bb7f5 100644 --- a/launcher/ui/pages/modplatform/ShaderPackPage.h +++ b/launcher/ui/pages/modplatform/ShaderPackPage.h @@ -5,11 +5,6 @@ #pragma once #include "ui/pages/modplatform/ResourcePage.h" -#include "ui/pages/modplatform/ShaderPackModel.h" - -namespace Ui { -class ResourcePage; -} namespace ResourceDownload { @@ -19,37 +14,7 @@ class ShaderPackResourcePage : public ResourcePage { Q_OBJECT public: - template - static T* create(ShaderPackDownloadDialog* dialog, BaseInstance& instance) - { - auto page = new T(dialog, instance); - auto* model = static_cast(page->getModel()); - - connect(model, &ResourceModel::versionListUpdated, page, &ResourcePage::versionListUpdated); - connect(model, &ResourceModel::projectInfoUpdated, page, &ResourcePage::updateUi); - connect(model, &QAbstractListModel::modelReset, page, &ResourcePage::modelReset); - - return page; - } - - //: The plural version of 'shader pack' - QString resourcesString() const override { return tr("shader packs"); } - //: The singular version of 'shader packs' - QString resourceString() const override { return tr("shader pack"); } - - bool supportsFiltering() const override { return false; }; - - void addResourceToPage(ModPlatform::IndexedPack::Ptr /*unused*/, - ModPlatform::IndexedVersion& /*unused*/, - ResourceFolderModel* /*unused*/, - QString downloadReason = "standalone") override; - - QMap urlHandlers() const override; - - auto helpPage() const -> QString override { return "shaderpack-platform"; } - - protected: - ShaderPackResourcePage(ShaderPackDownloadDialog* dialog, BaseInstance& instance); + ShaderPackResourcePage(ShaderPackDownloadDialog* dialog, BaseInstance& instance, ResourceProviderData p, ResourceAPI* api); protected slots: void triggerSearch() override; diff --git a/launcher/ui/pages/modplatform/TexturePackPage.cpp b/launcher/ui/pages/modplatform/TexturePackPage.cpp new file mode 100644 index 000000000..ac1fe9520 --- /dev/null +++ b/launcher/ui/pages/modplatform/TexturePackPage.cpp @@ -0,0 +1,79 @@ +// SPDX-FileCopyrightText: 2023 flowln +// +// SPDX-License-Identifier: GPL-3.0-only + +#include "TexturePackPage.h" +#include "ui_ResourcePage.h" + +#include "TexturePackModel.h" + +#include "ui/dialogs/ResourceDownloadDialog.h" + +#include + +namespace ResourceDownload { + +static ResourceDescriptor prepareResourcePackDescriptor() +{ + QMap urlHandlers; + urlHandlers.insert(QRegularExpression::anchoredPattern("(?:www\\.)?modrinth\\.com\\/resourcepack\\/([^\\/]+)\\/?"), "modrinth"); + urlHandlers.insert(QRegularExpression::anchoredPattern("(?:www\\.)?curseforge\\.com\\/minecraft\\/texture-packs\\/([^\\/]+)\\/?"), + "curseforge"); + urlHandlers.insert(QRegularExpression::anchoredPattern("minecraft\\.curseforge\\.com\\/projects\\/([^\\/]+)\\/?"), "curseforge"); + return { + .helpPage = {}, + //: The singular version of 'texture packs' + .resourceString = QObject::tr("texture pack"), + //: The plural version of 'texture pack' + .resourcesString = QObject::tr("texture packs"), + .supportsFiltering = false, + .isIndexed = true, + .urlHandlers = urlHandlers, + }; +} + +TexturePackResourcePage::TexturePackResourcePage(TexturePackDownloadDialog* dialog, + BaseInstance& instance, + ResourceProviderData p, + ResourceAPI* api, + TexturePackResourceModel* model) + : ResourcePage(dialog, instance, prepareResourcePackDescriptor(), p) +{ + m_model = model; + if (!m_model) { + m_model = new TexturePackResourceModel(instance, api, debugName(), metaEntryBase()); + } + m_ui->packView->setModel(m_model); + + addSortings(); + + // 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(m_model, &ResourceModel::versionListUpdated, this, &ResourcePage::versionListUpdated); + connect(m_model, &ResourceModel::projectInfoUpdated, this, &ResourcePage::updateUi); + connect(m_model, &QAbstractListModel::modelReset, this, &ResourcePage::modelReset); + + connect(m_ui->sortByBox, &QComboBox::currentIndexChanged, this, &TexturePackResourcePage::triggerSearch); + connect(m_ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &TexturePackResourcePage::onSelectionChanged); + connect(m_ui->versionSelectionBox, &QComboBox::currentIndexChanged, this, &TexturePackResourcePage::onVersionSelectionChanged); + connect(m_ui->resourceSelectionButton, &QPushButton::clicked, this, &TexturePackResourcePage::onResourceSelected); + + m_ui->packDescription->setMetaEntry(metaEntryBase()); +} + +/******** Callbacks to events in the UI (set up in the derived classes) ********/ + +void TexturePackResourcePage::triggerSearch() +{ + m_ui->packView->selectionModel()->setCurrentIndex({}, QItemSelectionModel::SelectionFlag::ClearAndSelect); + m_ui->packView->clearSelection(); + m_ui->packDescription->clear(); + m_ui->versionSelectionBox->clear(); + + updateSelectionButton(); + + static_cast(m_model)->searchWithTerm(getSearchTerm(), m_ui->sortByBox->currentData().toUInt()); + m_fetchProgress.watch(m_model->activeSearchJob().get()); +} + +} // namespace ResourceDownload diff --git a/launcher/ui/pages/modplatform/TexturePackPage.h b/launcher/ui/pages/modplatform/TexturePackPage.h index 262004dfd..54b41e89b 100644 --- a/launcher/ui/pages/modplatform/TexturePackPage.h +++ b/launcher/ui/pages/modplatform/TexturePackPage.h @@ -4,43 +4,25 @@ #pragma once -#include "ui/dialogs/ResourceDownloadDialog.h" -#include "ui/pages/modplatform/ResourcePackPage.h" -#include "ui/pages/modplatform/TexturePackModel.h" -#include "ui_ResourcePage.h" - -namespace Ui { -class ResourcePage; -} +#include "ui/pages/modplatform/ResourcePage.h" namespace ResourceDownload { class TexturePackDownloadDialog; +class TexturePackResourceModel; -class TexturePackResourcePage : public ResourcePackResourcePage { +class TexturePackResourcePage : public ResourcePage { Q_OBJECT public: - template - static T* create(TexturePackDownloadDialog* dialog, BaseInstance& instance) - { - auto page = new T(dialog, instance); - auto model = static_cast(page->getModel()); + TexturePackResourcePage(TexturePackDownloadDialog* dialog, + BaseInstance& instance, + ResourceProviderData p, + ResourceAPI* api, + TexturePackResourceModel* model = nullptr); - connect(model, &ResourceModel::versionListUpdated, page, &ResourcePage::versionListUpdated); - connect(model, &ResourceModel::projectInfoUpdated, page, &ResourcePage::updateUi); - connect(model, &QAbstractListModel::modelReset, page, &ResourcePage::modelReset); - - return page; - } - - //: The plural version of 'texture pack' - inline QString resourcesString() const override { return tr("texture packs"); } - //: The singular version of 'texture packs' - inline QString resourceString() const override { return tr("texture pack"); } - - protected: - TexturePackResourcePage(TexturePackDownloadDialog* dialog, BaseInstance& instance) : ResourcePackResourcePage(dialog, instance) {} + protected slots: + void triggerSearch() override; }; } // namespace ResourceDownload diff --git a/launcher/ui/pages/modplatform/flame/FlamePage.cpp b/launcher/ui/pages/modplatform/flame/FlamePage.cpp index 336133819..f6796408c 100644 --- a/launcher/ui/pages/modplatform/flame/FlamePage.cpp +++ b/launcher/ui/pages/modplatform/flame/FlamePage.cpp @@ -51,14 +51,12 @@ #include "ui/dialogs/NewInstanceDialog.h" #include "ui/widgets/ProjectItem.h" -static FlameAPI api; - FlamePage::FlamePage(NewInstanceDialog* dialog, QWidget* parent) - : QWidget(parent), m_ui(new Ui::FlamePage), m_dialog(dialog), m_fetch_progress(this, false) + : QWidget(parent), m_ui(new Ui::FlamePage), m_dialog(dialog), m_listModel(new Flame::ListModel(this)), m_fetch_progress(this, false) { m_ui->setupUi(this); m_ui->searchEdit->installEventFilter(this); - m_listModel = new Flame::ListModel(this); + m_ui->packView->setModel(m_listModel); m_ui->versionSelectionBox->view()->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); @@ -101,17 +99,17 @@ FlamePage::~FlamePage() bool FlamePage::eventFilter(QObject* watched, QEvent* event) { if (watched == m_ui->searchEdit && event->type() == QEvent::KeyPress) { - QKeyEvent* keyEvent = static_cast(event); + auto* keyEvent = static_cast(event); if (keyEvent->key() == Qt::Key_Return) { triggerSearch(); keyEvent->accept(); return true; - } else { - if (m_search_timer.isActive()) - m_search_timer.stop(); - - m_search_timer.start(350); } + if (m_search_timer.isActive()) { + m_search_timer.stop(); + } + + m_search_timer.start(350); } return QWidget::eventFilter(watched, event); } @@ -171,8 +169,9 @@ void FlamePage::onSelectionChanged(QModelIndex curr, [[maybe_unused]] QModelInde m_current->versions = doc; m_current->versionsLoaded = true; auto pred = [this](const ModPlatform::IndexedVersion& v) { - if (auto filter = m_filterWidget->getFilter()) + if (auto filter = m_filterWidget->getFilter()) { return !filter->checkModpackFilters(v); + } return false; }; #if QT_VERSION >= QT_VERSION_CHECK(6, 1, 0) @@ -184,15 +183,16 @@ void FlamePage::onSelectionChanged(QModelIndex curr, [[maybe_unused]] QModelInde else ++it; #endif - for (auto version : m_current->versions) { + for (const auto& version : m_current->versions) { m_ui->versionSelectionBox->addItem(version.getVersionDisplayString(), QVariant(version.downloadUrl)); } QVariant current_updated; current_updated.setValue(m_current); - if (!m_listModel->setData(curr, current_updated, Qt::UserRole)) + if (!m_listModel->setData(curr, current_updated, Qt::UserRole)) { qWarning() << "Failed to cache versions for the current pack!"; + } // TODO: Check whether it's a connection issue or the project disabled 3rd-party distribution. if (m_current->versionsLoaded && m_ui->versionSelectionBox->count() < 1) { @@ -200,16 +200,16 @@ void FlamePage::onSelectionChanged(QModelIndex curr, [[maybe_unused]] QModelInde } suggestCurrent(); }; - callbacks.on_fail = [this](QString reason, int) { + callbacks.on_fail = [this](const QString& reason, int) { CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->exec(); }; - auto netJob = api.getProjectVersions({ m_current, {}, {}, ModPlatform::ResourceType::Modpack }, std::move(callbacks)); + auto netJob = FlameAPI().getProjectVersions({ m_current, {}, {}, ModPlatform::ResourceType::Modpack }, std::move(callbacks)); m_job = netJob; netJob->start(); } else { - for (auto version : m_current->versions) { + for (const auto& version : m_current->versions) { m_ui->versionSelectionBox->addItem(version.version, QVariant(version.downloadUrl)); } @@ -244,7 +244,7 @@ void FlamePage::suggestCurrent() m_dialog->setSuggestedPack(m_current->name, new InstanceImportTask(version.downloadUrl, this, std::move(extra_info))); QString editedLogoName = "curseforge_" + m_current->logoName; m_listModel->getLogo(m_current->logoName, m_current->logoUrl, - [this, editedLogoName](QString logo) { m_dialog->setSuggestedIconFromFile(logo, editedLogoName); }); + [this, editedLogoName](const QString& logo) { m_dialog->setSuggestedIconFromFile(logo, editedLogoName); }); } void FlamePage::onVersionSelectionChanged(int index) @@ -269,10 +269,11 @@ void FlamePage::updateUi() QString text = ""; QString name = m_current->name; - if (m_current->websiteUrl.isEmpty()) + if (m_current->websiteUrl.isEmpty()) { text = name; - else + } else { text = "websiteUrl + "\">" + name + ""; + } if (!m_current->authors.empty()) { auto authorToStr = [](ModPlatform::ModpackAuthor& author) { if (author.url.isEmpty()) { @@ -293,16 +294,19 @@ void FlamePage::updateUi() text += "

" + tr("External links:") + "
"; } - if (!m_current->extraData.issuesUrl.isEmpty()) + if (!m_current->extraData.issuesUrl.isEmpty()) { text += "- " + tr("Issues: %1").arg(m_current->extraData.issuesUrl) + "
"; - if (!m_current->extraData.wikiUrl.isEmpty()) + } + if (!m_current->extraData.wikiUrl.isEmpty()) { text += "- " + tr("Wiki: %1").arg(m_current->extraData.wikiUrl) + "
"; - if (!m_current->extraData.sourceUrl.isEmpty()) + } + if (!m_current->extraData.sourceUrl.isEmpty()) { text += "- " + tr("Source code: %1").arg(m_current->extraData.sourceUrl) + "
"; + } } text += "
"; - text += api.getModDescription(m_current->addonId.toInt()).toUtf8(); + text += FlameAPI().getModDescription(m_current->addonId.toInt()).toUtf8(); m_ui->packDescription->setHtml(StringUtils::htmlListPatch(text + m_current->description)); m_ui->packDescription->flush(); @@ -319,12 +323,12 @@ void FlamePage::setSearchTerm(QString term) void FlamePage::createFilterWidget() { - auto widget = ModFilterWidget::create(nullptr, false); - m_filterWidget.swap(widget); - auto old = m_ui->splitter->replaceWidget(0, m_filterWidget.get()); + auto* widget = ModFilterWidget::create(nullptr, false); + m_filterWidget.reset(widget); + auto* old = m_ui->splitter->replaceWidget(0, m_filterWidget.get()); // because we replaced the widget we also need to delete it if (old) { - delete old; + old->deleteLater(); } connect(m_ui->filterButton, &QPushButton::clicked, this, [this] { m_filterWidget->setHidden(!m_filterWidget->isHidden()); }); @@ -333,7 +337,7 @@ void FlamePage::createFilterWidget() auto [task, response] = FlameAPI::getCategories(ModPlatform::ResourceType::Modpack); m_categoriesTask = task; connect(m_categoriesTask.get(), &Task::succeeded, [this, response]() { - auto categories = FlameAPI::loadModCategories(*response); + auto categories = FlameAPI().loadModCategories(*response); m_filterWidget->setCategories(categories); }); m_categoriesTask->start(); diff --git a/launcher/ui/pages/modplatform/flame/FlamePage.h b/launcher/ui/pages/modplatform/flame/FlamePage.h index eb763229f..17cf5b097 100644 --- a/launcher/ui/pages/modplatform/flame/FlamePage.h +++ b/launcher/ui/pages/modplatform/flame/FlamePage.h @@ -82,7 +82,7 @@ class FlamePage : public QWidget, public ModpackProviderBasePage { private slots: void triggerSearch(); - void onSelectionChanged(QModelIndex first, QModelIndex second); + void onSelectionChanged(QModelIndex curr, QModelIndex prev); void onVersionSelectionChanged(int index); void createFilterWidget(); diff --git a/launcher/ui/pages/modplatform/flame/FlameResourceModels.h b/launcher/ui/pages/modplatform/flame/FlameResourceModels.h index 76062f8e6..f719aa46d 100644 --- a/launcher/ui/pages/modplatform/flame/FlameResourceModels.h +++ b/launcher/ui/pages/modplatform/flame/FlameResourceModels.h @@ -4,8 +4,7 @@ #pragma once -#include "ui/pages/modplatform/ModModel.h" -#include "ui/pages/modplatform/flame/FlameResourcePages.h" +#include "ui/pages/modplatform/TexturePackModel.h" namespace ResourceDownload { @@ -19,9 +18,6 @@ class FlameTexturePackModel : public TexturePackResourceModel { bool optedOut(const ModPlatform::IndexedVersion& ver) const override; private: - QString debugName() const override { return Flame::debugName() + " (Model)"; } - QString metaEntryBase() const override { return Flame::metaEntryBase(); } - ResourceAPI::SearchArgs createSearchArguments() override; ResourceAPI::VersionSearchArgs createVersionsArguments(const QModelIndex&) override; }; diff --git a/launcher/ui/pages/modplatform/flame/FlameResourcePages.cpp b/launcher/ui/pages/modplatform/flame/FlameResourcePages.cpp index acdce29b6..85e004d29 100644 --- a/launcher/ui/pages/modplatform/flame/FlameResourcePages.cpp +++ b/launcher/ui/pages/modplatform/flame/FlameResourcePages.cpp @@ -38,221 +38,48 @@ */ #include "FlameResourcePages.h" -#include -#include + #include "modplatform/flame/FlameAPI.h" -#include "../ui_ResourcePage.h" #include "FlameResourceModels.h" #include "ui/dialogs/ResourceDownloadDialog.h" namespace ResourceDownload { -FlameModPage::FlameModPage(ModDownloadDialog* dialog, BaseInstance& instance) : ModPage(dialog, instance) +static ResourceProviderData prepareFlame() { - m_model = new ModModel(instance, new FlameAPI(), Flame::debugName(), Flame::metaEntryBase()); - m_ui->packView->setModel(m_model); - - addSortings(); - - // 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(m_ui->sortByBox, &QComboBox::currentIndexChanged, this, &FlameModPage::triggerSearch); - connect(m_ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &FlameModPage::onSelectionChanged); - connect(m_ui->versionSelectionBox, &QComboBox::currentIndexChanged, this, &FlameModPage::onVersionSelectionChanged); - connect(m_ui->resourceSelectionButton, &QPushButton::clicked, this, &FlameModPage::onResourceSelected); - - m_ui->packDescription->setMetaEntry(metaEntryBase()); + return { + .displayName = Flame::displayName(), + .icon = Flame::icon(), + .id = Flame::id(), + .metaEntryBase = Flame::metaEntryBase(), + .debugName = Flame::debugName(), + }; } -void FlameModPage::openUrl(const QUrl& url) +ShaderPackResourcePage* Flame::createShaderPackResourcePage(ShaderPackDownloadDialog* dialog, BaseInstance& instance) { - 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); + return new ShaderPackResourcePage(dialog, instance, prepareFlame(), new FlameAPI()); } -FlameResourcePackPage::FlameResourcePackPage(ResourcePackDownloadDialog* dialog, BaseInstance& instance) - : ResourcePackResourcePage(dialog, instance) +DataPackResourcePage* Flame::createDataPackResourcePage(DataPackDownloadDialog* dialog, BaseInstance& instance) { - m_model = new ResourcePackResourceModel(instance, new FlameAPI(), Flame::debugName(), Flame::metaEntryBase()); - m_ui->packView->setModel(m_model); - - addSortings(); - - // 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(m_ui->sortByBox, &QComboBox::currentIndexChanged, this, &FlameResourcePackPage::triggerSearch); - connect(m_ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &FlameResourcePackPage::onSelectionChanged); - connect(m_ui->versionSelectionBox, &QComboBox::currentIndexChanged, this, &FlameResourcePackPage::onVersionSelectionChanged); - connect(m_ui->resourceSelectionButton, &QPushButton::clicked, this, &FlameResourcePackPage::onResourceSelected); - - m_ui->packDescription->setMetaEntry(metaEntryBase()); + return new DataPackResourcePage(dialog, instance, prepareFlame(), new FlameAPI()); } -void FlameResourcePackPage::openUrl(const QUrl& url) +ResourcePackResourcePage* Flame::createResourcePackResourcePage(ResourcePackDownloadDialog* dialog, BaseInstance& instance) { - 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); - ResourcePackResourcePage::openUrl({ QUrl::fromPercentEncoding(query.toUtf8()) }); // double decoding is necessary - return; - } - } - - ResourcePackResourcePage::openUrl(url); + return new ResourcePackResourcePage(dialog, instance, prepareFlame(), new FlameAPI()); } -FlameTexturePackPage::FlameTexturePackPage(TexturePackDownloadDialog* dialog, BaseInstance& instance) - : TexturePackResourcePage(dialog, instance) +TexturePackResourcePage* Flame::createTexturePackResourcePage(TexturePackDownloadDialog* dialog, BaseInstance& instance) { - m_model = new FlameTexturePackModel(instance); - m_ui->packView->setModel(m_model); - - addSortings(); - - // 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(m_ui->sortByBox, &QComboBox::currentIndexChanged, this, &FlameTexturePackPage::triggerSearch); - connect(m_ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &FlameTexturePackPage::onSelectionChanged); - connect(m_ui->versionSelectionBox, &QComboBox::currentIndexChanged, this, &FlameTexturePackPage::onVersionSelectionChanged); - connect(m_ui->resourceSelectionButton, &QPushButton::clicked, this, &FlameTexturePackPage::onResourceSelected); - - m_ui->packDescription->setMetaEntry(metaEntryBase()); + return new TexturePackResourcePage(dialog, instance, prepareFlame(), new FlameAPI(), new FlameTexturePackModel(instance)); } -void FlameTexturePackPage::openUrl(const QUrl& url) +ModPage* Flame::createModPage(ModDownloadDialog* dialog, BaseInstance& instance) { - 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); - ResourcePackResourcePage::openUrl({ QUrl::fromPercentEncoding(query.toUtf8()) }); // double decoding is necessary - return; - } - } - - TexturePackResourcePage::openUrl(url); + return new ModPage(dialog, instance, prepareFlame(), new FlameAPI(), + ModFilterWidget::create(&static_cast(instance), false)); } - -void FlameDataPackPage::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); - DataPackResourcePage::openUrl({ QUrl::fromPercentEncoding(query.toUtf8()) }); // double decoding is necessary - return; - } - } - - DataPackResourcePage::openUrl(url); -} - -FlameShaderPackPage::FlameShaderPackPage(ShaderPackDownloadDialog* dialog, BaseInstance& instance) - : ShaderPackResourcePage(dialog, instance) -{ - m_model = new ShaderPackResourceModel(instance, new FlameAPI(), Flame::debugName(), Flame::metaEntryBase()); - m_ui->packView->setModel(m_model); - - addSortings(); - - // 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(m_ui->sortByBox, &QComboBox::currentIndexChanged, this, &FlameShaderPackPage::triggerSearch); - connect(m_ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &FlameShaderPackPage::onSelectionChanged); - connect(m_ui->versionSelectionBox, &QComboBox::currentIndexChanged, this, &FlameShaderPackPage::onVersionSelectionChanged); - connect(m_ui->resourceSelectionButton, &QPushButton::clicked, this, &FlameShaderPackPage::onResourceSelected); - - m_ui->packDescription->setMetaEntry(metaEntryBase()); -} - -FlameDataPackPage::FlameDataPackPage(DataPackDownloadDialog* dialog, BaseInstance& instance) : DataPackResourcePage(dialog, instance) -{ - m_model = new DataPackResourceModel(instance, new FlameAPI(), Flame::debugName(), Flame::metaEntryBase()); - m_ui->packView->setModel(m_model); - - addSortings(); - - // 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(m_ui->sortByBox, &QComboBox::currentIndexChanged, this, &FlameDataPackPage::triggerSearch); - connect(m_ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &FlameDataPackPage::onSelectionChanged); - connect(m_ui->versionSelectionBox, &QComboBox::currentIndexChanged, this, &FlameDataPackPage::onVersionSelectionChanged); - connect(m_ui->resourceSelectionButton, &QPushButton::clicked, this, &FlameDataPackPage::onResourceSelected); - - m_ui->packDescription->setMetaEntry(metaEntryBase()); -} - -void FlameShaderPackPage::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); - ShaderPackResourcePage::openUrl({ QUrl::fromPercentEncoding(query.toUtf8()) }); // double decoding is necessary - return; - } - } - - ShaderPackResourcePage::openUrl(url); -} - -// I don't know why, but doing this on the parent class makes it so that -// 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; -} -auto FlameResourcePackPage::shouldDisplay() const -> bool -{ - return true; -} -auto FlameTexturePackPage::shouldDisplay() const -> bool -{ - return true; -} -auto FlameShaderPackPage::shouldDisplay() const -> bool -{ - return true; -} -auto FlameDataPackPage::shouldDisplay() const -> bool -{ - return true; -} - -std::unique_ptr FlameModPage::createFilterWidget() -{ - return ModFilterWidget::create(&static_cast(m_baseInstance), false); -} - -void FlameModPage::prepareProviderCategories() -{ - auto [task, response] = FlameAPI::getModCategories(); - m_categoriesTask = task; - connect(m_categoriesTask.get(), &Task::succeeded, [this, response]() { - auto categories = FlameAPI::loadModCategories(*response); - m_filter_widget->setCategories(categories); - }); - m_categoriesTask->start(); -}; } // namespace ResourceDownload diff --git a/launcher/ui/pages/modplatform/flame/FlameResourcePages.h b/launcher/ui/pages/modplatform/flame/FlameResourcePages.h index d4b697ae0..d9f1fe996 100644 --- a/launcher/ui/pages/modplatform/flame/FlameResourcePages.h +++ b/launcher/ui/pages/modplatform/flame/FlameResourcePages.h @@ -39,12 +39,10 @@ #pragma once -#include - -#include "modplatform/ResourceAPI.h" - +#include "ui/pages/modplatform/DataPackPage.h" #include "ui/pages/modplatform/ModPage.h" #include "ui/pages/modplatform/ResourcePackPage.h" +#include "ui/pages/modplatform/ResourcePage.h" #include "ui/pages/modplatform/ShaderPackPage.h" #include "ui/pages/modplatform/TexturePackPage.h" @@ -71,138 +69,12 @@ static inline QString metaEntryBase() { return "FlameMods"; } + +ShaderPackResourcePage* createShaderPackResourcePage(ShaderPackDownloadDialog* dialog, BaseInstance& instance); +DataPackResourcePage* createDataPackResourcePage(DataPackDownloadDialog* dialog, BaseInstance& instance); +ResourcePackResourcePage* createResourcePackResourcePage(ResourcePackDownloadDialog* dialog, BaseInstance& instance); +TexturePackResourcePage* createTexturePackResourcePage(TexturePackDownloadDialog* dialog, BaseInstance& instance); +ModPage* createModPage(ModDownloadDialog* dialog, BaseInstance& instance); } // namespace Flame -class FlameModPage : public ModPage { - Q_OBJECT - - public: - static FlameModPage* create(ModDownloadDialog* dialog, BaseInstance& instance) - { - return ModPage::create(dialog, instance); - } - - FlameModPage(ModDownloadDialog* dialog, BaseInstance& instance); - ~FlameModPage() override = default; - - bool shouldDisplay() const override; - - inline auto displayName() const -> QString override { return Flame::displayName(); } - inline auto icon() const -> QIcon override { return Flame::icon(); } - inline auto id() const -> QString override { return Flame::id(); } - inline auto debugName() const -> QString override { return Flame::debugName(); } - inline auto metaEntryBase() const -> QString override { return Flame::metaEntryBase(); } - - inline auto helpPage() const -> QString override { return "Mod-platform"; } - - void openUrl(const QUrl& url) override; - std::unique_ptr createFilterWidget() override; - - protected: - virtual void prepareProviderCategories() override; - - private: - Task::Ptr m_categoriesTask; -}; - -class FlameResourcePackPage : public ResourcePackResourcePage { - Q_OBJECT - - public: - static FlameResourcePackPage* create(ResourcePackDownloadDialog* dialog, BaseInstance& instance) - { - return ResourcePackResourcePage::create(dialog, instance); - } - - FlameResourcePackPage(ResourcePackDownloadDialog* dialog, BaseInstance& instance); - ~FlameResourcePackPage() override = default; - - bool shouldDisplay() const override; - - inline auto displayName() const -> QString override { return Flame::displayName(); } - inline auto icon() const -> QIcon override { return Flame::icon(); } - inline auto id() const -> QString override { return Flame::id(); } - inline auto debugName() const -> QString override { return Flame::debugName(); } - inline auto metaEntryBase() const -> QString override { return Flame::metaEntryBase(); } - - inline auto helpPage() const -> QString override { return ""; } - - void openUrl(const QUrl& url) override; -}; - -class FlameTexturePackPage : public TexturePackResourcePage { - Q_OBJECT - - public: - static FlameTexturePackPage* create(TexturePackDownloadDialog* dialog, BaseInstance& instance) - { - return TexturePackResourcePage::create(dialog, instance); - } - - FlameTexturePackPage(TexturePackDownloadDialog* dialog, BaseInstance& instance); - ~FlameTexturePackPage() override = default; - - bool shouldDisplay() const override; - - inline auto displayName() const -> QString override { return Flame::displayName(); } - inline auto icon() const -> QIcon override { return Flame::icon(); } - inline auto id() const -> QString override { return Flame::id(); } - inline auto debugName() const -> QString override { return Flame::debugName(); } - inline auto metaEntryBase() const -> QString override { return Flame::metaEntryBase(); } - - inline auto helpPage() const -> QString override { return ""; } - - void openUrl(const QUrl& url) override; -}; - -class FlameShaderPackPage : public ShaderPackResourcePage { - Q_OBJECT - - public: - static FlameShaderPackPage* create(ShaderPackDownloadDialog* dialog, BaseInstance& instance) - { - return ShaderPackResourcePage::create(dialog, instance); - } - - FlameShaderPackPage(ShaderPackDownloadDialog* dialog, BaseInstance& instance); - ~FlameShaderPackPage() override = default; - - bool shouldDisplay() const override; - - inline auto displayName() const -> QString override { return Flame::displayName(); } - inline auto icon() const -> QIcon override { return Flame::icon(); } - inline auto id() const -> QString override { return Flame::id(); } - inline auto debugName() const -> QString override { return Flame::debugName(); } - inline auto metaEntryBase() const -> QString override { return Flame::metaEntryBase(); } - - inline auto helpPage() const -> QString override { return ""; } - - void openUrl(const QUrl& url) override; -}; - -class FlameDataPackPage : public DataPackResourcePage { - Q_OBJECT - - public: - static FlameDataPackPage* create(DataPackDownloadDialog* dialog, BaseInstance& instance) - { - return DataPackResourcePage::create(dialog, instance); - } - - FlameDataPackPage(DataPackDownloadDialog* dialog, BaseInstance& instance); - ~FlameDataPackPage() override = default; - - bool shouldDisplay() const override; - - inline auto displayName() const -> QString override { return Flame::displayName(); } - inline auto icon() const -> QIcon override { return Flame::icon(); } - inline auto id() const -> QString override { return Flame::id(); } - inline auto debugName() const -> QString override { return Flame::debugName(); } - inline auto metaEntryBase() const -> QString override { return Flame::metaEntryBase(); } - - inline auto helpPage() const -> QString override { return ""; } - - void openUrl(const QUrl& url) override; -}; - } // namespace ResourceDownload diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp b/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp index 4798583bd..c7e9fdeb1 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp @@ -43,28 +43,28 @@ #include "ModrinthModel.h" -#include "BuildConfig.h" #include "InstanceImportTask.h" -#include "Json.h" #include "Markdown.h" #include "StringUtils.h" #include "ui/widgets/ProjectItem.h" -#include "net/ApiDownload.h" - #include #include #include ModrinthPage::ModrinthPage(NewInstanceDialog* dialog, QWidget* parent) - : QWidget(parent), m_ui(new Ui::ModrinthPage), m_dialog(dialog), m_fetch_progress(this, false) + : QWidget(parent) + , m_ui(new Ui::ModrinthPage) + , m_dialog(dialog) + , m_model(new Modrinth::ModpackListModel(this)) + , m_fetch_progress(this, false) { m_ui->setupUi(this); createFilterWidget(); m_ui->searchEdit->installEventFilter(this); - m_model = new Modrinth::ModpackListModel(this); + m_ui->packView->setModel(m_model); m_ui->versionSelectionBox->view()->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); @@ -116,17 +116,17 @@ void ModrinthPage::openedImpl() bool ModrinthPage::eventFilter(QObject* watched, QEvent* event) { if (watched == m_ui->searchEdit && event->type() == QEvent::KeyPress) { - auto* keyEvent = reinterpret_cast(event); + auto* keyEvent = static_cast(event); if (keyEvent->key() == Qt::Key_Return) { this->triggerSearch(); keyEvent->accept(); return true; - } else { - if (m_search_timer.isActive()) - m_search_timer.stop(); - - m_search_timer.start(350); } + if (m_search_timer.isActive()) { + m_search_timer.stop(); + } + + m_search_timer.start(350); } return QObject::eventFilter(watched, event); } @@ -150,7 +150,7 @@ void ModrinthPage::onSelectionChanged(QModelIndex curr, [[maybe_unused]] QModelI ResourceAPI::Callback callbacks; auto id = m_current->addonId; - callbacks.on_fail = [this](QString reason, int) { + callbacks.on_fail = [this](const QString& reason, int) { CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->exec(); }; callbacks.on_succeed = [this, id, curr](auto& pack) { @@ -161,8 +161,9 @@ void ModrinthPage::onSelectionChanged(QModelIndex curr, [[maybe_unused]] QModelI QVariant current_updated; current_updated.setValue(pack); - if (!m_model->setData(curr, current_updated, Qt::UserRole)) + if (!m_model->setData(curr, current_updated, Qt::UserRole)) { qWarning() << "Failed to cache extra info for the current pack!"; + } suggestCurrent(); updateUI(); @@ -172,8 +173,9 @@ void ModrinthPage::onSelectionChanged(QModelIndex curr, [[maybe_unused]] QModelI m_job->start(); } - } else + } else { updateUI(); + } if (!m_current->versionsLoaded || m_filterWidget->changed()) { qDebug() << "Loading modrinth modpack versions"; @@ -190,8 +192,9 @@ void ModrinthPage::onSelectionChanged(QModelIndex curr, [[maybe_unused]] QModelI m_current->versions = doc; m_current->versionsLoaded = true; auto pred = [this](const ModPlatform::IndexedVersion& v) { - if (auto filter = m_filterWidget->getFilter()) + if (auto filter = m_filterWidget->getFilter()) { return !filter->checkModpackFilters(v); + } return false; }; #if QT_VERSION >= QT_VERSION_CHECK(6, 1, 0) @@ -210,12 +213,13 @@ void ModrinthPage::onSelectionChanged(QModelIndex curr, [[maybe_unused]] QModelI QVariant current_updated; current_updated.setValue(m_current); - if (!m_model->setData(curr, current_updated, Qt::UserRole)) + if (!m_model->setData(curr, current_updated, Qt::UserRole)) { qWarning() << "Failed to cache versions for the current pack!"; + } suggestCurrent(); }; - callbacks.on_fail = [this](QString reason, int) { + callbacks.on_fail = [this](const QString& reason, int) { CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->exec(); }; @@ -225,12 +229,13 @@ void ModrinthPage::onSelectionChanged(QModelIndex curr, [[maybe_unused]] QModelI m_job2->start(); } else { - for (auto version : m_current->versions) { - if (!version.version.contains(version.version)) + for (const auto& version : m_current->versions) { + if (!version.version.contains(version.version)) { m_ui->versionSelectionBox->addItem(QString("%1 - %2").arg(version.version, version.version_number), QVariant(version.fileId)); - else + } else { m_ui->versionSelectionBox->addItem(version.version, QVariant(version.fileId)); + } } suggestCurrent(); @@ -283,14 +288,18 @@ void ModrinthPage::updateUI() text += "

" + tr("External links:") + "
"; } - if (!m_current->extraData.issuesUrl.isEmpty()) + if (!m_current->extraData.issuesUrl.isEmpty()) { text += "- " + tr("Issues: %1").arg(m_current->extraData.issuesUrl) + "
"; - if (!m_current->extraData.wikiUrl.isEmpty()) + } + if (!m_current->extraData.wikiUrl.isEmpty()) { text += "- " + tr("Wiki: %1").arg(m_current->extraData.wikiUrl) + "
"; - if (!m_current->extraData.sourceUrl.isEmpty()) + } + if (!m_current->extraData.sourceUrl.isEmpty()) { text += "- " + tr("Source code: %1").arg(m_current->extraData.sourceUrl) + "
"; - if (!m_current->extraData.discordUrl.isEmpty()) + } + if (!m_current->extraData.discordUrl.isEmpty()) { text += "- " + tr("Discord: %1").arg(m_current->extraData.discordUrl) + "
"; + } } text += "
"; @@ -321,7 +330,7 @@ void ModrinthPage::suggestCurrent() m_dialog->setSuggestedPack(m_current->name, ver.version, new InstanceImportTask(ver.downloadUrl, this, std::move(extra_info))); QString editedLogoName = "modrinth_" + m_current->logoName; m_model->getLogo(m_current->logoName, m_current->logoUrl, - [this, editedLogoName](QString logo) { m_dialog->setSuggestedIconFromFile(logo, editedLogoName); }); + [this, editedLogoName](const QString& logo) { m_dialog->setSuggestedIconFromFile(logo, editedLogoName); }); break; } @@ -361,18 +370,18 @@ QString ModrinthPage::getSerachTerm() const void ModrinthPage::createFilterWidget() { - auto widget = ModFilterWidget::create(nullptr, true); - m_filterWidget.swap(widget); - auto old = m_ui->splitter->replaceWidget(0, m_filterWidget.get()); + auto* widget = ModFilterWidget::create(nullptr, true); + m_filterWidget.reset(widget); + auto* old = m_ui->splitter->replaceWidget(0, m_filterWidget.get()); // because we replaced the widget we also need to delete it if (old) { - delete old; + old->deleteLater(); } connect(m_ui->filterButton, &QPushButton::clicked, this, [this] { m_filterWidget->setHidden(!m_filterWidget->isHidden()); }); connect(m_filterWidget.get(), &ModFilterWidget::filterChanged, this, &ModrinthPage::triggerSearch); - auto [categoriesTask, response] = ModrinthAPI::getModCategories(); + auto [categoriesTask, response] = ModrinthAPI().getModCategories(); m_categoriesTask = categoriesTask; connect(m_categoriesTask.get(), &Task::succeeded, [this, response]() { auto categories = ModrinthAPI::loadCategories(*response, "modpack"); diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthPage.h b/launcher/ui/pages/modplatform/modrinth/ModrinthPage.h index 4ca41a3e0..f8a4f4342 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthPage.h +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthPage.h @@ -67,8 +67,8 @@ class ModrinthPage : public QWidget, public ModpackProviderBasePage { QString id() const override { return "modrinth"; } QString helpPage() const override { return "Modrinth-platform"; } - inline QString debugName() const { return "Modrinth"; } - inline QString metaEntryBase() const { return "ModrinthModpacks"; }; + static QString debugName() { return "Modrinth"; } + static QString metaEntryBase() { return "ModrinthModpacks"; }; ModPlatform::IndexedPack::Ptr getCurrent() { return m_current; } void suggestCurrent(); @@ -80,12 +80,12 @@ class ModrinthPage : public QWidget, public ModpackProviderBasePage { bool eventFilter(QObject* watched, QEvent* event) override; /** Programatically set the term in the search bar. */ - virtual void setSearchTerm(QString) override; + void setSearchTerm(QString) override; /** Get the current term in the search bar. */ - virtual QString getSerachTerm() const override; + QString getSerachTerm() const override; private slots: - void onSelectionChanged(QModelIndex first, QModelIndex second); + void onSelectionChanged(QModelIndex curr, QModelIndex prev); void onVersionSelectionChanged(int index); void triggerSearch(); void createFilterWidget(); diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.cpp b/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.cpp index a1a7390bb..c4d3025d2 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.cpp +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.cpp @@ -37,8 +37,6 @@ */ #include "ModrinthResourcePages.h" -#include "ui/pages/modplatform/DataPackModel.h" -#include "../ui_ResourcePage.h" #include "modplatform/modrinth/ModrinthAPI.h" @@ -46,131 +44,40 @@ namespace ResourceDownload { -ModrinthModPage::ModrinthModPage(ModDownloadDialog* dialog, BaseInstance& instance) : ModPage(dialog, instance) +static ResourceProviderData prepareModrinth() { - m_model = new ModModel(instance, new ModrinthAPI(), Modrinth::debugName(), Modrinth::metaEntryBase()); - m_ui->packView->setModel(m_model); - - addSortings(); - - // 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(m_ui->sortByBox, &QComboBox::currentIndexChanged, this, &ModrinthModPage::triggerSearch); - connect(m_ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &ModrinthModPage::onSelectionChanged); - connect(m_ui->versionSelectionBox, &QComboBox::currentIndexChanged, this, &ModrinthModPage::onVersionSelectionChanged); - connect(m_ui->resourceSelectionButton, &QPushButton::clicked, this, &ModrinthModPage::onResourceSelected); - - m_ui->packDescription->setMetaEntry(metaEntryBase()); + return { + .displayName = Modrinth::displayName(), + .icon = Modrinth::icon(), + .id = Modrinth::id(), + .metaEntryBase = Modrinth::metaEntryBase(), + .debugName = Modrinth::debugName(), + }; } -ModrinthResourcePackPage::ModrinthResourcePackPage(ResourcePackDownloadDialog* dialog, BaseInstance& instance) - : ResourcePackResourcePage(dialog, instance) +ShaderPackResourcePage* Modrinth::createShaderPackResourcePage(ShaderPackDownloadDialog* dialog, BaseInstance& instance) { - m_model = new ResourcePackResourceModel(instance, new ModrinthAPI(), Modrinth::debugName(), Modrinth::metaEntryBase()); - m_ui->packView->setModel(m_model); - - addSortings(); - - // 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(m_ui->sortByBox, &QComboBox::currentIndexChanged, this, &ModrinthResourcePackPage::triggerSearch); - connect(m_ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &ModrinthResourcePackPage::onSelectionChanged); - connect(m_ui->versionSelectionBox, &QComboBox::currentIndexChanged, this, &ModrinthResourcePackPage::onVersionSelectionChanged); - connect(m_ui->resourceSelectionButton, &QPushButton::clicked, this, &ModrinthResourcePackPage::onResourceSelected); - - m_ui->packDescription->setMetaEntry(metaEntryBase()); + return new ShaderPackResourcePage(dialog, instance, prepareModrinth(), new ModrinthAPI()); } -ModrinthTexturePackPage::ModrinthTexturePackPage(TexturePackDownloadDialog* dialog, BaseInstance& instance) - : TexturePackResourcePage(dialog, instance) +DataPackResourcePage* Modrinth::createDataPackResourcePage(DataPackDownloadDialog* dialog, BaseInstance& instance) { - m_model = new TexturePackResourceModel(instance, new ModrinthAPI(), Modrinth::debugName(), Modrinth::metaEntryBase()); - m_ui->packView->setModel(m_model); - - addSortings(); - - // 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(m_ui->sortByBox, &QComboBox::currentIndexChanged, this, &ModrinthTexturePackPage::triggerSearch); - connect(m_ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &ModrinthTexturePackPage::onSelectionChanged); - connect(m_ui->versionSelectionBox, &QComboBox::currentIndexChanged, this, &ModrinthTexturePackPage::onVersionSelectionChanged); - connect(m_ui->resourceSelectionButton, &QPushButton::clicked, this, &ModrinthTexturePackPage::onResourceSelected); - - m_ui->packDescription->setMetaEntry(metaEntryBase()); + return new DataPackResourcePage(dialog, instance, prepareModrinth(), new ModrinthAPI()); } -ModrinthShaderPackPage::ModrinthShaderPackPage(ShaderPackDownloadDialog* dialog, BaseInstance& instance) - : ShaderPackResourcePage(dialog, instance) +ResourcePackResourcePage* Modrinth::createResourcePackResourcePage(ResourcePackDownloadDialog* dialog, BaseInstance& instance) { - m_model = new ShaderPackResourceModel(instance, new ModrinthAPI(), Modrinth::debugName(), Modrinth::metaEntryBase()); - m_ui->packView->setModel(m_model); - - addSortings(); - - // 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(m_ui->sortByBox, &QComboBox::currentIndexChanged, this, &ModrinthShaderPackPage::triggerSearch); - connect(m_ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &ModrinthShaderPackPage::onSelectionChanged); - connect(m_ui->versionSelectionBox, &QComboBox::currentIndexChanged, this, &ModrinthShaderPackPage::onVersionSelectionChanged); - connect(m_ui->resourceSelectionButton, &QPushButton::clicked, this, &ModrinthShaderPackPage::onResourceSelected); - - m_ui->packDescription->setMetaEntry(metaEntryBase()); + return new ResourcePackResourcePage(dialog, instance, prepareModrinth(), new ModrinthAPI()); } -ModrinthDataPackPage::ModrinthDataPackPage(DataPackDownloadDialog* dialog, BaseInstance& instance) : DataPackResourcePage(dialog, instance) +TexturePackResourcePage* Modrinth::createTexturePackResourcePage(TexturePackDownloadDialog* dialog, BaseInstance& instance) { - m_model = new DataPackResourceModel(instance, new ModrinthAPI(), Modrinth::debugName(), Modrinth::metaEntryBase()); - m_ui->packView->setModel(m_model); - - addSortings(); - - // 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(m_ui->sortByBox, &QComboBox::currentIndexChanged, this, &ModrinthDataPackPage::triggerSearch); - connect(m_ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &ModrinthDataPackPage::onSelectionChanged); - connect(m_ui->versionSelectionBox, &QComboBox::currentIndexChanged, this, &ModrinthDataPackPage::onVersionSelectionChanged); - connect(m_ui->resourceSelectionButton, &QPushButton::clicked, this, &ModrinthDataPackPage::onResourceSelected); - - m_ui->packDescription->setMetaEntry(metaEntryBase()); + return new TexturePackResourcePage(dialog, instance, prepareModrinth(), new ModrinthAPI()); } -// I don't know why, but doing this on the parent class makes it so that -// other mod providers start loading before being selected, at least with -// my Qt, so we need to implement this in every derived class... -auto ModrinthModPage::shouldDisplay() const -> bool +ModPage* Modrinth::createModPage(ModDownloadDialog* dialog, BaseInstance& instance) { - return true; + return new ModPage(dialog, instance, prepareModrinth(), new ModrinthAPI(), + ModFilterWidget::create(&static_cast(instance), true)); } -auto ModrinthResourcePackPage::shouldDisplay() const -> bool -{ - return true; -} -auto ModrinthTexturePackPage::shouldDisplay() const -> bool -{ - return true; -} -auto ModrinthShaderPackPage::shouldDisplay() const -> bool -{ - return true; -} -auto ModrinthDataPackPage::shouldDisplay() const -> bool -{ - return true; -} - -std::unique_ptr ModrinthModPage::createFilterWidget() -{ - return ModFilterWidget::create(&static_cast(m_baseInstance), true); -} - -void ModrinthModPage::prepareProviderCategories() -{ - auto [categoriesTask, response] = ModrinthAPI::getModCategories(); - m_categoriesTask = categoriesTask; - connect(m_categoriesTask.get(), &Task::succeeded, [this, response]() { - auto categories = ModrinthAPI::loadModCategories(*response); - m_filter_widget->setCategories(categories); - }); - m_categoriesTask->start(); -}; } // namespace ResourceDownload diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.h b/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.h index 3f41a3d5e..68fcbc8f5 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.h +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.h @@ -38,8 +38,6 @@ #pragma once -#include "modplatform/ResourceAPI.h" - #include "ui/pages/modplatform/DataPackPage.h" #include "ui/pages/modplatform/ModPage.h" #include "ui/pages/modplatform/ResourcePackPage.h" @@ -69,127 +67,12 @@ static inline QString metaEntryBase() { return "ModrinthPacks"; } + +ShaderPackResourcePage* createShaderPackResourcePage(ShaderPackDownloadDialog* dialog, BaseInstance& instance); +DataPackResourcePage* createDataPackResourcePage(DataPackDownloadDialog* dialog, BaseInstance& instance); +ResourcePackResourcePage* createResourcePackResourcePage(ResourcePackDownloadDialog* dialog, BaseInstance& instance); +TexturePackResourcePage* createTexturePackResourcePage(TexturePackDownloadDialog* dialog, BaseInstance& instance); +ModPage* createModPage(ModDownloadDialog* dialog, BaseInstance& instance); } // namespace Modrinth -class ModrinthModPage : public ModPage { - Q_OBJECT - - public: - static ModrinthModPage* create(ModDownloadDialog* dialog, BaseInstance& instance) - { - return ModPage::create(dialog, instance); - } - - ModrinthModPage(ModDownloadDialog* dialog, BaseInstance& instance); - ~ModrinthModPage() override = default; - - bool shouldDisplay() const override; - - inline auto displayName() const -> QString override { return Modrinth::displayName(); } - inline auto icon() const -> QIcon override { return Modrinth::icon(); } - inline auto id() const -> QString override { return Modrinth::id(); } - inline auto debugName() const -> QString override { return Modrinth::debugName(); } - inline auto metaEntryBase() const -> QString override { return Modrinth::metaEntryBase(); } - - inline auto helpPage() const -> QString override { return "Mod-platform"; } - - std::unique_ptr createFilterWidget() override; - - protected: - virtual void prepareProviderCategories() override; - Task::Ptr m_categoriesTask; -}; - -class ModrinthResourcePackPage : public ResourcePackResourcePage { - Q_OBJECT - - public: - static ModrinthResourcePackPage* create(ResourcePackDownloadDialog* dialog, BaseInstance& instance) - { - return ResourcePackResourcePage::create(dialog, instance); - } - - ModrinthResourcePackPage(ResourcePackDownloadDialog* dialog, BaseInstance& instance); - ~ModrinthResourcePackPage() override = default; - - bool shouldDisplay() const override; - - inline auto displayName() const -> QString override { return Modrinth::displayName(); } - inline auto icon() const -> QIcon override { return Modrinth::icon(); } - inline auto id() const -> QString override { return Modrinth::id(); } - inline auto debugName() const -> QString override { return Modrinth::debugName(); } - inline auto metaEntryBase() const -> QString override { return Modrinth::metaEntryBase(); } - - inline auto helpPage() const -> QString override { return ""; } -}; - -class ModrinthTexturePackPage : public TexturePackResourcePage { - Q_OBJECT - - public: - static ModrinthTexturePackPage* create(TexturePackDownloadDialog* dialog, BaseInstance& instance) - { - return TexturePackResourcePage::create(dialog, instance); - } - - ModrinthTexturePackPage(TexturePackDownloadDialog* dialog, BaseInstance& instance); - ~ModrinthTexturePackPage() override = default; - - bool shouldDisplay() const override; - - inline auto displayName() const -> QString override { return Modrinth::displayName(); } - inline auto icon() const -> QIcon override { return Modrinth::icon(); } - inline auto id() const -> QString override { return Modrinth::id(); } - inline auto debugName() const -> QString override { return Modrinth::debugName(); } - inline auto metaEntryBase() const -> QString override { return Modrinth::metaEntryBase(); } - - inline auto helpPage() const -> QString override { return ""; } -}; - -class ModrinthShaderPackPage : public ShaderPackResourcePage { - Q_OBJECT - - public: - static ModrinthShaderPackPage* create(ShaderPackDownloadDialog* dialog, BaseInstance& instance) - { - return ShaderPackResourcePage::create(dialog, instance); - } - - ModrinthShaderPackPage(ShaderPackDownloadDialog* dialog, BaseInstance& instance); - ~ModrinthShaderPackPage() override = default; - - bool shouldDisplay() const override; - - inline auto displayName() const -> QString override { return Modrinth::displayName(); } - inline auto icon() const -> QIcon override { return Modrinth::icon(); } - inline auto id() const -> QString override { return Modrinth::id(); } - inline auto debugName() const -> QString override { return Modrinth::debugName(); } - inline auto metaEntryBase() const -> QString override { return Modrinth::metaEntryBase(); } - - inline auto helpPage() const -> QString override { return ""; } -}; - -class ModrinthDataPackPage : public DataPackResourcePage { - Q_OBJECT - - public: - static ModrinthDataPackPage* create(DataPackDownloadDialog* dialog, BaseInstance& instance) - { - return DataPackResourcePage::create(dialog, instance); - } - - ModrinthDataPackPage(DataPackDownloadDialog* dialog, BaseInstance& instance); - ~ModrinthDataPackPage() override = default; - - bool shouldDisplay() const override; - - inline auto displayName() const -> QString override { return Modrinth::displayName(); } - inline auto icon() const -> QIcon override { return Modrinth::icon(); } - inline auto id() const -> QString override { return Modrinth::id(); } - inline auto debugName() const -> QString override { return Modrinth::debugName(); } - inline auto metaEntryBase() const -> QString override { return Modrinth::metaEntryBase(); } - - inline auto helpPage() const -> QString override { return ""; } -}; - } // namespace ResourceDownload diff --git a/launcher/ui/widgets/ModFilterWidget.cpp b/launcher/ui/widgets/ModFilterWidget.cpp index 6fab2b2a5..ea687d3e4 100644 --- a/launcher/ui/widgets/ModFilterWidget.cpp +++ b/launcher/ui/widgets/ModFilterWidget.cpp @@ -38,7 +38,6 @@ #include #include #include -#include #include "BaseVersionList.h" #include "Json.h" #include "Version.h" @@ -50,9 +49,9 @@ #include "Application.h" #include "minecraft/PackProfile.h" -std::unique_ptr ModFilterWidget::create(MinecraftInstance* instance, bool extended) +ModFilterWidget* ModFilterWidget::create(MinecraftInstance* instance, bool extended) { - return std::unique_ptr(new ModFilterWidget(instance, extended)); + return new ModFilterWidget(instance, extended); } class VersionBasicModel : public QIdentityProxyModel { diff --git a/launcher/ui/widgets/ModFilterWidget.h b/launcher/ui/widgets/ModFilterWidget.h index 85deb51dc..a4da07bba 100644 --- a/launcher/ui/widgets/ModFilterWidget.h +++ b/launcher/ui/widgets/ModFilterWidget.h @@ -91,7 +91,7 @@ class ModFilterWidget : public QTabWidget { } }; - static std::unique_ptr create(MinecraftInstance* instance, bool extended); + static ModFilterWidget* create(MinecraftInstance* instance, bool extended); virtual ~ModFilterWidget(); auto getFilter() -> std::shared_ptr;