Merge branch 'PrismLauncher:develop' into modrinth-token

This commit is contained in:
TheKodeToad 2023-03-02 10:10:46 +00:00 committed by GitHub
commit 5c913149c8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
38 changed files with 1570 additions and 62 deletions

View File

@ -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: |

View File

@ -612,6 +612,9 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
m_settings->registerSetting("UpdateDialogGeometry", "");
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?
{

View File

@ -720,8 +720,11 @@ 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
ui/pages/instance/ShaderPackPage.cpp
ui/pages/instance/ModFolderPage.cpp
ui/pages/instance/ModFolderPage.h
ui/pages/instance/NotesPage.cpp
@ -773,6 +776,16 @@ SET(LAUNCHER_SOURCES
ui/pages/modplatform/ModModel.cpp
ui/pages/modplatform/ModModel.h
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
ui/pages/modplatform/atlauncher/AtlFilterModel.cpp
ui/pages/modplatform/atlauncher/AtlFilterModel.h
ui/pages/modplatform/atlauncher/AtlListModel.cpp

View File

@ -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;

View File

@ -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);

View File

@ -763,7 +763,7 @@ bool PackProfile::installComponents(QStringList selectedFiles)
continue;
}
appendComponent(new Component(this, versionFile->uid, versionFile));
appendComponent(makeShared<Component>(this, versionFile->uid, versionFile));
}
scheduleSave();

View File

@ -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:

View File

@ -27,6 +27,8 @@ class FlameAPI : public NetworkResourceAPI {
default:
case ModPlatform::ResourceType::MOD:
return 6;
case ModPlatform::ResourceType::RESOURCE_PACK:
return 12;
}
}

View File

@ -68,6 +68,10 @@ class ModrinthAPI : public NetworkResourceAPI {
switch (type) {
case ModPlatform::ResourceType::MOD:
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;

View File

@ -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"

View File

@ -25,6 +25,9 @@
#include "ResourceDownloadTask.h"
#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"
@ -229,4 +232,80 @@ QList<BasePage*> ModDownloadDialog::getPages()
return pages;
}
ResourcePackDownloadDialog::ResourcePackDownloadDialog(QWidget* parent,
const std::shared_ptr<ResourcePackFolderModel>& 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*> ResourcePackDownloadDialog::getPages()
{
QList<BasePage*> pages;
pages.append(ModrinthResourcePackPage::create(this, *m_instance));
if (APPLICATION->capabilities() & Application::SupportsFlame)
pages.append(FlameResourcePackPage::create(this, *m_instance));
return pages;
}
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)
: ResourceDownloadDialog(parent, shaders), m_instance(instance)
{
setWindowTitle(dialogTitle());
initializeContainer();
connectButtons();
if (!geometrySaveKey().isEmpty())
restoreGeometry(QByteArray::fromBase64(APPLICATION->settings()->get(geometrySaveKey()).toByteArray()));
}
QList<BasePage*> ShaderPackDownloadDialog::getPages()
{
QList<BasePage*> pages;
pages.append(ModrinthShaderPackPage::create(this, *m_instance));
return pages;
}
} // namespace ResourceDownload

View File

