From c3ea303a3742c886aae9e05d2e5f5fbb497260a1 Mon Sep 17 00:00:00 2001 From: flow Date: Fri, 16 Dec 2022 20:26:10 -0300 Subject: [PATCH 1/7] feat(RD): add resource pack downloader Signed-off-by: flow --- launcher/Application.cpp | 1 + launcher/CMakeLists.txt | 4 + launcher/modplatform/flame/FlameAPI.h | 2 + launcher/modplatform/modrinth/ModrinthAPI.h | 2 + .../ui/dialogs/ResourceDownloadDialog.cpp | 27 +++++ launcher/ui/dialogs/ResourceDownloadDialog.h | 20 ++++ .../ui/pages/instance/ResourcePackPage.cpp | 102 ++++++++++++++++++ launcher/ui/pages/instance/ResourcePackPage.h | 18 +--- .../pages/modplatform/ResourcePackModel.cpp | 42 ++++++++ .../ui/pages/modplatform/ResourcePackModel.h | 39 +++++++ .../ui/pages/modplatform/ResourcePackPage.cpp | 42 ++++++++ .../ui/pages/modplatform/ResourcePackPage.h | 48 +++++++++ .../modplatform/flame/FlameResourceModels.cpp | 24 +++++ .../modplatform/flame/FlameResourceModels.h | 19 ++++ .../modplatform/flame/FlameResourcePages.cpp | 57 ++++++++-- .../modplatform/flame/FlameResourcePages.h | 28 +++++ .../modrinth/ModrinthResourceModels.cpp | 22 ++++ .../modrinth/ModrinthResourceModels.h | 21 +++- .../modrinth/ModrinthResourcePages.cpp | 19 ++++ .../modrinth/ModrinthResourcePages.h | 24 +++++ 20 files changed, 538 insertions(+), 23 deletions(-) create mode 100644 launcher/ui/pages/instance/ResourcePackPage.cpp create mode 100644 launcher/ui/pages/modplatform/ResourcePackModel.cpp create mode 100644 launcher/ui/pages/modplatform/ResourcePackModel.h create mode 100644 launcher/ui/pages/modplatform/ResourcePackPage.cpp create mode 100644 launcher/ui/pages/modplatform/ResourcePackPage.h diff --git a/launcher/Application.cpp b/launcher/Application.cpp index 0d3b086f..c1ce4659 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -610,6 +610,7 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) m_settings->registerSetting("UpdateDialogGeometry", ""); m_settings->registerSetting("ModDownloadGeometry", ""); + m_settings->registerSetting("RPDownloadGeometry", ""); // HACK: This code feels so stupid is there a less stupid way of doing this? { diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index 1bfe9cbc..7ae148e0 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -721,6 +721,7 @@ SET(LAUNCHER_SOURCES ui/pages/instance/ManagedPackPage.h ui/pages/instance/TexturePackPage.h ui/pages/instance/ResourcePackPage.h + ui/pages/instance/ResourcePackPage.cpp ui/pages/instance/ShaderPackPage.h ui/pages/instance/ModFolderPage.cpp ui/pages/instance/ModFolderPage.h @@ -773,6 +774,9 @@ SET(LAUNCHER_SOURCES ui/pages/modplatform/ModModel.cpp ui/pages/modplatform/ModModel.h + ui/pages/modplatform/ResourcePackPage.cpp + ui/pages/modplatform/ResourcePackModel.cpp + ui/pages/modplatform/atlauncher/AtlFilterModel.cpp ui/pages/modplatform/atlauncher/AtlFilterModel.h ui/pages/modplatform/atlauncher/AtlListModel.cpp diff --git a/launcher/modplatform/flame/FlameAPI.h b/launcher/modplatform/flame/FlameAPI.h index 06d749e6..5811d717 100644 --- a/launcher/modplatform/flame/FlameAPI.h +++ b/launcher/modplatform/flame/FlameAPI.h @@ -27,6 +27,8 @@ class FlameAPI : public NetworkResourceAPI { default: case ModPlatform::ResourceType::MOD: return 6; + case ModPlatform::ResourceType::RESOURCE_PACK: + return 12; } } diff --git a/launcher/modplatform/modrinth/ModrinthAPI.h b/launcher/modplatform/modrinth/ModrinthAPI.h index dda27303..0b2d149e 100644 --- a/launcher/modplatform/modrinth/ModrinthAPI.h +++ b/launcher/modplatform/modrinth/ModrinthAPI.h @@ -68,6 +68,8 @@ class ModrinthAPI : public NetworkResourceAPI { switch (type) { case ModPlatform::ResourceType::MOD: return "mod"; + case ModPlatform::ResourceType::RESOURCE_PACK: + return "resourcepack"; default: qWarning() << "Invalid resource type for Modrinth API!"; break; diff --git a/launcher/ui/dialogs/ResourceDownloadDialog.cpp b/launcher/ui/dialogs/ResourceDownloadDialog.cpp index fa829bfb..edcd642e 100644 --- a/launcher/ui/dialogs/ResourceDownloadDialog.cpp +++ b/launcher/ui/dialogs/ResourceDownloadDialog.cpp @@ -25,6 +25,7 @@ #include "ResourceDownloadTask.h" #include "minecraft/mod/ModFolderModel.h" +#include "minecraft/mod/ResourcePackFolderModel.h" #include "ui/dialogs/ReviewMessageBox.h" @@ -229,4 +230,30 @@ QList ModDownloadDialog::getPages() return pages; } + +ResourcePackDownloadDialog::ResourcePackDownloadDialog(QWidget* parent, + const std::shared_ptr& resource_packs, + BaseInstance* instance) + : ResourceDownloadDialog(parent, resource_packs), m_instance(instance) +{ + setWindowTitle(dialogTitle()); + + initializeContainer(); + connectButtons(); + + if (!geometrySaveKey().isEmpty()) + restoreGeometry(QByteArray::fromBase64(APPLICATION->settings()->get(geometrySaveKey()).toByteArray())); +} + +QList ResourcePackDownloadDialog::getPages() +{ + QList pages; + + pages.append(ModrinthResourcePackPage::create(this, *m_instance)); + if (APPLICATION->capabilities() & Application::SupportsFlame) + pages.append(FlameResourcePackPage::create(this, *m_instance)); + + return pages; +} + } // namespace ResourceDownload diff --git a/launcher/ui/dialogs/ResourceDownloadDialog.h b/launcher/ui/dialogs/ResourceDownloadDialog.h index 19843532..f534cccc 100644 --- a/launcher/ui/dialogs/ResourceDownloadDialog.h +++ b/launcher/ui/dialogs/ResourceDownloadDialog.h @@ -35,6 +35,7 @@ class QVBoxLayout; class QDialogButtonBox; class ResourceDownloadTask; class ResourceFolderModel; +class ResourcePackFolderModel; namespace ResourceDownload { @@ -108,4 +109,23 @@ class ModDownloadDialog final : public ResourceDownloadDialog { BaseInstance* m_instance; }; +class ResourcePackDownloadDialog final : public ResourceDownloadDialog { + Q_OBJECT + + public: + explicit ResourcePackDownloadDialog(QWidget* parent, + const std::shared_ptr& resource_packs, + BaseInstance* instance); + ~ResourcePackDownloadDialog() override = default; + + //: String that gets appended to the resource pack download dialog title ("Download " + resourcesString()) + [[nodiscard]] QString resourcesString() const override { return tr("resource packs"); } + [[nodiscard]] QString geometrySaveKey() const override { return "RPDownloadGeometry"; } + + QList getPages() override; + + private: + BaseInstance* m_instance; +}; + } // namespace ResourceDownload diff --git a/launcher/ui/pages/instance/ResourcePackPage.cpp b/launcher/ui/pages/instance/ResourcePackPage.cpp new file mode 100644 index 00000000..e705f29e --- /dev/null +++ b/launcher/ui/pages/instance/ResourcePackPage.cpp @@ -0,0 +1,102 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * PolyMC - Minecraft Launcher + * Copyright (c) 2022 Jamie Mansfield + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Copyright 2013-2021 MultiMC Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ResourcePackPage.h" + +#include "ResourceDownloadTask.h" + +#include "ui/dialogs/CustomMessageBox.h" +#include "ui/dialogs/ProgressDialog.h" +#include "ui/dialogs/ResourceDownloadDialog.h" + +ResourcePackPage::ResourcePackPage(MinecraftInstance* instance, std::shared_ptr model, QWidget* parent) + : ExternalResourcesPage(instance, model, parent) +{ + ui->actionDownloadItem->setText(tr("Download RPs")); + ui->actionDownloadItem->setToolTip(tr("Download RPs from online platforms")); + ui->actionDownloadItem->setEnabled(true); + connect(ui->actionDownloadItem, &QAction::triggered, this, &ResourcePackPage::downloadRPs); + ui->actionsToolbar->insertActionBefore(ui->actionAddItem, ui->actionDownloadItem); + + ui->actionViewConfigs->setVisible(false); +} + +bool ResourcePackPage::onSelectionChanged(const QModelIndex& current, const QModelIndex& previous) +{ + auto sourceCurrent = m_filterModel->mapToSource(current); + int row = sourceCurrent.row(); + auto& rp = static_cast(m_model->at(row)); + ui->frame->updateWithResourcePack(rp); + + return true; +} + +void ResourcePackPage::downloadRPs() +{ + if (!m_controlsEnabled) + return; + if (m_instance->typeName() != "Minecraft") + return; // this is a null instance or a legacy instance + + ResourceDownload::ResourcePackDownloadDialog mdownload(this, std::static_pointer_cast(m_model), m_instance); + if (mdownload.exec()) { + auto tasks = new ConcurrentTask(this); + connect(tasks, &Task::failed, [this, tasks](QString reason) { + CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->show(); + tasks->deleteLater(); + }); + connect(tasks, &Task::aborted, [this, tasks]() { + CustomMessageBox::selectable(this, tr("Aborted"), tr("Download stopped by user."), QMessageBox::Information)->show(); + tasks->deleteLater(); + }); + connect(tasks, &Task::succeeded, [this, tasks]() { + QStringList warnings = tasks->warnings(); + if (warnings.count()) + CustomMessageBox::selectable(this, tr("Warnings"), warnings.join('\n'), QMessageBox::Warning)->show(); + + tasks->deleteLater(); + }); + + for (auto& task : mdownload.getTasks()) { + tasks->addTask(task); + } + + ProgressDialog loadDialog(this); + loadDialog.setSkipButton(true, tr("Abort")); + loadDialog.execWithTask(tasks); + + m_model->update(); + } +} diff --git a/launcher/ui/pages/instance/ResourcePackPage.h b/launcher/ui/pages/instance/ResourcePackPage.h index db8af0c5..fc05158c 100644 --- a/launcher/ui/pages/instance/ResourcePackPage.h +++ b/launcher/ui/pages/instance/ResourcePackPage.h @@ -44,12 +44,7 @@ class ResourcePackPage : public ExternalResourcesPage { Q_OBJECT public: - explicit ResourcePackPage(MinecraftInstance *instance, std::shared_ptr model, QWidget *parent = 0) - : ExternalResourcesPage(instance, model, parent) - { - ui->actionViewConfigs->setVisible(false); - } - virtual ~ResourcePackPage() {} + explicit ResourcePackPage(MinecraftInstance *instance, std::shared_ptr model, QWidget *parent = 0); QString displayName() const override { return tr("Resource packs"); } QIcon icon() const override { return APPLICATION->getThemedIcon("resourcepacks"); } @@ -63,14 +58,7 @@ public: } public slots: - bool onSelectionChanged(const QModelIndex& current, const QModelIndex& previous) override - { - auto sourceCurrent = m_filterModel->mapToSource(current); - int row = sourceCurrent.row(); - auto& rp = static_cast(m_model->at(row)); - ui->frame->updateWithResourcePack(rp); - - return true; - } + bool onSelectionChanged(const QModelIndex& current, const QModelIndex& previous) override; + void downloadRPs(); }; diff --git a/launcher/ui/pages/modplatform/ResourcePackModel.cpp b/launcher/ui/pages/modplatform/ResourcePackModel.cpp new file mode 100644 index 00000000..fd1afa0d --- /dev/null +++ b/launcher/ui/pages/modplatform/ResourcePackModel.cpp @@ -0,0 +1,42 @@ +#include "ResourcePackModel.h" + +#include + +namespace ResourceDownload { + +ResourcePackResourceModel::ResourcePackResourceModel(BaseInstance const& base_inst, ResourceAPI* api) + : ResourceModel(api), m_base_instance(base_inst){}; + +/******** Make data requests ********/ + +ResourceAPI::SearchArgs ResourcePackResourceModel::createSearchArguments() +{ + auto sort = getCurrentSortingMethodByIndex(); + return { ModPlatform::ResourceType::RESOURCE_PACK, m_next_search_offset, m_search_term, sort }; +} + +ResourceAPI::VersionSearchArgs ResourcePackResourceModel::createVersionsArguments(QModelIndex& entry) +{ + auto& pack = m_packs[entry.row()]; + return { pack }; +} + +ResourceAPI::ProjectInfoArgs ResourcePackResourceModel::createInfoArguments(QModelIndex& entry) +{ + auto& pack = m_packs[entry.row()]; + return { pack }; +} + +void ResourcePackResourceModel::searchWithTerm(const QString& term, unsigned int sort) +{ + if (m_search_term == term && m_search_term.isNull() == term.isNull() && m_current_sort_index == sort) { + return; + } + + setSearchTerm(term); + m_current_sort_index = sort; + + refresh(); +} + +} // namespace ResourceDownload diff --git a/launcher/ui/pages/modplatform/ResourcePackModel.h b/launcher/ui/pages/modplatform/ResourcePackModel.h new file mode 100644 index 00000000..63aa533c --- /dev/null +++ b/launcher/ui/pages/modplatform/ResourcePackModel.h @@ -0,0 +1,39 @@ +#pragma once + +#include + +#include "BaseInstance.h" + +#include "modplatform/ModIndex.h" + +#include "ui/pages/modplatform/ResourceModel.h" + +class Version; + +namespace ResourceDownload { + +class ResourcePackResourceModel : public ResourceModel { + Q_OBJECT + + public: + ResourcePackResourceModel(BaseInstance const&, ResourceAPI*); + + /* Ask the API for more information */ + void searchWithTerm(const QString& term, unsigned int sort); + + void loadIndexedPack(ModPlatform::IndexedPack&, QJsonObject&) override = 0; + void loadExtraPackInfo(ModPlatform::IndexedPack&, QJsonObject&) override = 0; + void loadIndexedPackVersions(ModPlatform::IndexedPack&, QJsonArray&) override = 0; + + public slots: + ResourceAPI::SearchArgs createSearchArguments() override; + ResourceAPI::VersionSearchArgs createVersionsArguments(QModelIndex&) override; + ResourceAPI::ProjectInfoArgs createInfoArguments(QModelIndex&) override; + + protected: + const BaseInstance& m_base_instance; + + auto documentToArray(QJsonDocument& obj) const -> QJsonArray override = 0; +}; + +} // namespace ResourceDownload diff --git a/launcher/ui/pages/modplatform/ResourcePackPage.cpp b/launcher/ui/pages/modplatform/ResourcePackPage.cpp new file mode 100644 index 00000000..8d663aa8 --- /dev/null +++ b/launcher/ui/pages/modplatform/ResourcePackPage.cpp @@ -0,0 +1,42 @@ +#include "ResourcePackPage.h" +#include "ui_ResourcePage.h" + +#include "ResourcePackModel.h" + +#include "ui/dialogs/ResourceDownloadDialog.h" + +#include + +namespace ResourceDownload { + +ResourcePackResourcePage::ResourcePackResourcePage(ResourcePackDownloadDialog* dialog, BaseInstance& instance) + : ResourcePage(dialog, instance) +{ + connect(m_ui->searchButton, &QPushButton::clicked, this, &ResourcePackResourcePage::triggerSearch); + connect(m_ui->packView, &QListView::doubleClicked, this, &ResourcePackResourcePage::onResourceSelected); +} + +/******** Callbacks to events in the UI (set up in the derived classes) ********/ + +void ResourcePackResourcePage::triggerSearch() +{ + 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_fetch_progress.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 new file mode 100644 index 00000000..2ecff390 --- /dev/null +++ b/launcher/ui/pages/modplatform/ResourcePackPage.h @@ -0,0 +1,48 @@ +#pragma once + +#include "ui/pages/modplatform/ResourcePage.h" +#include "ui/pages/modplatform/ResourcePackModel.h" + +namespace Ui { +class ResourcePage; +} + +namespace ResourceDownload { + +class ResourcePackDownloadDialog; + +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::updateVersionList); + connect(model, &ResourceModel::projectInfoUpdated, page, &ResourcePage::updateUi); + + return page; + } + + ~ResourcePackResourcePage() override = default; + + //: The plural version of 'resource pack' + [[nodiscard]] inline QString resourcesString() const override { return tr("resource packs"); } + //: The singular version of 'resource packs' + [[nodiscard]] inline QString resourceString() const override { return tr("resource pack"); } + + [[nodiscard]] bool supportsFiltering() const override { return false; }; + + [[nodiscard]] QMap urlHandlers() const override; + + protected: + ResourcePackResourcePage(ResourcePackDownloadDialog* dialog, BaseInstance& instance); + + protected slots: + void triggerSearch() override; +}; + +} // namespace ResourceDownload diff --git a/launcher/ui/pages/modplatform/flame/FlameResourceModels.cpp b/launcher/ui/pages/modplatform/flame/FlameResourceModels.cpp index de1f2122..95d915fc 100644 --- a/launcher/ui/pages/modplatform/flame/FlameResourceModels.cpp +++ b/launcher/ui/pages/modplatform/flame/FlameResourceModels.cpp @@ -34,4 +34,28 @@ auto FlameModModel::documentToArray(QJsonDocument& obj) const -> QJsonArray return Json::ensureArray(obj.object(), "data"); } +FlameResourcePackModel::FlameResourcePackModel(const BaseInstance& base) : ResourcePackResourceModel(base, new FlameAPI) {} + +void FlameResourcePackModel::loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) +{ + FlameMod::loadIndexedPack(m, obj); +} + +// We already deal with the URLs when initializing the pack, due to the API response's structure +void FlameResourcePackModel::loadExtraPackInfo(ModPlatform::IndexedPack& m, QJsonObject& obj) +{ + FlameMod::loadBody(m, obj); +} + +void FlameResourcePackModel::loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray& arr) +{ + FlameMod::loadIndexedPackVersions(m, arr, APPLICATION->network(), &m_base_instance); +} + +auto FlameResourcePackModel::documentToArray(QJsonDocument& obj) const -> QJsonArray +{ + return Json::ensureArray(obj.object(), "data"); +} + + } // namespace ResourceDownload diff --git a/launcher/ui/pages/modplatform/flame/FlameResourceModels.h b/launcher/ui/pages/modplatform/flame/FlameResourceModels.h index 625a2a7d..be214716 100644 --- a/launcher/ui/pages/modplatform/flame/FlameResourceModels.h +++ b/launcher/ui/pages/modplatform/flame/FlameResourceModels.h @@ -5,6 +5,7 @@ #pragma once #include "ui/pages/modplatform/ModModel.h" +#include "ui/pages/modplatform/ResourcePackModel.h" #include "ui/pages/modplatform/flame/FlameResourcePages.h" namespace ResourceDownload { @@ -27,4 +28,22 @@ class FlameModModel : public ModModel { auto documentToArray(QJsonDocument& obj) const -> QJsonArray override; }; +class FlameResourcePackModel : public ResourcePackResourceModel { + Q_OBJECT + + public: + FlameResourcePackModel(const BaseInstance&); + ~FlameResourcePackModel() override = default; + + private: + [[nodiscard]] QString debugName() const override { return Flame::debugName() + " (Model)"; } + [[nodiscard]] QString metaEntryBase() const override { return Flame::metaEntryBase(); } + + void loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) override; + void loadExtraPackInfo(ModPlatform::IndexedPack& m, QJsonObject& obj) override; + void loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray& arr) override; + + auto documentToArray(QJsonDocument& obj) const -> QJsonArray override; +}; + } // namespace ResourceDownload diff --git a/launcher/ui/pages/modplatform/flame/FlameResourcePages.cpp b/launcher/ui/pages/modplatform/flame/FlameResourcePages.cpp index 485431a7..15b04ab4 100644 --- a/launcher/ui/pages/modplatform/flame/FlameResourcePages.cpp +++ b/launcher/ui/pages/modplatform/flame/FlameResourcePages.cpp @@ -44,6 +44,11 @@ namespace ResourceDownload { +static bool isOptedOut(ModPlatform::IndexedVersion const& ver) +{ + return ver.downloadUrl.isEmpty(); +} + FlameModPage::FlameModPage(ModDownloadDialog* dialog, BaseInstance& instance) : ModPage(dialog, instance) { @@ -70,14 +75,9 @@ auto FlameModPage::validateVersion(ModPlatform::IndexedVersion& ver, QString min bool FlameModPage::optedOut(ModPlatform::IndexedVersion& ver) const { - return ver.downloadUrl.isEmpty(); + return isOptedOut(ver); } -// 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; } - void FlameModPage::openUrl(const QUrl& url) { if (url.scheme().isEmpty()) { @@ -94,4 +94,49 @@ void FlameModPage::openUrl(const QUrl& url) ModPage::openUrl(url); } +FlameResourcePackPage::FlameResourcePackPage(ResourcePackDownloadDialog* dialog, BaseInstance& instance) + : ResourcePackResourcePage(dialog, instance) +{ + m_model = new FlameResourcePackModel(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, SIGNAL(currentIndexChanged(int)), this, SLOT(triggerSearch())); + connect(m_ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &FlameResourcePackPage::onSelectionChanged); + connect(m_ui->versionSelectionBox, &QComboBox::currentTextChanged, this, &FlameResourcePackPage::onVersionSelectionChanged); + connect(m_ui->resourceSelectionButton, &QPushButton::clicked, this, &FlameResourcePackPage::onResourceSelected); + + m_ui->packDescription->setMetaEntry(metaEntryBase()); +} + +bool FlameResourcePackPage::optedOut(ModPlatform::IndexedVersion& ver) const +{ + return isOptedOut(ver); +} + +void FlameResourcePackPage::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); + ResourcePackResourcePage::openUrl({QUrl::fromPercentEncoding(query.toUtf8())}); // double decoding is necessary + return; + } + } + + ResourcePackResourcePage::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; } + } // namespace ResourceDownload diff --git a/launcher/ui/pages/modplatform/flame/FlameResourcePages.h b/launcher/ui/pages/modplatform/flame/FlameResourcePages.h index b21a53ad..03cf7795 100644 --- a/launcher/ui/pages/modplatform/flame/FlameResourcePages.h +++ b/launcher/ui/pages/modplatform/flame/FlameResourcePages.h @@ -43,6 +43,7 @@ #include "modplatform/ResourceAPI.h" #include "ui/pages/modplatform/ModPage.h" +#include "ui/pages/modplatform/ResourcePackPage.h" namespace ResourceDownload { @@ -82,4 +83,31 @@ class FlameModPage : public ModPage { void openUrl(const QUrl& url) override; }; +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; + + [[nodiscard]] bool shouldDisplay() const override; + + [[nodiscard]] inline auto displayName() const -> QString override { return Flame::displayName(); } + [[nodiscard]] inline auto icon() const -> QIcon override { return Flame::icon(); } + [[nodiscard]] inline auto id() const -> QString override { return Flame::id(); } + [[nodiscard]] inline auto debugName() const -> QString override { return Flame::debugName(); } + [[nodiscard]] inline auto metaEntryBase() const -> QString override { return Flame::metaEntryBase(); } + + [[nodiscard]] inline auto helpPage() const -> QString override { return ""; } + + bool optedOut(ModPlatform::IndexedVersion& ver) const override; + + void openUrl(const QUrl& url) override; +}; + } // namespace ResourceDownload diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.cpp b/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.cpp index 73d55133..b36339d7 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.cpp +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.cpp @@ -47,4 +47,26 @@ auto ModrinthModModel::documentToArray(QJsonDocument& obj) const -> QJsonArray return obj.object().value("hits").toArray(); } +ModrinthResourcePackModel::ModrinthResourcePackModel(const BaseInstance& base) : ResourcePackResourceModel(base, new ModrinthAPI){} + +void ModrinthResourcePackModel::loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) +{ + ::Modrinth::loadIndexedPack(m, obj); +} + +void ModrinthResourcePackModel::loadExtraPackInfo(ModPlatform::IndexedPack& m, QJsonObject& obj) +{ + ::Modrinth::loadExtraPackData(m, obj); +} + +void ModrinthResourcePackModel::loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray& arr) +{ + ::Modrinth::loadIndexedPackVersions(m, arr, APPLICATION->network(), &m_base_instance); +} + +auto ModrinthResourcePackModel::documentToArray(QJsonDocument& obj) const -> QJsonArray +{ + return obj.object().value("hits").toArray(); +} + } // namespace ResourceDownload diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.h b/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.h index 56cab146..0a91ef23 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.h +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.h @@ -21,12 +21,11 @@ #pragma once #include "ui/pages/modplatform/ModModel.h" +#include "ui/pages/modplatform/ResourcePackModel.h" #include "ui/pages/modplatform/modrinth/ModrinthResourcePages.h" namespace ResourceDownload { -class ModrinthModPage; - class ModrinthModModel : public ModModel { Q_OBJECT @@ -45,4 +44,22 @@ class ModrinthModModel : public ModModel { auto documentToArray(QJsonDocument& obj) const -> QJsonArray override; }; +class ModrinthResourcePackModel : public ResourcePackResourceModel { + Q_OBJECT + + public: + ModrinthResourcePackModel(const BaseInstance&); + ~ModrinthResourcePackModel() override = default; + + private: + [[nodiscard]] QString debugName() const override { return Modrinth::debugName() + " (Model)"; } + [[nodiscard]] QString metaEntryBase() const override { return Modrinth::metaEntryBase(); } + + void loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) override; + void loadExtraPackInfo(ModPlatform::IndexedPack& m, QJsonObject& obj) override; + void loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray& arr) override; + + auto documentToArray(QJsonDocument& obj) const -> QJsonArray override; +}; + } // namespace ResourceDownload diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.cpp b/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.cpp index b82f800e..d32b9091 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.cpp +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.cpp @@ -82,9 +82,28 @@ auto ModrinthModPage::validateVersion(ModPlatform::IndexedVersion& ver, QString return ver.mcVersion.contains(mineVer) && loaderCompatible; } +ModrinthResourcePackPage::ModrinthResourcePackPage(ResourcePackDownloadDialog* dialog, BaseInstance& instance) + : ResourcePackResourcePage(dialog, instance) +{ + m_model = new ModrinthResourcePackModel(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 constructor... + connect(m_ui->sortByBox, SIGNAL(currentIndexChanged(int)), this, SLOT(triggerSearch())); + connect(m_ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &ModrinthResourcePackPage::onSelectionChanged); + connect(m_ui->versionSelectionBox, &QComboBox::currentTextChanged, this, &ModrinthResourcePackPage::onVersionSelectionChanged); + connect(m_ui->resourceSelectionButton, &QPushButton::clicked, this, &ModrinthResourcePackPage::onResourceSelected); + + m_ui->packDescription->setMetaEntry(metaEntryBase()); +} + // 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 { return true; } +auto ModrinthResourcePackPage::shouldDisplay() const -> bool { return true; } } // namespace ResourceDownload diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.h b/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.h index be38eff1..be3740a1 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.h +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.h @@ -42,6 +42,7 @@ #include "modplatform/ResourceAPI.h" #include "ui/pages/modplatform/ModPage.h" +#include "ui/pages/modplatform/ResourcePackPage.h" namespace ResourceDownload { @@ -78,4 +79,27 @@ class ModrinthModPage : public ModPage { auto validateVersion(ModPlatform::IndexedVersion& ver, QString mineVer, std::optional loaders = {}) const -> bool override; }; +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; + + [[nodiscard]] bool shouldDisplay() const override; + + [[nodiscard]] inline auto displayName() const -> QString override { return Modrinth::displayName(); } + [[nodiscard]] inline auto icon() const -> QIcon override { return Modrinth::icon(); } + [[nodiscard]] inline auto id() const -> QString override { return Modrinth::id(); } + [[nodiscard]] inline auto debugName() const -> QString override { return Modrinth::debugName(); } + [[nodiscard]] inline auto metaEntryBase() const -> QString override { return Modrinth::metaEntryBase(); } + + [[nodiscard]] inline auto helpPage() const -> QString override { return ""; } +}; + } // namespace ResourceDownload From b724607e31d102c50cb42225b4a31f2932b2eb61 Mon Sep 17 00:00:00 2001 From: flow Date: Fri, 30 Dec 2022 14:06:07 -0300 Subject: [PATCH 2/7] feat(RD): add shader pack downloader Signed-off-by: flow --- launcher/Application.cpp | 1 + launcher/CMakeLists.txt | 4 + launcher/modplatform/ModIndex.h | 2 +- launcher/modplatform/modrinth/ModrinthAPI.h | 2 + launcher/ui/MainWindow.cpp | 1 + .../ui/dialogs/ResourceDownloadDialog.cpp | 25 +++++ launcher/ui/dialogs/ResourceDownloadDialog.h | 20 ++++ launcher/ui/pages/instance/ShaderPackPage.cpp | 96 +++++++++++++++++++ launcher/ui/pages/instance/ShaderPackPage.h | 19 ++-- .../ui/pages/modplatform/ShaderPackModel.cpp | 42 ++++++++ .../ui/pages/modplatform/ShaderPackModel.h | 39 ++++++++ .../ui/pages/modplatform/ShaderPackPage.cpp | 50 ++++++++++ .../ui/pages/modplatform/ShaderPackPage.h | 50 ++++++++++ .../modplatform/flame/FlameResourcePages.h | 1 + .../modrinth/ModrinthResourceModels.cpp | 22 +++++ .../modrinth/ModrinthResourceModels.h | 18 ++++ .../modrinth/ModrinthResourcePages.cpp | 19 ++++ .../modrinth/ModrinthResourcePages.h | 24 +++++ 18 files changed, 421 insertions(+), 14 deletions(-) create mode 100644 launcher/ui/pages/instance/ShaderPackPage.cpp create mode 100644 launcher/ui/pages/modplatform/ShaderPackModel.cpp create mode 100644 launcher/ui/pages/modplatform/ShaderPackModel.h create mode 100644 launcher/ui/pages/modplatform/ShaderPackPage.cpp create mode 100644 launcher/ui/pages/modplatform/ShaderPackPage.h diff --git a/launcher/Application.cpp b/launcher/Application.cpp index c1ce4659..0f7cce66 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -611,6 +611,7 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) m_settings->registerSetting("ModDownloadGeometry", ""); m_settings->registerSetting("RPDownloadGeometry", ""); + m_settings->registerSetting("ShaderDownloadGeometry", ""); // HACK: This code feels so stupid is there a less stupid way of doing this? { diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index 7ae148e0..795aeb9f 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -723,6 +723,7 @@ SET(LAUNCHER_SOURCES ui/pages/instance/ResourcePackPage.h ui/pages/instance/ResourcePackPage.cpp ui/pages/instance/ShaderPackPage.h + ui/pages/instance/ShaderPackPage.cpp ui/pages/instance/ModFolderPage.cpp ui/pages/instance/ModFolderPage.h ui/pages/instance/NotesPage.cpp @@ -777,6 +778,9 @@ SET(LAUNCHER_SOURCES ui/pages/modplatform/ResourcePackPage.cpp ui/pages/modplatform/ResourcePackModel.cpp + ui/pages/modplatform/ShaderPackPage.cpp + ui/pages/modplatform/ShaderPackModel.cpp + ui/pages/modplatform/atlauncher/AtlFilterModel.cpp ui/pages/modplatform/atlauncher/AtlFilterModel.h ui/pages/modplatform/atlauncher/AtlListModel.cpp diff --git a/launcher/modplatform/ModIndex.h b/launcher/modplatform/ModIndex.h index b1f8050d..40f1efc4 100644 --- a/launcher/modplatform/ModIndex.h +++ b/launcher/modplatform/ModIndex.h @@ -30,7 +30,7 @@ namespace ModPlatform { enum class ResourceProvider { MODRINTH, FLAME }; -enum class ResourceType { MOD, RESOURCE_PACK }; +enum class ResourceType { MOD, RESOURCE_PACK, SHADER_PACK }; class ProviderCapabilities { public: diff --git a/launcher/modplatform/modrinth/ModrinthAPI.h b/launcher/modplatform/modrinth/ModrinthAPI.h index 0b2d149e..b91ac5c1 100644 --- a/launcher/modplatform/modrinth/ModrinthAPI.h +++ b/launcher/modplatform/modrinth/ModrinthAPI.h @@ -70,6 +70,8 @@ class ModrinthAPI : public NetworkResourceAPI { return "mod"; case ModPlatform::ResourceType::RESOURCE_PACK: return "resourcepack"; + case ModPlatform::ResourceType::SHADER_PACK: + return "shader"; default: qWarning() << "Invalid resource type for Modrinth API!"; break; diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp index 6d21f5ed..8490b292 100644 --- a/launcher/ui/MainWindow.cpp +++ b/launcher/ui/MainWindow.cpp @@ -113,6 +113,7 @@ #include "minecraft/mod/tasks/LocalResourceParse.h" #include "minecraft/mod/ModFolderModel.h" +#include "minecraft/mod/ShaderPackFolderModel.h" #include "minecraft/WorldList.h" #include "KonamiCode.h" diff --git a/launcher/ui/dialogs/ResourceDownloadDialog.cpp b/launcher/ui/dialogs/ResourceDownloadDialog.cpp index edcd642e..98a2eb88 100644 --- a/launcher/ui/dialogs/ResourceDownloadDialog.cpp +++ b/launcher/ui/dialogs/ResourceDownloadDialog.cpp @@ -26,6 +26,7 @@ #include "minecraft/mod/ModFolderModel.h" #include "minecraft/mod/ResourcePackFolderModel.h" +#include "minecraft/mod/ShaderPackFolderModel.h" #include "ui/dialogs/ReviewMessageBox.h" @@ -256,4 +257,28 @@ QList ResourcePackDownloadDialog::getPages() return pages; } + +ShaderPackDownloadDialog::ShaderPackDownloadDialog(QWidget* parent, + const std::shared_ptr& shaders, + BaseInstance* instance) + : ResourceDownloadDialog(parent, shaders), m_instance(instance) +{ + setWindowTitle(dialogTitle()); + + initializeContainer(); + connectButtons(); + + if (!geometrySaveKey().isEmpty()) + restoreGeometry(QByteArray::fromBase64(APPLICATION->settings()->get(geometrySaveKey()).toByteArray())); +} + +QList ShaderPackDownloadDialog::getPages() +{ + QList pages; + + pages.append(ModrinthShaderPackPage::create(this, *m_instance)); + + return pages; +} + } // namespace ResourceDownload diff --git a/launcher/ui/dialogs/ResourceDownloadDialog.h b/launcher/ui/dialogs/ResourceDownloadDialog.h index f534cccc..203bac66 100644 --- a/launcher/ui/dialogs/ResourceDownloadDialog.h +++ b/launcher/ui/dialogs/ResourceDownloadDialog.h @@ -36,6 +36,7 @@ class QDialogButtonBox; class ResourceDownloadTask; class ResourceFolderModel; class ResourcePackFolderModel; +class ShaderPackFolderModel; namespace ResourceDownload { @@ -128,4 +129,23 @@ class ResourcePackDownloadDialog final : public ResourceDownloadDialog { BaseInstance* m_instance; }; +class ShaderPackDownloadDialog final : public ResourceDownloadDialog { + Q_OBJECT + + public: + explicit ShaderPackDownloadDialog(QWidget* parent, + const std::shared_ptr& shader_packs, + BaseInstance* instance); + ~ShaderPackDownloadDialog() override = default; + + //: String that gets appended to the shader pack download dialog title ("Download " + resourcesString()) + [[nodiscard]] QString resourcesString() const override { return tr("shader packs"); } + [[nodiscard]] QString geometrySaveKey() const override { return "ShaderDownloadGeometry"; } + + QList getPages() override; + + private: + BaseInstance* m_instance; +}; + } // namespace ResourceDownload diff --git a/launcher/ui/pages/instance/ShaderPackPage.cpp b/launcher/ui/pages/instance/ShaderPackPage.cpp new file mode 100644 index 00000000..2dde4dc7 --- /dev/null +++ b/launcher/ui/pages/instance/ShaderPackPage.cpp @@ -0,0 +1,96 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * PolyMC - Minecraft Launcher + * Copyright (c) 2022 Jamie Mansfield + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Copyright 2013-2021 MultiMC Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ShaderPackPage.h" +#include "ui_ExternalResourcesPage.h" + +#include "ResourceDownloadTask.h" + +#include "minecraft/mod/ShaderPackFolderModel.h" + +#include "ui/dialogs/CustomMessageBox.h" +#include "ui/dialogs/ProgressDialog.h" +#include "ui/dialogs/ResourceDownloadDialog.h" + + +ShaderPackPage::ShaderPackPage(MinecraftInstance* instance, std::shared_ptr model, QWidget* parent) + : ExternalResourcesPage(instance, model, parent) +{ + ui->actionDownloadItem->setText(tr("Download shaders")); + ui->actionDownloadItem->setToolTip(tr("Download shaders from online platforms")); + ui->actionDownloadItem->setEnabled(true); + connect(ui->actionDownloadItem, &QAction::triggered, this, &ShaderPackPage::downloadShaders); + ui->actionsToolbar->insertActionBefore(ui->actionAddItem, ui->actionDownloadItem); + + ui->actionViewConfigs->setVisible(false); +} + +void ShaderPackPage::downloadShaders() +{ + if (!m_controlsEnabled) + return; + if (m_instance->typeName() != "Minecraft") + return; // this is a null instance or a legacy instance + + ResourceDownload::ShaderPackDownloadDialog mdownload(this, std::static_pointer_cast(m_model), m_instance); + if (mdownload.exec()) { + auto tasks = new ConcurrentTask(this); + connect(tasks, &Task::failed, [this, tasks](QString reason) { + CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->show(); + tasks->deleteLater(); + }); + connect(tasks, &Task::aborted, [this, tasks]() { + CustomMessageBox::selectable(this, tr("Aborted"), tr("Download stopped by user."), QMessageBox::Information)->show(); + tasks->deleteLater(); + }); + connect(tasks, &Task::succeeded, [this, tasks]() { + QStringList warnings = tasks->warnings(); + if (warnings.count()) + CustomMessageBox::selectable(this, tr("Warnings"), warnings.join('\n'), QMessageBox::Warning)->show(); + + tasks->deleteLater(); + }); + + for (auto& task : mdownload.getTasks()) { + tasks->addTask(task); + } + + ProgressDialog loadDialog(this); + loadDialog.setSkipButton(true, tr("Abort")); + loadDialog.execWithTask(tasks); + + m_model->update(); + } +} diff --git a/launcher/ui/pages/instance/ShaderPackPage.h b/launcher/ui/pages/instance/ShaderPackPage.h index 7f7ff8c1..09895949 100644 --- a/launcher/ui/pages/instance/ShaderPackPage.h +++ b/launcher/ui/pages/instance/ShaderPackPage.h @@ -36,28 +36,21 @@ #pragma once #include "ExternalResourcesPage.h" -#include "ui_ExternalResourcesPage.h" - -#include "minecraft/mod/ShaderPackFolderModel.h" class ShaderPackPage : public ExternalResourcesPage { Q_OBJECT public: - explicit ShaderPackPage(MinecraftInstance *instance, std::shared_ptr model, QWidget *parent = 0) - : ExternalResourcesPage(instance, model, parent) - { - ui->actionViewConfigs->setVisible(false); - } - virtual ~ShaderPackPage() {} + explicit ShaderPackPage(MinecraftInstance *instance, std::shared_ptr model, QWidget *parent = nullptr); + ~ShaderPackPage() override = default; QString displayName() const override { return tr("Shader packs"); } QIcon icon() const override { return APPLICATION->getThemedIcon("shaderpacks"); } QString id() const override { return "shaderpacks"; } QString helpPage() const override { return "Resource-packs"; } - virtual bool shouldDisplay() const override - { - return true; - } + bool shouldDisplay() const override { return true; } + + public slots: + void downloadShaders(); }; diff --git a/launcher/ui/pages/modplatform/ShaderPackModel.cpp b/launcher/ui/pages/modplatform/ShaderPackModel.cpp new file mode 100644 index 00000000..36993288 --- /dev/null +++ b/launcher/ui/pages/modplatform/ShaderPackModel.cpp @@ -0,0 +1,42 @@ +#include "ShaderPackModel.h" + +#include + +namespace ResourceDownload { + +ShaderPackResourceModel::ShaderPackResourceModel(BaseInstance const& base_inst, ResourceAPI* api) + : ResourceModel(api), m_base_instance(base_inst){}; + +/******** Make data requests ********/ + +ResourceAPI::SearchArgs ShaderPackResourceModel::createSearchArguments() +{ + auto sort = getCurrentSortingMethodByIndex(); + return { ModPlatform::ResourceType::SHADER_PACK, m_next_search_offset, m_search_term, sort }; +} + +ResourceAPI::VersionSearchArgs ShaderPackResourceModel::createVersionsArguments(QModelIndex& entry) +{ + auto& pack = m_packs[entry.row()]; + return { pack }; +} + +ResourceAPI::ProjectInfoArgs ShaderPackResourceModel::createInfoArguments(QModelIndex& entry) +{ + auto& pack = m_packs[entry.row()]; + return { pack }; +} + +void ShaderPackResourceModel::searchWithTerm(const QString& term, unsigned int sort) +{ + if (m_search_term == term && m_search_term.isNull() == term.isNull() && m_current_sort_index == sort) { + return; + } + + setSearchTerm(term); + m_current_sort_index = sort; + + refresh(); +} + +} // namespace ResourceDownload diff --git a/launcher/ui/pages/modplatform/ShaderPackModel.h b/launcher/ui/pages/modplatform/ShaderPackModel.h new file mode 100644 index 00000000..c84df15a --- /dev/null +++ b/launcher/ui/pages/modplatform/ShaderPackModel.h @@ -0,0 +1,39 @@ +#pragma once + +#include + +#include "BaseInstance.h" + +#include "modplatform/ModIndex.h" + +#include "ui/pages/modplatform/ResourceModel.h" + +class Version; + +namespace ResourceDownload { + +class ShaderPackResourceModel : public ResourceModel { + Q_OBJECT + + public: + ShaderPackResourceModel(BaseInstance const&, ResourceAPI*); + + /* Ask the API for more information */ + void searchWithTerm(const QString& term, unsigned int sort); + + void loadIndexedPack(ModPlatform::IndexedPack&, QJsonObject&) override = 0; + void loadExtraPackInfo(ModPlatform::IndexedPack&, QJsonObject&) override = 0; + void loadIndexedPackVersions(ModPlatform::IndexedPack&, QJsonArray&) override = 0; + + public slots: + ResourceAPI::SearchArgs createSearchArguments() override; + ResourceAPI::VersionSearchArgs createVersionsArguments(QModelIndex&) override; + ResourceAPI::ProjectInfoArgs createInfoArguments(QModelIndex&) override; + + protected: + const BaseInstance& m_base_instance; + + auto documentToArray(QJsonDocument& obj) const -> QJsonArray override = 0; +}; + +} // namespace ResourceDownload diff --git a/launcher/ui/pages/modplatform/ShaderPackPage.cpp b/launcher/ui/pages/modplatform/ShaderPackPage.cpp new file mode 100644 index 00000000..364d0a54 --- /dev/null +++ b/launcher/ui/pages/modplatform/ShaderPackPage.cpp @@ -0,0 +1,50 @@ +#include "ShaderPackPage.h" +#include "ui_ResourcePage.h" + +#include "ShaderPackModel.h" + +#include "ui/dialogs/ResourceDownloadDialog.h" + +#include + +namespace ResourceDownload { + +ShaderPackResourcePage::ShaderPackResourcePage(ShaderPackDownloadDialog* dialog, BaseInstance& instance) + : ResourcePage(dialog, instance) +{ + connect(m_ui->searchButton, &QPushButton::clicked, this, &ShaderPackResourcePage::triggerSearch); + connect(m_ui->packView, &QListView::doubleClicked, this, &ShaderPackResourcePage::onResourceSelected); +} + +/******** Callbacks to events in the UI (set up in the derived classes) ********/ + +void ShaderPackResourcePage::triggerSearch() +{ + 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_fetch_progress.watch(m_model->activeSearchJob().get()); +} + +QMap ShaderPackResourcePage::urlHandlers() const +{ + QMap map; + map.insert(QRegularExpression::anchoredPattern("(?:www\\.)?modrinth\\.com\\/shaders\\/([^\\/]+)\\/?"), "modrinth"); + map.insert(QRegularExpression::anchoredPattern("(?:www\\.)?curseforge\\.com\\/minecraft\\/customization\\/([^\\/]+)\\/?"), "curseforge"); + map.insert(QRegularExpression::anchoredPattern("minecraft\\.curseforge\\.com\\/projects\\/([^\\/]+)\\/?"), "curseforge"); + return map; +} + +void ShaderPackResourcePage::addResourceToDialog(ModPlatform::IndexedPack& pack, ModPlatform::IndexedVersion& version) +{ + if (version.loaders.contains(QStringLiteral("canvas"))) + version.custom_target_folder = QStringLiteral("resourcepacks"); + + m_parent_dialog->addResource(pack, version); +} + +} // namespace ResourceDownload diff --git a/launcher/ui/pages/modplatform/ShaderPackPage.h b/launcher/ui/pages/modplatform/ShaderPackPage.h new file mode 100644 index 00000000..92a9c3ee --- /dev/null +++ b/launcher/ui/pages/modplatform/ShaderPackPage.h @@ -0,0 +1,50 @@ +#pragma once + +#include "ui/pages/modplatform/ResourcePage.h" +#include "ui/pages/modplatform/ShaderPackModel.h" + +namespace Ui { +class ResourcePage; +} + +namespace ResourceDownload { + +class ShaderPackDownloadDialog; + +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::updateVersionList); + connect(model, &ResourceModel::projectInfoUpdated, page, &ResourcePage::updateUi); + + return page; + } + + ~ShaderPackResourcePage() override = default; + + //: The plural version of 'shader pack' + [[nodiscard]] inline QString resourcesString() const override { return tr("shader packs"); } + //: The singular version of 'shader packs' + [[nodiscard]] inline QString resourceString() const override { return tr("shader pack"); } + + [[nodiscard]] bool supportsFiltering() const override { return false; }; + + void addResourceToDialog(ModPlatform::IndexedPack&, ModPlatform::IndexedVersion&) override; + + [[nodiscard]] QMap urlHandlers() const override; + + protected: + ShaderPackResourcePage(ShaderPackDownloadDialog* dialog, BaseInstance& instance); + + protected slots: + void triggerSearch() override; +}; + +} // namespace ResourceDownload diff --git a/launcher/ui/pages/modplatform/flame/FlameResourcePages.h b/launcher/ui/pages/modplatform/flame/FlameResourcePages.h index 03cf7795..4507a32a 100644 --- a/launcher/ui/pages/modplatform/flame/FlameResourcePages.h +++ b/launcher/ui/pages/modplatform/flame/FlameResourcePages.h @@ -44,6 +44,7 @@ #include "ui/pages/modplatform/ModPage.h" #include "ui/pages/modplatform/ResourcePackPage.h" +#include "ui/pages/modplatform/ShaderPackPage.h" namespace ResourceDownload { diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.cpp b/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.cpp index b36339d7..bd433121 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.cpp +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.cpp @@ -69,4 +69,26 @@ auto ModrinthResourcePackModel::documentToArray(QJsonDocument& obj) const -> QJs return obj.object().value("hits").toArray(); } +ModrinthShaderPackModel::ModrinthShaderPackModel(const BaseInstance& base) : ShaderPackResourceModel(base, new ModrinthAPI){} + +void ModrinthShaderPackModel::loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) +{ + ::Modrinth::loadIndexedPack(m, obj); +} + +void ModrinthShaderPackModel::loadExtraPackInfo(ModPlatform::IndexedPack& m, QJsonObject& obj) +{ + ::Modrinth::loadExtraPackData(m, obj); +} + +void ModrinthShaderPackModel::loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray& arr) +{ + ::Modrinth::loadIndexedPackVersions(m, arr, APPLICATION->network(), &m_base_instance); +} + +auto ModrinthShaderPackModel::documentToArray(QJsonDocument& obj) const -> QJsonArray +{ + return obj.object().value("hits").toArray(); +} + } // namespace ResourceDownload diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.h b/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.h index 0a91ef23..80a48089 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.h +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.h @@ -62,4 +62,22 @@ class ModrinthResourcePackModel : public ResourcePackResourceModel { auto documentToArray(QJsonDocument& obj) const -> QJsonArray override; }; +class ModrinthShaderPackModel : public ShaderPackResourceModel { + Q_OBJECT + + public: + ModrinthShaderPackModel(const BaseInstance&); + ~ModrinthShaderPackModel() override = default; + + private: + [[nodiscard]] QString debugName() const override { return Modrinth::debugName() + " (Model)"; } + [[nodiscard]] QString metaEntryBase() const override { return Modrinth::metaEntryBase(); } + + void loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) override; + void loadExtraPackInfo(ModPlatform::IndexedPack& m, QJsonObject& obj) override; + void loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray& arr) override; + + auto documentToArray(QJsonDocument& obj) const -> QJsonArray override; +}; + } // namespace ResourceDownload diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.cpp b/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.cpp index d32b9091..2826b5d3 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.cpp +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.cpp @@ -100,10 +100,29 @@ ModrinthResourcePackPage::ModrinthResourcePackPage(ResourcePackDownloadDialog* d m_ui->packDescription->setMetaEntry(metaEntryBase()); } +ModrinthShaderPackPage::ModrinthShaderPackPage(ShaderPackDownloadDialog* dialog, BaseInstance& instance) + : ShaderPackResourcePage(dialog, instance) +{ + m_model = new ModrinthShaderPackModel(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 constructor... + connect(m_ui->sortByBox, SIGNAL(currentIndexChanged(int)), this, SLOT(triggerSearch())); + connect(m_ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &ModrinthShaderPackPage::onSelectionChanged); + connect(m_ui->versionSelectionBox, &QComboBox::currentTextChanged, this, &ModrinthShaderPackPage::onVersionSelectionChanged); + connect(m_ui->resourceSelectionButton, &QPushButton::clicked, this, &ModrinthShaderPackPage::onResourceSelected); + + m_ui->packDescription->setMetaEntry(metaEntryBase()); +} + // 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 { return true; } auto ModrinthResourcePackPage::shouldDisplay() const -> bool { return true; } +auto ModrinthShaderPackPage::shouldDisplay() const -> bool { return true; } } // namespace ResourceDownload diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.h b/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.h index be3740a1..8733a1b2 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.h +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.h @@ -43,6 +43,7 @@ #include "ui/pages/modplatform/ModPage.h" #include "ui/pages/modplatform/ResourcePackPage.h" +#include "ui/pages/modplatform/ShaderPackPage.h" namespace ResourceDownload { @@ -102,4 +103,27 @@ class ModrinthResourcePackPage : public ResourcePackResourcePage { [[nodiscard]] 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; + + [[nodiscard]] bool shouldDisplay() const override; + + [[nodiscard]] inline auto displayName() const -> QString override { return Modrinth::displayName(); } + [[nodiscard]] inline auto icon() const -> QIcon override { return Modrinth::icon(); } + [[nodiscard]] inline auto id() const -> QString override { return Modrinth::id(); } + [[nodiscard]] inline auto debugName() const -> QString override { return Modrinth::debugName(); } + [[nodiscard]] inline auto metaEntryBase() const -> QString override { return Modrinth::metaEntryBase(); } + + [[nodiscard]] inline auto helpPage() const -> QString override { return ""; } +}; + } // namespace ResourceDownload From ada5e88eb933a41691121316c78cd2e564965fa0 Mon Sep 17 00:00:00 2001 From: flow Date: Sun, 29 Jan 2023 18:07:49 -0300 Subject: [PATCH 3/7] feat(RD): add texture pack downloader This extends the resource pack downloader, with the custom behavior of filtering the versions that shows up, to those <= 1.6. As always, Flame is funky and requires a bit more workarounds than average. This will also get a nice improvement when the Version parsing and comparison PR gets merged! :D Signed-off-by: flow --- launcher/Application.cpp | 1 + launcher/CMakeLists.txt | 5 + launcher/meta/Version.cpp | 5 + launcher/meta/Version.h | 3 + .../ui/dialogs/ResourceDownloadDialog.cpp | 27 +++++ launcher/ui/dialogs/ResourceDownloadDialog.h | 20 ++++ .../ui/pages/instance/TexturePackPage.cpp | 104 ++++++++++++++++++ launcher/ui/pages/instance/TexturePackPage.h | 19 +--- launcher/ui/pages/modplatform/ResourceModel.h | 2 +- .../ui/pages/modplatform/ResourcePackPage.cpp | 2 +- .../ui/pages/modplatform/ResourcePackPage.h | 2 +- .../ui/pages/modplatform/TexturePackModel.cpp | 80 ++++++++++++++ .../ui/pages/modplatform/TexturePackModel.h | 23 ++++ .../ui/pages/modplatform/TexturePackPage.h | 46 ++++++++ .../modplatform/flame/FlameResourceModels.cpp | 58 ++++++++++ .../modplatform/flame/FlameResourceModels.h | 21 ++++ .../modplatform/flame/FlameResourcePages.cpp | 40 +++++++ .../modplatform/flame/FlameResourcePages.h | 29 ++++- .../modrinth/ModrinthResourceModels.cpp | 22 ++++ .../modrinth/ModrinthResourceModels.h | 18 +++ .../modrinth/ModrinthResourcePages.cpp | 19 ++++ .../modrinth/ModrinthResourcePages.h | 24 ++++ 22 files changed, 550 insertions(+), 20 deletions(-) create mode 100644 launcher/ui/pages/instance/TexturePackPage.cpp create mode 100644 launcher/ui/pages/modplatform/TexturePackModel.cpp create mode 100644 launcher/ui/pages/modplatform/TexturePackModel.h create mode 100644 launcher/ui/pages/modplatform/TexturePackPage.h diff --git a/launcher/Application.cpp b/launcher/Application.cpp index 0f7cce66..2956d798 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -611,6 +611,7 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) m_settings->registerSetting("ModDownloadGeometry", ""); m_settings->registerSetting("RPDownloadGeometry", ""); + m_settings->registerSetting("TPDownloadGeometry", ""); m_settings->registerSetting("ShaderDownloadGeometry", ""); // HACK: This code feels so stupid is there a less stupid way of doing this? diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index 795aeb9f..202e633c 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -720,6 +720,7 @@ SET(LAUNCHER_SOURCES ui/pages/instance/ManagedPackPage.cpp ui/pages/instance/ManagedPackPage.h ui/pages/instance/TexturePackPage.h + ui/pages/instance/TexturePackPage.cpp ui/pages/instance/ResourcePackPage.h ui/pages/instance/ResourcePackPage.cpp ui/pages/instance/ShaderPackPage.h @@ -778,6 +779,10 @@ SET(LAUNCHER_SOURCES ui/pages/modplatform/ResourcePackPage.cpp ui/pages/modplatform/ResourcePackModel.cpp + # Needed for MOC to find them without a corresponding .cpp + ui/pages/modplatform/TexturePackPage.h + ui/pages/modplatform/TexturePackModel.cpp + ui/pages/modplatform/ShaderPackPage.cpp ui/pages/modplatform/ShaderPackModel.cpp diff --git a/launcher/meta/Version.cpp b/launcher/meta/Version.cpp index 68cfa55c..e617abf8 100644 --- a/launcher/meta/Version.cpp +++ b/launcher/meta/Version.cpp @@ -99,6 +99,11 @@ QString Meta::Version::localFilename() const return m_uid + '/' + m_version + ".json"; } +::Version Meta::Version::toComparableVersion() const +{ + return { const_cast(this)->descriptor() }; +} + void Meta::Version::setType(const QString &type) { m_type = type; diff --git a/launcher/meta/Version.h b/launcher/meta/Version.h index 7228fa36..78156193 100644 --- a/launcher/meta/Version.h +++ b/launcher/meta/Version.h @@ -16,6 +16,7 @@ #pragma once #include "BaseVersion.h" +#include "../Version.h" #include #include @@ -85,6 +86,8 @@ public: QString localFilename() const override; + [[nodiscard]] ::Version toComparableVersion() const; + public: // for usage by format parsers only void setType(const QString &type); void setTime(const qint64 time); diff --git a/launcher/ui/dialogs/ResourceDownloadDialog.cpp b/launcher/ui/dialogs/ResourceDownloadDialog.cpp index 98a2eb88..edb7d063 100644 --- a/launcher/ui/dialogs/ResourceDownloadDialog.cpp +++ b/launcher/ui/dialogs/ResourceDownloadDialog.cpp @@ -26,6 +26,7 @@ #include "minecraft/mod/ModFolderModel.h" #include "minecraft/mod/ResourcePackFolderModel.h" +#include "minecraft/mod/TexturePackFolderModel.h" #include "minecraft/mod/ShaderPackFolderModel.h" #include "ui/dialogs/ReviewMessageBox.h" @@ -258,6 +259,32 @@ QList ResourcePackDownloadDialog::getPages() } +TexturePackDownloadDialog::TexturePackDownloadDialog(QWidget* parent, + const std::shared_ptr& resource_packs, + BaseInstance* instance) + : ResourceDownloadDialog(parent, resource_packs), m_instance(instance) +{ + setWindowTitle(dialogTitle()); + + initializeContainer(); + connectButtons(); + + if (!geometrySaveKey().isEmpty()) + restoreGeometry(QByteArray::fromBase64(APPLICATION->settings()->get(geometrySaveKey()).toByteArray())); +} + +QList TexturePackDownloadDialog::getPages() +{ + QList pages; + + pages.append(ModrinthTexturePackPage::create(this, *m_instance)); + if (APPLICATION->capabilities() & Application::SupportsFlame) + pages.append(FlameTexturePackPage::create(this, *m_instance)); + + return pages; +} + + ShaderPackDownloadDialog::ShaderPackDownloadDialog(QWidget* parent, const std::shared_ptr& shaders, BaseInstance* instance) diff --git a/launcher/ui/dialogs/ResourceDownloadDialog.h b/launcher/ui/dialogs/ResourceDownloadDialog.h index 203bac66..5678dc8b 100644 --- a/launcher/ui/dialogs/ResourceDownloadDialog.h +++ b/launcher/ui/dialogs/ResourceDownloadDialog.h @@ -36,6 +36,7 @@ class QDialogButtonBox; class ResourceDownloadTask; class ResourceFolderModel; class ResourcePackFolderModel; +class TexturePackFolderModel; class ShaderPackFolderModel; namespace ResourceDownload { @@ -129,6 +130,25 @@ class ResourcePackDownloadDialog final : public ResourceDownloadDialog { BaseInstance* m_instance; }; +class TexturePackDownloadDialog final : public ResourceDownloadDialog { + Q_OBJECT + + public: + explicit TexturePackDownloadDialog(QWidget* parent, + const std::shared_ptr& resource_packs, + BaseInstance* instance); + ~TexturePackDownloadDialog() override = default; + + //: String that gets appended to the texture pack download dialog title ("Download " + resourcesString()) + [[nodiscard]] QString resourcesString() const override { return tr("texture packs"); } + [[nodiscard]] QString geometrySaveKey() const override { return "TPDownloadGeometry"; } + + QList getPages() override; + + private: + BaseInstance* m_instance; +}; + class ShaderPackDownloadDialog final : public ResourceDownloadDialog { Q_OBJECT diff --git a/launcher/ui/pages/instance/TexturePackPage.cpp b/launcher/ui/pages/instance/TexturePackPage.cpp new file mode 100644 index 00000000..5b68c102 --- /dev/null +++ b/launcher/ui/pages/instance/TexturePackPage.cpp @@ -0,0 +1,104 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * PolyMC - Minecraft Launcher + * Copyright (c) 2022 Jamie Mansfield + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Copyright 2013-2021 MultiMC Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "TexturePackPage.h" + +#include "ResourceDownloadTask.h" + +#include "minecraft/mod/TexturePack.h" + +#include "ui/dialogs/CustomMessageBox.h" +#include "ui/dialogs/ProgressDialog.h" +#include "ui/dialogs/ResourceDownloadDialog.h" + +TexturePackPage::TexturePackPage(MinecraftInstance* instance, std::shared_ptr model, QWidget* parent) + : ExternalResourcesPage(instance, model, parent) +{ + ui->actionDownloadItem->setText(tr("Download TPs")); + ui->actionDownloadItem->setToolTip(tr("Download TPs from online platforms")); + ui->actionDownloadItem->setEnabled(true); + connect(ui->actionDownloadItem, &QAction::triggered, this, &TexturePackPage::downloadTPs); + ui->actionsToolbar->insertActionBefore(ui->actionAddItem, ui->actionDownloadItem); + + ui->actionViewConfigs->setVisible(false); +} + +bool TexturePackPage::onSelectionChanged(const QModelIndex& current, const QModelIndex& previous) +{ + auto sourceCurrent = m_filterModel->mapToSource(current); + int row = sourceCurrent.row(); + auto& rp = static_cast(m_model->at(row)); + ui->frame->updateWithTexturePack(rp); + + return true; +} + +void TexturePackPage::downloadTPs() +{ + if (!m_controlsEnabled) + return; + if (m_instance->typeName() != "Minecraft") + return; // this is a null instance or a legacy instance + + ResourceDownload::TexturePackDownloadDialog mdownload(this, std::static_pointer_cast(m_model), m_instance); + if (mdownload.exec()) { + auto tasks = new ConcurrentTask(this); + connect(tasks, &Task::failed, [this, tasks](QString reason) { + CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->show(); + tasks->deleteLater(); + }); + connect(tasks, &Task::aborted, [this, tasks]() { + CustomMessageBox::selectable(this, tr("Aborted"), tr("Download stopped by user."), QMessageBox::Information)->show(); + tasks->deleteLater(); + }); + connect(tasks, &Task::succeeded, [this, tasks]() { + QStringList warnings = tasks->warnings(); + if (warnings.count()) + CustomMessageBox::selectable(this, tr("Warnings"), warnings.join('\n'), QMessageBox::Warning)->show(); + + tasks->deleteLater(); + }); + + for (auto& task : mdownload.getTasks()) { + tasks->addTask(task); + } + + ProgressDialog loadDialog(this); + loadDialog.setSkipButton(true, tr("Abort")); + loadDialog.execWithTask(tasks); + + m_model->update(); + } +} diff --git a/launcher/ui/pages/instance/TexturePackPage.h b/launcher/ui/pages/instance/TexturePackPage.h index 69b836ca..5712f7d6 100644 --- a/launcher/ui/pages/instance/TexturePackPage.h +++ b/launcher/ui/pages/instance/TexturePackPage.h @@ -39,18 +39,12 @@ #include "ui_ExternalResourcesPage.h" #include "minecraft/mod/TexturePackFolderModel.h" -#include "minecraft/mod/TexturePack.h" class TexturePackPage : public ExternalResourcesPage { Q_OBJECT public: - explicit TexturePackPage(MinecraftInstance *instance, std::shared_ptr model, QWidget *parent = 0) - : ExternalResourcesPage(instance, model, parent) - { - ui->actionViewConfigs->setVisible(false); - } - virtual ~TexturePackPage() {} + explicit TexturePackPage(MinecraftInstance *instance, std::shared_ptr model, QWidget* parent = nullptr); QString displayName() const override { return tr("Texture packs"); } QIcon icon() const override { return APPLICATION->getThemedIcon("resourcepacks"); } @@ -63,13 +57,6 @@ public: } public slots: - bool onSelectionChanged(const QModelIndex& current, const QModelIndex& previous) override - { - auto sourceCurrent = m_filterModel->mapToSource(current); - int row = sourceCurrent.row(); - auto& rp = static_cast(m_model->at(row)); - ui->frame->updateWithTexturePack(rp); - - return true; - } + bool onSelectionChanged(const QModelIndex& current, const QModelIndex& previous) override; + void downloadTPs(); }; diff --git a/launcher/ui/pages/modplatform/ResourceModel.h b/launcher/ui/pages/modplatform/ResourceModel.h index 610b631c..46a02d6e 100644 --- a/launcher/ui/pages/modplatform/ResourceModel.h +++ b/launcher/ui/pages/modplatform/ResourceModel.h @@ -98,7 +98,7 @@ class ResourceModel : public QAbstractListModel { /** Functions to load data into a pack. * - * Those are needed for the same reason as ddocumentToArray, and NEED to be re-implemented in the same way. + * Those are needed for the same reason as documentToArray, and NEED to be re-implemented in the same way. */ virtual void loadIndexedPack(ModPlatform::IndexedPack&, QJsonObject&); diff --git a/launcher/ui/pages/modplatform/ResourcePackPage.cpp b/launcher/ui/pages/modplatform/ResourcePackPage.cpp index 8d663aa8..c2de9e3b 100644 --- a/launcher/ui/pages/modplatform/ResourcePackPage.cpp +++ b/launcher/ui/pages/modplatform/ResourcePackPage.cpp @@ -9,7 +9,7 @@ namespace ResourceDownload { -ResourcePackResourcePage::ResourcePackResourcePage(ResourcePackDownloadDialog* dialog, BaseInstance& instance) +ResourcePackResourcePage::ResourcePackResourcePage(ResourceDownloadDialog* dialog, BaseInstance& instance) : ResourcePage(dialog, instance) { connect(m_ui->searchButton, &QPushButton::clicked, this, &ResourcePackResourcePage::triggerSearch); diff --git a/launcher/ui/pages/modplatform/ResourcePackPage.h b/launcher/ui/pages/modplatform/ResourcePackPage.h index 2ecff390..97780047 100644 --- a/launcher/ui/pages/modplatform/ResourcePackPage.h +++ b/launcher/ui/pages/modplatform/ResourcePackPage.h @@ -39,7 +39,7 @@ class ResourcePackResourcePage : public ResourcePage { [[nodiscard]] QMap urlHandlers() const override; protected: - ResourcePackResourcePage(ResourcePackDownloadDialog* dialog, BaseInstance& instance); + ResourcePackResourcePage(ResourceDownloadDialog* dialog, BaseInstance& instance); protected slots: void triggerSearch() override; diff --git a/launcher/ui/pages/modplatform/TexturePackModel.cpp b/launcher/ui/pages/modplatform/TexturePackModel.cpp new file mode 100644 index 00000000..076a200d --- /dev/null +++ b/launcher/ui/pages/modplatform/TexturePackModel.cpp @@ -0,0 +1,80 @@ +#include "TexturePackModel.h" + +#include "Application.h" + +#include "meta/Index.h" +#include "meta/Version.h" + +static std::list s_availableVersions = {}; + +namespace ResourceDownload { +TexturePackResourceModel::TexturePackResourceModel(BaseInstance const& inst, ResourceAPI* api) + : ResourcePackResourceModel(inst, api), m_version_list(APPLICATION->metadataIndex()->get("net.minecraft")) +{ + if (!m_version_list->isLoaded()) { + qDebug() << "Loading version list..."; + auto task = m_version_list->getLoadTask(); + if (!task->isRunning()) + task->start(); + } +} + +void waitOnVersionListLoad(Meta::VersionList::Ptr version_list) +{ + QEventLoop load_version_list_loop; + + QTimer time_limit_for_list_load; + time_limit_for_list_load.setTimerType(Qt::TimerType::CoarseTimer); + time_limit_for_list_load.setSingleShot(true); + time_limit_for_list_load.callOnTimeout(&load_version_list_loop, &QEventLoop::quit); + time_limit_for_list_load.start(4000); + + auto task = version_list->getLoadTask(); + QObject::connect(task.get(), &Task::finished, &load_version_list_loop, &QEventLoop::quit); + + load_version_list_loop.exec(); + if (time_limit_for_list_load.isActive()) + time_limit_for_list_load.stop(); +} + +ResourceAPI::SearchArgs TexturePackResourceModel::createSearchArguments() +{ + if (s_availableVersions.empty()) + waitOnVersionListLoad(m_version_list); + + auto args = ResourcePackResourceModel::createSearchArguments(); + + if (!m_version_list->isLoaded()) { + qCritical() << "The version list could not be loaded. Falling back to showing all entries."; + return args; + } + + if (s_availableVersions.empty()) { + for (auto&& version : m_version_list->versions()) { + // FIXME: This duplicates the logic in meta for the 'texturepacks' trait. However, we don't have access to that + // information from the index file alone. Also, downloading every version's file isn't a very good idea. + if (auto ver = version->toComparableVersion(); ver <= maximumTexturePackVersion()) + s_availableVersions.push_back(ver); + } + } + + Q_ASSERT(!s_availableVersions.empty()); + + args.versions = s_availableVersions; + + return args; +} + +ResourceAPI::VersionSearchArgs TexturePackResourceModel::createVersionsArguments(QModelIndex& entry) +{ + auto args = ResourcePackResourceModel::createVersionsArguments(entry); + if (!m_version_list->isLoaded()) { + qCritical() << "The version list could not be loaded. Falling back to showing all entries."; + return args; + } + + args.mcVersions = s_availableVersions; + return args; +} + +} // namespace ResourceDownload diff --git a/launcher/ui/pages/modplatform/TexturePackModel.h b/launcher/ui/pages/modplatform/TexturePackModel.h new file mode 100644 index 00000000..0ae5bdd4 --- /dev/null +++ b/launcher/ui/pages/modplatform/TexturePackModel.h @@ -0,0 +1,23 @@ +#pragma once + +#include "meta/VersionList.h" +#include "ui/pages/modplatform/ResourcePackModel.h" + +namespace ResourceDownload { + +class TexturePackResourceModel : public ResourcePackResourceModel { + Q_OBJECT + + public: + TexturePackResourceModel(BaseInstance const& inst, ResourceAPI* api); + + [[nodiscard]] inline ::Version maximumTexturePackVersion() const { return { "1.6" }; } + + ResourceAPI::SearchArgs createSearchArguments() override; + ResourceAPI::VersionSearchArgs createVersionsArguments(QModelIndex&) override; + + protected: + Meta::VersionList::Ptr m_version_list; +}; + +} // namespace ResourceDownload diff --git a/launcher/ui/pages/modplatform/TexturePackPage.h b/launcher/ui/pages/modplatform/TexturePackPage.h new file mode 100644 index 00000000..3466d3ea --- /dev/null +++ b/launcher/ui/pages/modplatform/TexturePackPage.h @@ -0,0 +1,46 @@ +#pragma once + +#include "ui_ResourcePage.h" +#include "ui/dialogs/ResourceDownloadDialog.h" +#include "ui/pages/modplatform/ResourcePackPage.h" +#include "ui/pages/modplatform/TexturePackModel.h" + +namespace Ui { +class ResourcePage; +} + +namespace ResourceDownload { + +class TexturePackDownloadDialog; + +class TexturePackResourcePage : public ResourcePackResourcePage { + Q_OBJECT + + public: + template + static T* create(TexturePackDownloadDialog* dialog, BaseInstance& instance) + { + auto page = new T(dialog, instance); + auto model = static_cast(page->getModel()); + + connect(model, &ResourceModel::versionListUpdated, page, &ResourcePage::updateVersionList); + connect(model, &ResourceModel::projectInfoUpdated, page, &ResourcePage::updateUi); + + return page; + } + + //: The plural version of 'texture pack' + [[nodiscard]] inline QString resourcesString() const override { return tr("texture packs"); } + //: The singular version of 'texture packs' + [[nodiscard]] inline QString resourceString() const override { return tr("texture pack"); } + + protected: + TexturePackResourcePage(TexturePackDownloadDialog* dialog, BaseInstance& instance) + : ResourcePackResourcePage(dialog, instance) + { + connect(m_ui->searchButton, &QPushButton::clicked, this, &TexturePackResourcePage::triggerSearch); + connect(m_ui->packView, &QListView::doubleClicked, this, &TexturePackResourcePage::onResourceSelected); + } +}; + +} // namespace ResourceDownload diff --git a/launcher/ui/pages/modplatform/flame/FlameResourceModels.cpp b/launcher/ui/pages/modplatform/flame/FlameResourceModels.cpp index 95d915fc..e3d0bc14 100644 --- a/launcher/ui/pages/modplatform/flame/FlameResourceModels.cpp +++ b/launcher/ui/pages/modplatform/flame/FlameResourceModels.cpp @@ -57,5 +57,63 @@ auto FlameResourcePackModel::documentToArray(QJsonDocument& obj) const -> QJsonA return Json::ensureArray(obj.object(), "data"); } +FlameTexturePackModel::FlameTexturePackModel(const BaseInstance& base) : TexturePackResourceModel(base, new FlameAPI) {} + +void FlameTexturePackModel::loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) +{ + FlameMod::loadIndexedPack(m, obj); +} + +// We already deal with the URLs when initializing the pack, due to the API response's structure +void FlameTexturePackModel::loadExtraPackInfo(ModPlatform::IndexedPack& m, QJsonObject& obj) +{ + FlameMod::loadBody(m, obj); +} + +void FlameTexturePackModel::loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray& arr) +{ + FlameMod::loadIndexedPackVersions(m, arr, APPLICATION->network(), &m_base_instance); + + QVector filtered_versions(m.versions.size()); + + // FIXME: Client-side version filtering. This won't take into account any user-selected filtering. + for (auto const& version : m.versions) { + auto const& mc_versions = version.mcVersion; + + if (std::any_of(mc_versions.constBegin(), mc_versions.constEnd(), + [this](auto const& mc_version){ return Version(mc_version) <= maximumTexturePackVersion(); })) + filtered_versions.push_back(version); + } + + m.versions = filtered_versions; +} + +ResourceAPI::SearchArgs FlameTexturePackModel::createSearchArguments() +{ + auto args = TexturePackResourceModel::createSearchArguments(); + + auto profile = static_cast(m_base_instance).getPackProfile(); + QString instance_minecraft_version = profile->getComponentVersion("net.minecraft"); + + // Bypass the texture pack logic, because we can't do multiple versions in the API query + args.versions = { instance_minecraft_version }; + + return args; +} + +ResourceAPI::VersionSearchArgs FlameTexturePackModel::createVersionsArguments(QModelIndex& entry) +{ + auto args = TexturePackResourceModel::createVersionsArguments(entry); + + // Bypass the texture pack logic, because we can't do multiple versions in the API query + args.mcVersions = {}; + + return args; +} + +auto FlameTexturePackModel::documentToArray(QJsonDocument& obj) const -> QJsonArray +{ + return Json::ensureArray(obj.object(), "data"); +} } // namespace ResourceDownload diff --git a/launcher/ui/pages/modplatform/flame/FlameResourceModels.h b/launcher/ui/pages/modplatform/flame/FlameResourceModels.h index be214716..0252ac40 100644 --- a/launcher/ui/pages/modplatform/flame/FlameResourceModels.h +++ b/launcher/ui/pages/modplatform/flame/FlameResourceModels.h @@ -46,4 +46,25 @@ class FlameResourcePackModel : public ResourcePackResourceModel { auto documentToArray(QJsonDocument& obj) const -> QJsonArray override; }; +class FlameTexturePackModel : public TexturePackResourceModel { + Q_OBJECT + + public: + FlameTexturePackModel(const BaseInstance&); + ~FlameTexturePackModel() override = default; + + private: + [[nodiscard]] QString debugName() const override { return Flame::debugName() + " (Model)"; } + [[nodiscard]] QString metaEntryBase() const override { return Flame::metaEntryBase(); } + + void loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) override; + void loadExtraPackInfo(ModPlatform::IndexedPack& m, QJsonObject& obj) override; + void loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray& arr) override; + + ResourceAPI::SearchArgs createSearchArguments() override; + ResourceAPI::VersionSearchArgs createVersionsArguments(QModelIndex&) override; + + auto documentToArray(QJsonDocument& obj) const -> QJsonArray override; +}; + } // namespace ResourceDownload diff --git a/launcher/ui/pages/modplatform/flame/FlameResourcePages.cpp b/launcher/ui/pages/modplatform/flame/FlameResourcePages.cpp index 15b04ab4..f93e27e6 100644 --- a/launcher/ui/pages/modplatform/flame/FlameResourcePages.cpp +++ b/launcher/ui/pages/modplatform/flame/FlameResourcePages.cpp @@ -133,10 +133,50 @@ void FlameResourcePackPage::openUrl(const QUrl& url) ResourcePackResourcePage::openUrl(url); } +FlameTexturePackPage::FlameTexturePackPage(TexturePackDownloadDialog* dialog, BaseInstance& instance) + : TexturePackResourcePage(dialog, 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, SIGNAL(currentIndexChanged(int)), this, SLOT(triggerSearch())); + connect(m_ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &FlameTexturePackPage::onSelectionChanged); + connect(m_ui->versionSelectionBox, &QComboBox::currentTextChanged, this, &FlameTexturePackPage::onVersionSelectionChanged); + connect(m_ui->resourceSelectionButton, &QPushButton::clicked, this, &FlameTexturePackPage::onResourceSelected); + + m_ui->packDescription->setMetaEntry(metaEntryBase()); +} + +bool FlameTexturePackPage::optedOut(ModPlatform::IndexedVersion& ver) const +{ + return isOptedOut(ver); +} + +void FlameTexturePackPage::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); + ResourcePackResourcePage::openUrl({QUrl::fromPercentEncoding(query.toUtf8())}); // double decoding is necessary + return; + } + } + + TexturePackResourcePage::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; } } // namespace ResourceDownload diff --git a/launcher/ui/pages/modplatform/flame/FlameResourcePages.h b/launcher/ui/pages/modplatform/flame/FlameResourcePages.h index 4507a32a..103a6bb9 100644 --- a/launcher/ui/pages/modplatform/flame/FlameResourcePages.h +++ b/launcher/ui/pages/modplatform/flame/FlameResourcePages.h @@ -44,7 +44,7 @@ #include "ui/pages/modplatform/ModPage.h" #include "ui/pages/modplatform/ResourcePackPage.h" -#include "ui/pages/modplatform/ShaderPackPage.h" +#include "ui/pages/modplatform/TexturePackPage.h" namespace ResourceDownload { @@ -111,4 +111,31 @@ class FlameResourcePackPage : public ResourcePackResourcePage { 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; + + [[nodiscard]] bool shouldDisplay() const override; + + [[nodiscard]] inline auto displayName() const -> QString override { return Flame::displayName(); } + [[nodiscard]] inline auto icon() const -> QIcon override { return Flame::icon(); } + [[nodiscard]] inline auto id() const -> QString override { return Flame::id(); } + [[nodiscard]] inline auto debugName() const -> QString override { return Flame::debugName(); } + [[nodiscard]] inline auto metaEntryBase() const -> QString override { return Flame::metaEntryBase(); } + + [[nodiscard]] inline auto helpPage() const -> QString override { return ""; } + + bool optedOut(ModPlatform::IndexedVersion& ver) const override; + + void openUrl(const QUrl& url) override; +}; + } // namespace ResourceDownload diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.cpp b/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.cpp index bd433121..f5d1cc28 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.cpp +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.cpp @@ -69,6 +69,28 @@ auto ModrinthResourcePackModel::documentToArray(QJsonDocument& obj) const -> QJs return obj.object().value("hits").toArray(); } +ModrinthTexturePackModel::ModrinthTexturePackModel(const BaseInstance& base) : TexturePackResourceModel(base, new ModrinthAPI){} + +void ModrinthTexturePackModel::loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) +{ + ::Modrinth::loadIndexedPack(m, obj); +} + +void ModrinthTexturePackModel::loadExtraPackInfo(ModPlatform::IndexedPack& m, QJsonObject& obj) +{ + ::Modrinth::loadExtraPackData(m, obj); +} + +void ModrinthTexturePackModel::loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray& arr) +{ + ::Modrinth::loadIndexedPackVersions(m, arr, APPLICATION->network(), &m_base_instance); +} + +auto ModrinthTexturePackModel::documentToArray(QJsonDocument& obj) const -> QJsonArray +{ + return obj.object().value("hits").toArray(); +} + ModrinthShaderPackModel::ModrinthShaderPackModel(const BaseInstance& base) : ShaderPackResourceModel(base, new ModrinthAPI){} void ModrinthShaderPackModel::loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.h b/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.h index 80a48089..b351b19b 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.h +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.h @@ -62,6 +62,24 @@ class ModrinthResourcePackModel : public ResourcePackResourceModel { auto documentToArray(QJsonDocument& obj) const -> QJsonArray override; }; +class ModrinthTexturePackModel : public TexturePackResourceModel { + Q_OBJECT + + public: + ModrinthTexturePackModel(const BaseInstance&); + ~ModrinthTexturePackModel() override = default; + + private: + [[nodiscard]] QString debugName() const override { return Modrinth::debugName() + " (Model)"; } + [[nodiscard]] QString metaEntryBase() const override { return Modrinth::metaEntryBase(); } + + void loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) override; + void loadExtraPackInfo(ModPlatform::IndexedPack& m, QJsonObject& obj) override; + void loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray& arr) override; + + auto documentToArray(QJsonDocument& obj) const -> QJsonArray override; +}; + class ModrinthShaderPackModel : public ShaderPackResourceModel { Q_OBJECT diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.cpp b/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.cpp index 2826b5d3..dd143700 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.cpp +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.cpp @@ -100,6 +100,24 @@ ModrinthResourcePackPage::ModrinthResourcePackPage(ResourcePackDownloadDialog* d m_ui->packDescription->setMetaEntry(metaEntryBase()); } +ModrinthTexturePackPage::ModrinthTexturePackPage(TexturePackDownloadDialog* dialog, BaseInstance& instance) + : TexturePackResourcePage(dialog, instance) +{ + m_model = new ModrinthTexturePackModel(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 constructor... + connect(m_ui->sortByBox, SIGNAL(currentIndexChanged(int)), this, SLOT(triggerSearch())); + connect(m_ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &ModrinthTexturePackPage::onSelectionChanged); + connect(m_ui->versionSelectionBox, &QComboBox::currentTextChanged, this, &ModrinthTexturePackPage::onVersionSelectionChanged); + connect(m_ui->resourceSelectionButton, &QPushButton::clicked, this, &ModrinthTexturePackPage::onResourceSelected); + + m_ui->packDescription->setMetaEntry(metaEntryBase()); +} + ModrinthShaderPackPage::ModrinthShaderPackPage(ShaderPackDownloadDialog* dialog, BaseInstance& instance) : ShaderPackResourcePage(dialog, instance) { @@ -123,6 +141,7 @@ ModrinthShaderPackPage::ModrinthShaderPackPage(ShaderPackDownloadDialog* dialog, // my Qt, so we need to implement this in every derived class... auto ModrinthModPage::shouldDisplay() const -> bool { return true; } auto ModrinthResourcePackPage::shouldDisplay() const -> bool { return true; } +auto ModrinthTexturePackPage::shouldDisplay() const -> bool { return true; } auto ModrinthShaderPackPage::shouldDisplay() const -> bool { return true; } } // namespace ResourceDownload diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.h b/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.h index 8733a1b2..f4eb5ce0 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.h +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.h @@ -43,6 +43,7 @@ #include "ui/pages/modplatform/ModPage.h" #include "ui/pages/modplatform/ResourcePackPage.h" +#include "ui/pages/modplatform/TexturePackPage.h" #include "ui/pages/modplatform/ShaderPackPage.h" namespace ResourceDownload { @@ -103,6 +104,29 @@ class ModrinthResourcePackPage : public ResourcePackResourcePage { [[nodiscard]] 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; + + [[nodiscard]] bool shouldDisplay() const override; + + [[nodiscard]] inline auto displayName() const -> QString override { return Modrinth::displayName(); } + [[nodiscard]] inline auto icon() const -> QIcon override { return Modrinth::icon(); } + [[nodiscard]] inline auto id() const -> QString override { return Modrinth::id(); } + [[nodiscard]] inline auto debugName() const -> QString override { return Modrinth::debugName(); } + [[nodiscard]] inline auto metaEntryBase() const -> QString override { return Modrinth::metaEntryBase(); } + + [[nodiscard]] inline auto helpPage() const -> QString override { return ""; } +}; + class ModrinthShaderPackPage : public ShaderPackResourcePage { Q_OBJECT From 46c6cc2d2b59ee3c81abe690218d8f60e6e02c76 Mon Sep 17 00:00:00 2001 From: flow Date: Sun, 29 Jan 2023 20:40:55 -0300 Subject: [PATCH 4/7] chore: add my copyright headers .-. Signed-off-by: flow --- launcher/ui/pages/instance/ResourcePackPage.cpp | 6 ++++-- launcher/ui/pages/instance/ResourcePackPage.h | 6 ++++-- launcher/ui/pages/instance/ShaderPackPage.cpp | 6 ++++-- launcher/ui/pages/instance/ShaderPackPage.h | 6 ++++-- launcher/ui/pages/instance/TexturePackPage.cpp | 6 ++++-- launcher/ui/pages/instance/TexturePackPage.h | 6 ++++-- launcher/ui/pages/modplatform/ResourcePackModel.cpp | 4 ++++ launcher/ui/pages/modplatform/ResourcePackModel.h | 4 ++++ launcher/ui/pages/modplatform/ResourcePackPage.cpp | 4 ++++ launcher/ui/pages/modplatform/ResourcePackPage.h | 4 ++++ launcher/ui/pages/modplatform/ShaderPackModel.cpp | 4 ++++ launcher/ui/pages/modplatform/ShaderPackModel.h | 4 ++++ launcher/ui/pages/modplatform/ShaderPackPage.cpp | 4 ++++ launcher/ui/pages/modplatform/ShaderPackPage.h | 4 ++++ launcher/ui/pages/modplatform/TexturePackModel.cpp | 4 ++++ launcher/ui/pages/modplatform/TexturePackModel.h | 4 ++++ launcher/ui/pages/modplatform/TexturePackPage.h | 4 ++++ 17 files changed, 68 insertions(+), 12 deletions(-) diff --git a/launcher/ui/pages/instance/ResourcePackPage.cpp b/launcher/ui/pages/instance/ResourcePackPage.cpp index e705f29e..f46a7939 100644 --- a/launcher/ui/pages/instance/ResourcePackPage.cpp +++ b/launcher/ui/pages/instance/ResourcePackPage.cpp @@ -1,6 +1,8 @@ -// SPDX-License-Identifier: GPL-3.0-only +// SPDX-FileCopyrightText: 2023 flowln +// +// SPDX-License-Identifier: GPL-3.0-only AND Apache-2.0 /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 Jamie Mansfield * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/ui/pages/instance/ResourcePackPage.h b/launcher/ui/pages/instance/ResourcePackPage.h index fc05158c..b04aa2e9 100644 --- a/launcher/ui/pages/instance/ResourcePackPage.h +++ b/launcher/ui/pages/instance/ResourcePackPage.h @@ -1,6 +1,8 @@ -// SPDX-License-Identifier: GPL-3.0-only +// SPDX-FileCopyrightText: 2023 flowln +// +// SPDX-License-Identifier: GPL-3.0-only AND Apache-2.0 /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 Jamie Mansfield * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/ui/pages/instance/ShaderPackPage.cpp b/launcher/ui/pages/instance/ShaderPackPage.cpp index 2dde4dc7..2d0c10aa 100644 --- a/launcher/ui/pages/instance/ShaderPackPage.cpp +++ b/launcher/ui/pages/instance/ShaderPackPage.cpp @@ -1,6 +1,8 @@ -// SPDX-License-Identifier: GPL-3.0-only +// SPDX-FileCopyrightText: 2023 flowln +// +// SPDX-License-Identifier: GPL-3.0-only AND Apache-2.0 /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 Jamie Mansfield * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/ui/pages/instance/ShaderPackPage.h b/launcher/ui/pages/instance/ShaderPackPage.h index 09895949..a779fd8c 100644 --- a/launcher/ui/pages/instance/ShaderPackPage.h +++ b/launcher/ui/pages/instance/ShaderPackPage.h @@ -1,6 +1,8 @@ -// SPDX-License-Identifier: GPL-3.0-only +// SPDX-FileCopyrightText: 2023 flowln +// +// SPDX-License-Identifier: GPL-3.0-only AND Apache-2.0 /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 Jamie Mansfield * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/ui/pages/instance/TexturePackPage.cpp b/launcher/ui/pages/instance/TexturePackPage.cpp index 5b68c102..76fc04e7 100644 --- a/launcher/ui/pages/instance/TexturePackPage.cpp +++ b/launcher/ui/pages/instance/TexturePackPage.cpp @@ -1,6 +1,8 @@ -// SPDX-License-Identifier: GPL-3.0-only +// SPDX-FileCopyrightText: 2023 flowln +// +// SPDX-License-Identifier: GPL-3.0-only AND Apache-2.0 /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 Jamie Mansfield * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/ui/pages/instance/TexturePackPage.h b/launcher/ui/pages/instance/TexturePackPage.h index 5712f7d6..47a8fa60 100644 --- a/launcher/ui/pages/instance/TexturePackPage.h +++ b/launcher/ui/pages/instance/TexturePackPage.h @@ -1,6 +1,8 @@ -// SPDX-License-Identifier: GPL-3.0-only +// SPDX-FileCopyrightText: 2023 flowln +// +// SPDX-License-Identifier: GPL-3.0-only AND Apache-2.0 /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 Jamie Mansfield * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/ui/pages/modplatform/ResourcePackModel.cpp b/launcher/ui/pages/modplatform/ResourcePackModel.cpp index fd1afa0d..3df9a787 100644 --- a/launcher/ui/pages/modplatform/ResourcePackModel.cpp +++ b/launcher/ui/pages/modplatform/ResourcePackModel.cpp @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2023 flowln +// +// SPDX-License-Identifier: GPL-3.0-only + #include "ResourcePackModel.h" #include diff --git a/launcher/ui/pages/modplatform/ResourcePackModel.h b/launcher/ui/pages/modplatform/ResourcePackModel.h index 63aa533c..e2b4a195 100644 --- a/launcher/ui/pages/modplatform/ResourcePackModel.h +++ b/launcher/ui/pages/modplatform/ResourcePackModel.h @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2023 flowln +// +// SPDX-License-Identifier: GPL-3.0-only + #pragma once #include diff --git a/launcher/ui/pages/modplatform/ResourcePackPage.cpp b/launcher/ui/pages/modplatform/ResourcePackPage.cpp index c2de9e3b..52fb4802 100644 --- a/launcher/ui/pages/modplatform/ResourcePackPage.cpp +++ b/launcher/ui/pages/modplatform/ResourcePackPage.cpp @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2023 flowln +// +// SPDX-License-Identifier: GPL-3.0-only + #include "ResourcePackPage.h" #include "ui_ResourcePage.h" diff --git a/launcher/ui/pages/modplatform/ResourcePackPage.h b/launcher/ui/pages/modplatform/ResourcePackPage.h index 97780047..c01c89c4 100644 --- a/launcher/ui/pages/modplatform/ResourcePackPage.h +++ b/launcher/ui/pages/modplatform/ResourcePackPage.h @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2023 flowln +// +// SPDX-License-Identifier: GPL-3.0-only + #pragma once #include "ui/pages/modplatform/ResourcePage.h" diff --git a/launcher/ui/pages/modplatform/ShaderPackModel.cpp b/launcher/ui/pages/modplatform/ShaderPackModel.cpp index 36993288..2101b394 100644 --- a/launcher/ui/pages/modplatform/ShaderPackModel.cpp +++ b/launcher/ui/pages/modplatform/ShaderPackModel.cpp @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2023 flowln +// +// SPDX-License-Identifier: GPL-3.0-only + #include "ShaderPackModel.h" #include diff --git a/launcher/ui/pages/modplatform/ShaderPackModel.h b/launcher/ui/pages/modplatform/ShaderPackModel.h index c84df15a..f3c695e9 100644 --- a/launcher/ui/pages/modplatform/ShaderPackModel.h +++ b/launcher/ui/pages/modplatform/ShaderPackModel.h @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2023 flowln +// +// SPDX-License-Identifier: GPL-3.0-only + #pragma once #include diff --git a/launcher/ui/pages/modplatform/ShaderPackPage.cpp b/launcher/ui/pages/modplatform/ShaderPackPage.cpp index 364d0a54..251c07e7 100644 --- a/launcher/ui/pages/modplatform/ShaderPackPage.cpp +++ b/launcher/ui/pages/modplatform/ShaderPackPage.cpp @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2023 flowln +// +// SPDX-License-Identifier: GPL-3.0-only + #include "ShaderPackPage.h" #include "ui_ResourcePage.h" diff --git a/launcher/ui/pages/modplatform/ShaderPackPage.h b/launcher/ui/pages/modplatform/ShaderPackPage.h index 92a9c3ee..972419a8 100644 --- a/launcher/ui/pages/modplatform/ShaderPackPage.h +++ b/launcher/ui/pages/modplatform/ShaderPackPage.h @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2023 flowln +// +// SPDX-License-Identifier: GPL-3.0-only + #pragma once #include "ui/pages/modplatform/ResourcePage.h" diff --git a/launcher/ui/pages/modplatform/TexturePackModel.cpp b/launcher/ui/pages/modplatform/TexturePackModel.cpp index 076a200d..fa636951 100644 --- a/launcher/ui/pages/modplatform/TexturePackModel.cpp +++ b/launcher/ui/pages/modplatform/TexturePackModel.cpp @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2023 flowln +// +// SPDX-License-Identifier: GPL-3.0-only + #include "TexturePackModel.h" #include "Application.h" diff --git a/launcher/ui/pages/modplatform/TexturePackModel.h b/launcher/ui/pages/modplatform/TexturePackModel.h index 0ae5bdd4..bb2db5cf 100644 --- a/launcher/ui/pages/modplatform/TexturePackModel.h +++ b/launcher/ui/pages/modplatform/TexturePackModel.h @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2023 flowln +// +// SPDX-License-Identifier: GPL-3.0-only + #pragma once #include "meta/VersionList.h" diff --git a/launcher/ui/pages/modplatform/TexturePackPage.h b/launcher/ui/pages/modplatform/TexturePackPage.h index 3466d3ea..0bdce2f9 100644 --- a/launcher/ui/pages/modplatform/TexturePackPage.h +++ b/launcher/ui/pages/modplatform/TexturePackPage.h @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2023 flowln +// +// SPDX-License-Identifier: GPL-3.0-only + #pragma once #include "ui_ResourcePage.h" From f986b4cd56a901295230fc84758910a2bed215cf Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 1 Mar 2023 07:20:11 +0000 Subject: [PATCH 5/7] chore(deps): update cachix/install-nix-action action to v20 --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8934f584..41eb5eb7 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -608,7 +608,7 @@ jobs: submodules: 'true' - name: Install nix if: inputs.build_type == 'Debug' - uses: cachix/install-nix-action@v19 + uses: cachix/install-nix-action@v20 with: install_url: https://nixos.org/nix/install extra_nix_config: | From 651e511ff06a54934573764906de176a397ef5a0 Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Wed, 1 Mar 2023 10:19:59 +0100 Subject: [PATCH 6/7] fix: use makeShared for importing components Signed-off-by: Sefa Eyeoglu --- launcher/minecraft/PackProfile.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/minecraft/PackProfile.cpp b/launcher/minecraft/PackProfile.cpp index 13da57d9..aff05dbc 100644 --- a/launcher/minecraft/PackProfile.cpp +++ b/launcher/minecraft/PackProfile.cpp @@ -763,7 +763,7 @@ bool PackProfile::installComponents(QStringList selectedFiles) continue; } - appendComponent(new Component(this, versionFile->uid, versionFile)); + appendComponent(makeShared(this, versionFile->uid, versionFile)); } scheduleSave(); From 89255e34bd0651ab226518090667bef92066d80c Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Thu, 2 Mar 2023 09:42:28 +0100 Subject: [PATCH 7/7] fix: change wording of TP/RP download buttons Signed-off-by: Sefa Eyeoglu --- launcher/ui/pages/instance/ResourcePackPage.cpp | 4 ++-- launcher/ui/pages/instance/TexturePackPage.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/launcher/ui/pages/instance/ResourcePackPage.cpp b/launcher/ui/pages/instance/ResourcePackPage.cpp index f46a7939..24bfb38d 100644 --- a/launcher/ui/pages/instance/ResourcePackPage.cpp +++ b/launcher/ui/pages/instance/ResourcePackPage.cpp @@ -46,8 +46,8 @@ ResourcePackPage::ResourcePackPage(MinecraftInstance* instance, std::shared_ptr model, QWidget* parent) : ExternalResourcesPage(instance, model, parent) { - ui->actionDownloadItem->setText(tr("Download RPs")); - ui->actionDownloadItem->setToolTip(tr("Download RPs from online platforms")); + ui->actionDownloadItem->setText(tr("Download packs")); + ui->actionDownloadItem->setToolTip(tr("Download resource packs from online platforms")); ui->actionDownloadItem->setEnabled(true); connect(ui->actionDownloadItem, &QAction::triggered, this, &ResourcePackPage::downloadRPs); ui->actionsToolbar->insertActionBefore(ui->actionAddItem, ui->actionDownloadItem); diff --git a/launcher/ui/pages/instance/TexturePackPage.cpp b/launcher/ui/pages/instance/TexturePackPage.cpp index 76fc04e7..427aba11 100644 --- a/launcher/ui/pages/instance/TexturePackPage.cpp +++ b/launcher/ui/pages/instance/TexturePackPage.cpp @@ -48,8 +48,8 @@ TexturePackPage::TexturePackPage(MinecraftInstance* instance, std::shared_ptr model, QWidget* parent) : ExternalResourcesPage(instance, model, parent) { - ui->actionDownloadItem->setText(tr("Download TPs")); - ui->actionDownloadItem->setToolTip(tr("Download TPs from online platforms")); + ui->actionDownloadItem->setText(tr("Download packs")); + ui->actionDownloadItem->setToolTip(tr("Download texture packs from online platforms")); ui->actionDownloadItem->setEnabled(true); connect(ui->actionDownloadItem, &QAction::triggered, this, &TexturePackPage::downloadTPs); ui->actionsToolbar->insertActionBefore(ui->actionAddItem, ui->actionDownloadItem);