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 <flowlnlnln@gmail.com>
This commit is contained in:
		| @@ -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? | ||||
|   | ||||
| @@ -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 | ||||
|  | ||||
|   | ||||
| @@ -99,6 +99,11 @@ QString Meta::Version::localFilename() const | ||||
|     return m_uid + '/' + m_version + ".json"; | ||||
| } | ||||
|  | ||||
| ::Version Meta::Version::toComparableVersion() const | ||||
| { | ||||
|     return { const_cast<Meta::Version*>(this)->descriptor() }; | ||||
| } | ||||
|  | ||||
| void Meta::Version::setType(const QString &type) | ||||
| { | ||||
|     m_type = type; | ||||
|   | ||||
| @@ -16,6 +16,7 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include "BaseVersion.h" | ||||
| #include "../Version.h" | ||||
|  | ||||
| #include <QJsonObject> | ||||
| #include <QStringList> | ||||
| @@ -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); | ||||
|   | ||||
| @@ -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<BasePage*> ResourcePackDownloadDialog::getPages() | ||||
| } | ||||
|  | ||||
|  | ||||
| TexturePackDownloadDialog::TexturePackDownloadDialog(QWidget* parent, | ||||
|                                                      const std::shared_ptr<TexturePackFolderModel>& 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<BasePage*> TexturePackDownloadDialog::getPages() | ||||
| { | ||||
|     QList<BasePage*> 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<ShaderPackFolderModel>& shaders, | ||||
|                                                    BaseInstance* instance) | ||||
|   | ||||
| @@ -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<TexturePackFolderModel>& 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<BasePage*> getPages() override; | ||||
|  | ||||
|    private: | ||||
|     BaseInstance* m_instance; | ||||
| }; | ||||
|  | ||||
| class ShaderPackDownloadDialog final : public ResourceDownloadDialog { | ||||
|     Q_OBJECT | ||||
|  | ||||
|   | ||||
							
								
								
									
										104
									
								
								launcher/ui/pages/instance/TexturePackPage.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										104
									
								
								launcher/ui/pages/instance/TexturePackPage.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,104 @@ | ||||
| // SPDX-License-Identifier: GPL-3.0-only | ||||
| /* | ||||
|  *  PolyMC - Minecraft Launcher | ||||
|  *  Copyright (c) 2022 Jamie Mansfield <jmansfield@cadixdev.org> | ||||
|  * | ||||
|  *  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 <https://www.gnu.org/licenses/>. | ||||
|  * | ||||
|  * 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<TexturePackFolderModel> 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<TexturePack&>(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<TexturePackFolderModel>(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(); | ||||
|     } | ||||
| } | ||||
| @@ -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<TexturePackFolderModel> model, QWidget *parent = 0) | ||||
|         : ExternalResourcesPage(instance, model, parent) | ||||
|     { | ||||
|         ui->actionViewConfigs->setVisible(false); | ||||
|     } | ||||
|     virtual ~TexturePackPage() {} | ||||
|     explicit TexturePackPage(MinecraftInstance *instance, std::shared_ptr<TexturePackFolderModel> 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<TexturePack&>(m_model->at(row)); | ||||
|         ui->frame->updateWithTexturePack(rp); | ||||
|  | ||||
|         return true; | ||||
|     } | ||||
|     bool onSelectionChanged(const QModelIndex& current, const QModelIndex& previous) override; | ||||
|     void downloadTPs(); | ||||
| }; | ||||
|   | ||||
| @@ -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&); | ||||
|   | ||||
| @@ -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); | ||||
|   | ||||
| @@ -39,7 +39,7 @@ class ResourcePackResourcePage : public ResourcePage { | ||||
|     [[nodiscard]] QMap<QString, QString> urlHandlers() const override; | ||||
|  | ||||
|    protected: | ||||
|     ResourcePackResourcePage(ResourcePackDownloadDialog* dialog, BaseInstance& instance); | ||||
|     ResourcePackResourcePage(ResourceDownloadDialog* dialog, BaseInstance& instance); | ||||
|  | ||||
|    protected slots: | ||||
|     void triggerSearch() override; | ||||
|   | ||||
							
								
								
									
										80
									
								
								launcher/ui/pages/modplatform/TexturePackModel.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								launcher/ui/pages/modplatform/TexturePackModel.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,80 @@ | ||||
| #include "TexturePackModel.h" | ||||
|  | ||||
| #include "Application.h" | ||||
|  | ||||
| #include "meta/Index.h" | ||||
| #include "meta/Version.h" | ||||
|  | ||||
| static std::list<Version> 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 | ||||
							
								
								
									
										23
									
								
								launcher/ui/pages/modplatform/TexturePackModel.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								launcher/ui/pages/modplatform/TexturePackModel.h
									
									
									
									
									
										Normal file
									
								
							| @@ -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 | ||||
							
								
								
									
										46
									
								
								launcher/ui/pages/modplatform/TexturePackPage.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								launcher/ui/pages/modplatform/TexturePackPage.h
									
									
									
									
									
										Normal file
									
								
							| @@ -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 <typename T> | ||||
|     static T* create(TexturePackDownloadDialog* dialog, BaseInstance& instance) | ||||
|     { | ||||
|         auto page = new T(dialog, instance); | ||||
|         auto model = static_cast<TexturePackResourceModel*>(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 | ||||
| @@ -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<ModPlatform::IndexedVersion> 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<const MinecraftInstance&>(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 | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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<FlameTexturePackPage>(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 | ||||
|   | ||||
| @@ -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) | ||||
|   | ||||
| @@ -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 | ||||
|  | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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<ModrinthTexturePackPage>(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 | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user