@ -35,6 +35,9 @@ class QVBoxLayout;
class QDialogButtonBox;
class ResourceDownloadTask;
class ResourceFolderModel;
class ResourcePackFolderModel;
class TexturePackFolderModel;
class ShaderPackFolderModel;
namespace ResourceDownload {
@ -108,4 +111,61 @@ class ModDownloadDialog final : public ResourceDownloadDialog {
BaseInstance* m_instance;
};
class ResourcePackDownloadDialog final : public ResourceDownloadDialog {
Q_OBJECT
public:
explicit ResourcePackDownloadDialog(QWidget* parent,
const std::shared_ptr<ResourcePackFolderModel>& 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<BasePage*> getPages() override;
private:
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
public:
explicit ShaderPackDownloadDialog(QWidget* parent,
const std::shared_ptr<ShaderPackFolderModel>& 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<BasePage*> getPages() override;
private:
BaseInstance* m_instance;
};
} // namespace ResourceDownload

View File

@ -0,0 +1,104 @@
// SPDX-FileCopyrightText: 2023 flowln <flowlnlnln@gmail.com>
//
// SPDX-License-Identifier: GPL-3.0-only AND Apache-2.0
/*
* Prism Launcher - 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 "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<ResourcePackFolderModel> model, QWidget* parent)
: ExternalResourcesPage(instance, model, parent)
{
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);
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<ResourcePack&>(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<ResourcePackFolderModel>(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();
}
}

View File

@ -1,6 +1,8 @@
// SPDX-License-Identifier: GPL-3.0-only
// SPDX-FileCopyrightText: 2023 flowln <flowlnlnln@gmail.com>
//
// SPDX-License-Identifier: GPL-3.0-only AND Apache-2.0
/*
* PolyMC - Minecraft Launcher
* Prism Launcher - Minecraft Launcher
* Copyright (c) 2022 Jamie Mansfield <jmansfield@cadixdev.org>
*
* This program is free software: you can redistribute it and/or modify
@ -44,12 +46,7 @@ class ResourcePackPage : public ExternalResourcesPage
{
Q_OBJECT
public:
explicit ResourcePackPage(MinecraftInstance *instance, std::shared_ptr<ResourcePackFolderModel> model, QWidget *parent = 0)
: ExternalResourcesPage(instance, model, parent)
{
ui->actionViewConfigs->setVisible(false);
}
virtual ~ResourcePackPage() {}
explicit ResourcePackPage(MinecraftInstance *instance, std::shared_ptr<ResourcePackFolderModel> model, QWidget *parent = 0);
QString displayName() const override { return tr("Resource packs"); }
QIcon icon() const override { return APPLICATION->getThemedIcon("resourcepacks"); }
@ -63,14 +60,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<ResourcePack&>(m_model->at(row));
ui->frame->updateWithResourcePack(rp);
return true;
}
bool onSelectionChanged(const QModelIndex& current, const QModelIndex& previous) override;
void downloadRPs();
};

View File

@ -0,0 +1,98 @@
// SPDX-FileCopyrightText: 2023 flowln <flowlnlnln@gmail.com>
//
// SPDX-License-Identifier: GPL-3.0-only AND Apache-2.0
/*
* Prism Launcher - 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 "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<ShaderPackFolderModel> 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<ShaderPackFolderModel>(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();
}
}

View File

@ -1,6 +1,8 @@
// SPDX-License-Identifier: GPL-3.0-only
// SPDX-FileCopyrightText: 2023 flowln <flowlnlnln@gmail.com>
//
// SPDX-License-Identifier: GPL-3.0-only AND Apache-2.0
/*
* PolyMC - Minecraft Launcher
* Prism Launcher - Minecraft Launcher
* Copyright (c) 2022 Jamie Mansfield <jmansfield@cadixdev.org>
*
* This program is free software: you can redistribute it and/or modify
@ -36,28 +38,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<ShaderPackFolderModel> model, QWidget *parent = 0)
: ExternalResourcesPage(instance, model, parent)
{
ui->actionViewConfigs->setVisible(false);
}
virtual ~ShaderPackPage() {}
explicit ShaderPackPage(MinecraftInstance *instance, std::shared_ptr<ShaderPackFolderModel> 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();
};

View File

@ -0,0 +1,106 @@
// SPDX-FileCopyrightText: 2023 flowln <flowlnlnln@gmail.com>
//
// SPDX-License-Identifier: GPL-3.0-only AND Apache-2.0
/*
* Prism Launcher - 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 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);
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();
}
}

View File

@ -1,6 +1,8 @@
// SPDX-License-Identifier: GPL-3.0-only
// SPDX-FileCopyrightText: 2023 flowln <flowlnlnln@gmail.com>
//
// SPDX-License-Identifier: GPL-3.0-only AND Apache-2.0
/*
* PolyMC - Minecraft Launcher
* Prism Launcher - Minecraft Launcher
* Copyright (c) 2022 Jamie Mansfield <jmansfield@cadixdev.org>
*
* This program is free software: you can redistribute it and/or modify
@ -39,18 +41,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 +59,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();
};

View File

@ -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&);

View File

@ -0,0 +1,46 @@
// SPDX-FileCopyrightText: 2023 flowln <flowlnlnln@gmail.com>
//
// SPDX-License-Identifier: GPL-3.0-only
#include "ResourcePackModel.h"
#include <QMessageBox>
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

View File

@ -0,0 +1,43 @@
// SPDX-FileCopyrightText: 2023 flowln <flowlnlnln@gmail.com>
//
// SPDX-License-Identifier: GPL-3.0-only
#pragma once
#include <QAbstractListModel>
#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

View File

@ -0,0 +1,46 @@
// SPDX-FileCopyrightText: 2023 flowln <flowlnlnln@gmail.com>
//
// SPDX-License-Identifier: GPL-3.0-only
#include "ResourcePackPage.h"
#include "ui_ResourcePage.h"
#include "ResourcePackModel.h"
#include "ui/dialogs/ResourceDownloadDialog.h"
#include <QRegularExpression>
namespace ResourceDownload {
ResourcePackResourcePage::ResourcePackResourcePage(ResourceDownloadDialog* 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<ResourcePackResourceModel*>(m_model)->searchWithTerm(getSearchTerm(), m_ui->sortByBox->currentData().toUInt());
m_fetch_progress.watch(m_model->activeSearchJob().get());
}
QMap<QString, QString> ResourcePackResourcePage::urlHandlers() const
{
QMap<QString, QString> 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

View File

@ -0,0 +1,52 @@
// SPDX-FileCopyrightText: 2023 flowln <flowlnlnln@gmail.com>
//
// SPDX-License-Identifier: GPL-3.0-only
#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 <typename T>
static T* create(ResourcePackDownloadDialog* dialog, BaseInstance& instance)
{
auto page = new T(dialog, instance);
auto model = static_cast<ResourcePackResourceModel*>(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<QString, QString> urlHandlers() const override;
protected:
ResourcePackResourcePage(ResourceDownloadDialog* dialog, BaseInstance& instance);
protected slots:
void triggerSearch() override;
};
} // namespace ResourceDownload

View File

@ -0,0 +1,46 @@
// SPDX-FileCopyrightText: 2023 flowln <flowlnlnln@gmail.com>
//
// SPDX-License-Identifier: GPL-3.0-only
#include "ShaderPackModel.h"
#include <QMessageBox>
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

View File

@ -0,0 +1,43 @@
// SPDX-FileCopyrightText: 2023 flowln <flowlnlnln@gmail.com>
//
// SPDX-License-Identifier: GPL-3.0-only
#pragma once
#include <QAbstractListModel>
#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

View File

@ -0,0 +1,54 @@
// SPDX-FileCopyrightText: 2023 flowln <flowlnlnln@gmail.com>
//
// SPDX-License-Identifier: GPL-3.0-only
#include "ShaderPackPage.h"
#include "ui_ResourcePage.h"
#include "ShaderPackModel.h"
#include "ui/dialogs/ResourceDownloadDialog.h"
#include <QRegularExpression>
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<ShaderPackResourceModel*>(m_model)->searchWithTerm(getSearchTerm(), m_ui->sortByBox->currentData().toUInt());
m_fetch_progress.watch(m_model->activeSearchJob().get());
}
QMap<QString, QString> ShaderPackResourcePage::urlHandlers() const
{
QMap<QString, QString> 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

View File

@ -0,0 +1,54 @@
// SPDX-FileCopyrightText: 2023 flowln <flowlnlnln@gmail.com>
//
// SPDX-License-Identifier: GPL-3.0-only
#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 <typename T>
static T* create(ShaderPackDownloadDialog* dialog, BaseInstance& instance)
{
auto page = new T(dialog, instance);
auto model = static_cast<ShaderPackResourceModel*>(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<QString, QString> urlHandlers() const override;
protected:
ShaderPackResourcePage(ShaderPackDownloadDialog* dialog, BaseInstance& instance);
protected slots:
void triggerSearch() override;
};
} // namespace ResourceDownload

View File

@ -0,0 +1,84 @@
// SPDX-FileCopyrightText: 2023 flowln <flowlnlnln@gmail.com>
//
// SPDX-License-Identifier: GPL-3.0-only
#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

View File

@ -0,0 +1,27 @@
// SPDX-FileCopyrightText: 2023 flowln <flowlnlnln@gmail.com>
//
// SPDX-License-Identifier: GPL-3.0-only
#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

View File

@ -0,0 +1,50 @@
// SPDX-FileCopyrightText: 2023 flowln <flowlnlnln@gmail.com>
//
// SPDX-License-Identifier: GPL-3.0-only
#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

View File

@ -34,4 +34,86 @@ 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");
}
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

View File

@ -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,43 @@ 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;
};
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

View File

@ -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,89 @@ 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);
}
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

View File

@ -43,6 +43,8 @@
#include "modplatform/ResourceAPI.h"
#include "ui/pages/modplatform/ModPage.h"
#include "ui/pages/modplatform/ResourcePackPage.h"
#include "ui/pages/modplatform/TexturePackPage.h"
namespace ResourceDownload {
@ -82,4 +84,58 @@ 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<FlameResourcePackPage>(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;
};
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

View File

@ -47,4 +47,70 @@ 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();
}
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)
{
::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

View File

@ -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,58 @@ 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;
};
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
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

View File

@ -82,9 +82,66 @@ 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());
}
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)
{
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 ModrinthTexturePackPage::shouldDisplay() const -> bool { return true; }
auto ModrinthShaderPackPage::shouldDisplay() const -> bool { return true; }
} // namespace ResourceDownload

View File

@ -42,6 +42,9 @@
#include "modplatform/ResourceAPI.h"
#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 {
@ -78,4 +81,73 @@ class ModrinthModPage : public ModPage {
auto validateVersion(ModPlatform::IndexedVersion& ver, QString mineVer, std::optional<ResourceAPI::ModLoaderTypes> loaders = {}) const -> bool override;
};
class ModrinthResourcePackPage : public ResourcePackResourcePage {
Q_OBJECT
public:
static ModrinthResourcePackPage* create(ResourcePackDownloadDialog* dialog, BaseInstance& instance)
{
return ResourcePackResourcePage::create<ModrinthResourcePackPage>(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 ""; }
};
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
public:
static ModrinthShaderPackPage* create(ShaderPackDownloadDialog* dialog, BaseInstance& instance)
{
return ShaderPackResourcePage::create<ModrinthShaderPackPage>(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