Merge branch 'PrismLauncher:develop' into skinfix
This commit is contained in:
@ -7,6 +7,7 @@
|
||||
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
||||
* Copyright (C) 2022 Lenny McLennington <lenny@sneed.church>
|
||||
* Copyright (C) 2022 Tayou <tayou@gmx.net>
|
||||
* Copyright (C) 2023 TheKodeToad <TheKodeToad@proton.me>
|
||||
*
|
||||
* 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
|
||||
@ -225,7 +226,7 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
|
||||
m_serverToJoin = parser.value("server");
|
||||
m_profileToUse = parser.value("profile");
|
||||
m_liveCheck = parser.isSet("alive");
|
||||
|
||||
|
||||
m_instanceIdToShowWindowOf = parser.value("show");
|
||||
|
||||
for (auto zip_path : parser.values("import")){
|
||||
@ -346,7 +347,7 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
|
||||
import.command = "import";
|
||||
import.args.insert("path", zip_url.toString());
|
||||
m_peerInstance->sendMessage(import.serialize(), timeout);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -611,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?
|
||||
{
|
||||
@ -657,6 +661,7 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
|
||||
m_settings->set("FlameKeyOverride", flameKey);
|
||||
m_settings->reset("CFKeyOverride");
|
||||
}
|
||||
m_settings->registerSetting("ModrinthToken", "");
|
||||
m_settings->registerSetting("UserAgentOverride", "");
|
||||
|
||||
// Init page provider
|
||||
@ -1545,6 +1550,15 @@ QString Application::getFlameAPIKey()
|
||||
return BuildConfig.FLAME_API_KEY;
|
||||
}
|
||||
|
||||
QString Application::getModrinthAPIToken()
|
||||
{
|
||||
QString tokenOverride = m_settings->get("ModrinthToken").toString();
|
||||
if (!tokenOverride.isEmpty())
|
||||
return tokenOverride;
|
||||
|
||||
return QString();
|
||||
}
|
||||
|
||||
QString Application::getUserAgent()
|
||||
{
|
||||
QString uaOverride = m_settings->get("UserAgentOverride").toString();
|
||||
|
@ -3,6 +3,7 @@
|
||||
* Prism Launcher - Minecraft Launcher
|
||||
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
||||
* Copyright (C) 2022 Tayou <tayou@gmx.net>
|
||||
* Copyright (C) 2023 TheKodeToad <TheKodeToad@proton.me>
|
||||
*
|
||||
* 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
|
||||
@ -177,6 +178,7 @@ public:
|
||||
|
||||
QString getMSAClientID();
|
||||
QString getFlameAPIKey();
|
||||
QString getModrinthAPIToken();
|
||||
QString getUserAgent();
|
||||
QString getUserAgentUncached();
|
||||
|
||||
|
@ -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
|
||||
@ -1025,6 +1038,7 @@ target_link_libraries(Launcher_logic
|
||||
nbt++
|
||||
${ZLIB_LIBRARIES}
|
||||
tomlplusplus::tomlplusplus
|
||||
qdcss
|
||||
BuildConfig
|
||||
Katabasis
|
||||
Qt${QT_VERSION_MAJOR}::Widgets
|
||||
|
@ -66,7 +66,12 @@ bool InstanceImportTask::abort()
|
||||
|
||||
if (m_filesNetJob)
|
||||
m_filesNetJob->abort();
|
||||
m_extractFuture.cancel();
|
||||
if (m_extractFuture.isRunning()) {
|
||||
// NOTE: The tasks created by QtConcurrent::run() can't actually get cancelled,
|
||||
// but we can use this call to check the state when the extraction finishes.
|
||||
m_extractFuture.cancel();
|
||||
m_extractFuture.waitForFinished();
|
||||
}
|
||||
|
||||
return Task::abort();
|
||||
}
|
||||
@ -185,18 +190,20 @@ void InstanceImportTask::processZipPack()
|
||||
// make sure we extract just the pack
|
||||
m_extractFuture = QtConcurrent::run(QThreadPool::globalInstance(), MMCZip::extractSubDir, m_packZip.get(), root, extractDir.absolutePath());
|
||||
connect(&m_extractFutureWatcher, &QFutureWatcher<QStringList>::finished, this, &InstanceImportTask::extractFinished);
|
||||
connect(&m_extractFutureWatcher, &QFutureWatcher<QStringList>::canceled, this, &InstanceImportTask::extractAborted);
|
||||
m_extractFutureWatcher.setFuture(m_extractFuture);
|
||||
}
|
||||
|
||||
void InstanceImportTask::extractFinished()
|
||||
{
|
||||
m_packZip.reset();
|
||||
if (!m_extractFuture.result())
|
||||
{
|
||||
|
||||
if (m_extractFuture.isCanceled())
|
||||
return;
|
||||
if (!m_extractFuture.result().has_value()) {
|
||||
emitFailed(tr("Failed to extract modpack"));
|
||||
return;
|
||||
}
|
||||
|
||||
QDir extractDir(m_stagingPath);
|
||||
|
||||
qDebug() << "Fixing permissions for extracted pack files...";
|
||||
@ -250,11 +257,6 @@ void InstanceImportTask::extractFinished()
|
||||
}
|
||||
}
|
||||
|
||||
void InstanceImportTask::extractAborted()
|
||||
{
|
||||
emitAborted();
|
||||
}
|
||||
|
||||
void InstanceImportTask::processFlame()
|
||||
{
|
||||
FlameCreationTask* inst_creation_task = nullptr;
|
||||
|
@ -81,7 +81,6 @@ private slots:
|
||||
void downloadProgressChanged(qint64 current, qint64 total);
|
||||
void downloadAborted();
|
||||
void extractFinished();
|
||||
void extractAborted();
|
||||
|
||||
private: /* data */
|
||||
NetJob::Ptr m_filesNetJob;
|
||||
|
@ -36,9 +36,10 @@ public:
|
||||
values.append(new VersionPage(onesix.get()));
|
||||
values.append(ManagedPackPage::createPage(onesix.get()));
|
||||
auto modsPage = new ModFolderPage(onesix.get(), onesix->loaderModList());
|
||||
modsPage->setFilter("%1 (*.zip *.jar *.litemod)");
|
||||
modsPage->setFilter("%1 (*.zip *.jar *.litemod *.nilmod)");
|
||||
values.append(modsPage);
|
||||
values.append(new CoreModFolderPage(onesix.get(), onesix->coreModList()));
|
||||
values.append(new NilModFolderPage(onesix.get(), onesix->nilModList()));
|
||||
values.append(new ResourcePackPage(onesix.get(), onesix->resourcePackList()));
|
||||
values.append(new TexturePackPage(onesix.get(), onesix->texturePackList()));
|
||||
values.append(new ShaderPackPage(onesix.get(), onesix->shaderPackList()));
|
||||
|
@ -275,7 +275,7 @@ bool MMCZip::findFilesInZip(QuaZip * zip, const QString & what, QStringList & re
|
||||
// ours
|
||||
std::optional<QStringList> MMCZip::extractSubDir(QuaZip *zip, const QString & subdir, const QString &target)
|
||||
{
|
||||
auto absDirectoryUrl = QUrl::fromLocalFile(target);
|
||||
auto target_top_dir = QUrl::fromLocalFile(target);
|
||||
|
||||
QStringList extracted;
|
||||
|
||||
@ -295,58 +295,53 @@ std::optional<QStringList> MMCZip::extractSubDir(QuaZip *zip, const QString & su
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
QString name = zip->getCurrentFileName();
|
||||
if(!name.startsWith(subdir))
|
||||
{
|
||||
do {
|
||||
QString file_name = zip->getCurrentFileName();
|
||||
if (!file_name.startsWith(subdir))
|
||||
continue;
|
||||
}
|
||||
|
||||
name.remove(0, subdir.size());
|
||||
auto original_name = name;
|
||||
auto relative_file_name = QDir::fromNativeSeparators(file_name.remove(0, subdir.size()));
|
||||
auto original_name = relative_file_name;
|
||||
|
||||
// Fix subdirs/files ending with a / getting transformed into absolute paths
|
||||
if(name.startsWith('/')){
|
||||
name = name.mid(1);
|
||||
}
|
||||
if (relative_file_name.startsWith('/'))
|
||||
relative_file_name = relative_file_name.mid(1);
|
||||
|
||||
// Fix weird "folders with a single file get squashed" thing
|
||||
QString path;
|
||||
if(name.contains('/') && !name.endsWith('/')){
|
||||
path = name.section('/', 0, -2) + "/";
|
||||
FS::ensureFolderPathExists(FS::PathCombine(target, path));
|
||||
QString sub_path;
|
||||
if (relative_file_name.contains('/') && !relative_file_name.endsWith('/')) {
|
||||
sub_path = relative_file_name.section('/', 0, -2) + '/';
|
||||
FS::ensureFolderPathExists(FS::PathCombine(target, sub_path));
|
||||
|
||||
name = name.split('/').last();
|
||||
relative_file_name = relative_file_name.split('/').last();
|
||||
}
|
||||
|
||||
QString absFilePath;
|
||||
if(name.isEmpty())
|
||||
{
|
||||
absFilePath = FS::PathCombine(target, "/"); // FIXME this seems weird
|
||||
}
|
||||
else
|
||||
{
|
||||
absFilePath = FS::PathCombine(target, path + name);
|
||||
QString target_file_path;
|
||||
if (relative_file_name.isEmpty()) {
|
||||
target_file_path = target + '/';
|
||||
} else {
|
||||
target_file_path = FS::PathCombine(target_top_dir.toLocalFile(), sub_path, relative_file_name);
|
||||
if (relative_file_name.endsWith('/') && !target_file_path.endsWith('/'))
|
||||
target_file_path += '/';
|
||||
}
|
||||
|
||||
if (!absDirectoryUrl.isParentOf(QUrl::fromLocalFile(absFilePath))) {
|
||||
qWarning() << "Extracting" << name << "was cancelled, because it was effectively outside of the target path" << target;
|
||||
if (!target_top_dir.isParentOf(QUrl::fromLocalFile(target_file_path))) {
|
||||
qWarning() << "Extracting" << relative_file_name << "was cancelled, because it was effectively outside of the target path" << target;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
if (!JlCompress::extractFile(zip, "", absFilePath))
|
||||
{
|
||||
qWarning() << "Failed to extract file" << original_name << "to" << absFilePath;
|
||||
if (!JlCompress::extractFile(zip, "", target_file_path)) {
|
||||
qWarning() << "Failed to extract file" << original_name << "to" << target_file_path;
|
||||
JlCompress::removeFile(extracted);
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
extracted.append(absFilePath);
|
||||
QFile::setPermissions(absFilePath, QFileDevice::Permission::ReadUser | QFileDevice::Permission::WriteUser | QFileDevice::Permission::ExeUser);
|
||||
extracted.append(target_file_path);
|
||||
QFile::setPermissions(target_file_path, QFileDevice::Permission::ReadUser | QFileDevice::Permission::WriteUser | QFileDevice::Permission::ExeUser);
|
||||
|
||||
qDebug() << "Extracted file" << name << "to" << absFilePath;
|
||||
qDebug() << "Extracted file" << relative_file_name << "to" << target_file_path;
|
||||
} while (zip->goToNextFile());
|
||||
|
||||
return extracted;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -292,6 +292,11 @@ QString MinecraftInstance::coreModsDir() const
|
||||
return FS::PathCombine(gameRoot(), "coremods");
|
||||
}
|
||||
|
||||
QString MinecraftInstance::nilModsDir() const
|
||||
{
|
||||
return FS::PathCombine(gameRoot(), "nilmods");
|
||||
}
|
||||
|
||||
QString MinecraftInstance::resourcePacksDir() const
|
||||
{
|
||||
return FS::PathCombine(gameRoot(), "resourcepacks");
|
||||
@ -1138,6 +1143,18 @@ std::shared_ptr<ModFolderModel> MinecraftInstance::coreModList() const
|
||||
return m_core_mod_list;
|
||||
}
|
||||
|
||||
std::shared_ptr<ModFolderModel> MinecraftInstance::nilModList() const
|
||||
{
|
||||
if (!m_nil_mod_list)
|
||||
{
|
||||
bool is_indexed = !APPLICATION->settings()->get("ModMetadataDisabled").toBool();
|
||||
m_nil_mod_list.reset(new ModFolderModel(nilModsDir(), is_indexed, false));
|
||||
m_nil_mod_list->disableInteraction(isRunning());
|
||||
connect(this, &BaseInstance::runningStatusChanged, m_nil_mod_list.get(), &ModFolderModel::disableInteraction);
|
||||
}
|
||||
return m_nil_mod_list;
|
||||
}
|
||||
|
||||
std::shared_ptr<ResourcePackFolderModel> MinecraftInstance::resourcePackList() const
|
||||
{
|
||||
if (!m_resource_pack_list)
|
||||
|
@ -84,6 +84,7 @@ public:
|
||||
QString shaderPacksDir() const;
|
||||
QString modsRoot() const override;
|
||||
QString coreModsDir() const;
|
||||
QString nilModsDir() const;
|
||||
QString modsCacheLocation() const;
|
||||
QString libDir() const;
|
||||
QString worldDir() const;
|
||||
@ -116,6 +117,7 @@ public:
|
||||
////// Mod Lists //////
|
||||
std::shared_ptr<ModFolderModel> loaderModList() const;
|
||||
std::shared_ptr<ModFolderModel> coreModList() const;
|
||||
std::shared_ptr<ModFolderModel> nilModList() const;
|
||||
std::shared_ptr<ResourcePackFolderModel> resourcePackList() const;
|
||||
std::shared_ptr<TexturePackFolderModel> texturePackList() const;
|
||||
std::shared_ptr<ShaderPackFolderModel> shaderPackList() const;
|
||||
@ -171,6 +173,7 @@ protected: // data
|
||||
std::shared_ptr<PackProfile> m_components;
|
||||
mutable std::shared_ptr<ModFolderModel> m_loader_mod_list;
|
||||
mutable std::shared_ptr<ModFolderModel> m_core_mod_list;
|
||||
mutable std::shared_ptr<ModFolderModel> m_nil_mod_list;
|
||||
mutable std::shared_ptr<ResourcePackFolderModel> m_resource_pack_list;
|
||||
mutable std::shared_ptr<ShaderPackFolderModel> m_shader_pack_list;
|
||||
mutable std::shared_ptr<TexturePackFolderModel> m_texture_pack_list;
|
||||
|
@ -1,7 +1,10 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
// SPDX-FileCopyrightText: 2022-2023 Sefa Eyeoglu <contact@scrumplex.net>
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-only AND Apache-2.0
|
||||
|
||||
/*
|
||||
* Prism Launcher - Minecraft Launcher
|
||||
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
||||
* Copyright (C) 2022-2023 Sefa Eyeoglu <contact@scrumplex.net>
|
||||
* Copyright (C) 2022 TheKodeToad <TheKodeToad@proton.me>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
@ -49,6 +52,7 @@
|
||||
#include "minecraft/OneSixVersionFormat.h"
|
||||
#include "FileSystem.h"
|
||||
#include "minecraft/MinecraftInstance.h"
|
||||
#include "minecraft/ProfileUtils.h"
|
||||
#include "Json.h"
|
||||
|
||||
#include "PackProfile.h"
|
||||
@ -730,16 +734,47 @@ void PackProfile::invalidateLaunchProfile()
|
||||
|
||||
void PackProfile::installJarMods(QStringList selectedFiles)
|
||||
{
|
||||
// FIXME: get rid of _internal
|
||||
installJarMods_internal(selectedFiles);
|
||||
}
|
||||
|
||||
void PackProfile::installCustomJar(QString selectedFile)
|
||||
{
|
||||
// FIXME: get rid of _internal
|
||||
installCustomJar_internal(selectedFile);
|
||||
}
|
||||
|
||||
bool PackProfile::installComponents(QStringList selectedFiles)
|
||||
{
|
||||
const QString patchDir = FS::PathCombine(d->m_instance->instanceRoot(), "patches");
|
||||
if (!FS::ensureFolderPathExists(patchDir))
|
||||
return false;
|
||||
|
||||
bool result = true;
|
||||
for (const QString& source : selectedFiles) {
|
||||
const QFileInfo sourceInfo(source);
|
||||
|
||||
auto versionFile = ProfileUtils::parseJsonFile(sourceInfo, false);
|
||||
const QString target = FS::PathCombine(patchDir, versionFile->uid + ".json");
|
||||
|
||||
if (!QFile::copy(source, target)) {
|
||||
qWarning() << "Component" << source << "could not be copied to target" << target;
|
||||
result = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
appendComponent(makeShared<Component>(this, versionFile->uid, versionFile));
|
||||
}
|
||||
|
||||
scheduleSave();
|
||||
invalidateLaunchProfile();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void PackProfile::installAgents(QStringList selectedFiles)
|
||||
{
|
||||
// FIXME: get rid of _internal
|
||||
installAgents_internal(selectedFiles);
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,10 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
// SPDX-FileCopyrightText: 2022-2023 Sefa Eyeoglu <contact@scrumplex.net>
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-only AND Apache-2.0
|
||||
|
||||
/*
|
||||
* Prism Launcher - Minecraft Launcher
|
||||
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
||||
* Copyright (C) 2022-2023 Sefa Eyeoglu <contact@scrumplex.net>
|
||||
* Copyright (C) 2022 TheKodeToad <TheKodeToad@proton.me>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
@ -86,6 +89,9 @@ public:
|
||||
/// install a jar/zip as a replacement for the main jar
|
||||
void installCustomJar(QString selectedFile);
|
||||
|
||||
/// install MMC/Prism component files
|
||||
bool installComponents(QStringList selectedFiles);
|
||||
|
||||
/// install Java agent files
|
||||
void installAgents(QStringList selectedFiles);
|
||||
|
||||
|
@ -55,6 +55,12 @@ void ScanModFolders::executeTask()
|
||||
if(!cores->update()) {
|
||||
m_coreModsDone = true;
|
||||
}
|
||||
|
||||
auto nils = m_inst->nilModList();
|
||||
connect(nils.get(), &ModFolderModel::updateFinished, this, &ScanModFolders::nilModsDone);
|
||||
if(!nils->update()) {
|
||||
m_nilModsDone = true;
|
||||
}
|
||||
checkDone();
|
||||
}
|
||||
|
||||
@ -70,9 +76,15 @@ void ScanModFolders::coreModsDone()
|
||||
checkDone();
|
||||
}
|
||||
|
||||
void ScanModFolders::nilModsDone()
|
||||
{
|
||||
m_nilModsDone = true;
|
||||
checkDone();
|
||||
}
|
||||
|
||||
void ScanModFolders::checkDone()
|
||||
{
|
||||
if(m_modsDone && m_coreModsDone) {
|
||||
if(m_modsDone && m_coreModsDone && m_nilModsDone) {
|
||||
emitSucceeded();
|
||||
}
|
||||
}
|
||||
|
@ -33,10 +33,12 @@ public:
|
||||
private slots:
|
||||
void coreModsDone();
|
||||
void modsDone();
|
||||
void nilModsDone();
|
||||
private:
|
||||
void checkDone();
|
||||
|
||||
private: // DATA
|
||||
bool m_modsDone = false;
|
||||
bool m_nilModsDone = false;
|
||||
bool m_coreModsDone = false;
|
||||
};
|
||||
|
@ -50,7 +50,7 @@
|
||||
#include "minecraft/mod/tasks/ModFolderLoadTask.h"
|
||||
#include "modplatform/ModIndex.h"
|
||||
|
||||
ModFolderModel::ModFolderModel(const QString &dir, bool is_indexed) : ResourceFolderModel(QDir(dir)), m_is_indexed(is_indexed)
|
||||
ModFolderModel::ModFolderModel(const QString &dir, bool is_indexed, bool create_dir) : ResourceFolderModel(QDir(dir), nullptr, create_dir), m_is_indexed(is_indexed)
|
||||
{
|
||||
m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::VERSION, SortType::DATE, SortType::PROVIDER };
|
||||
}
|
||||
|
@ -75,7 +75,7 @@ public:
|
||||
Enable,
|
||||
Toggle
|
||||
};
|
||||
ModFolderModel(const QString &dir, bool is_indexed = false);
|
||||
ModFolderModel(const QString &dir, bool is_indexed = false, bool create_dir = true);
|
||||
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
|
||||
|
@ -37,6 +37,9 @@ void Resource::parseFile()
|
||||
if (file_name.endsWith(".zip") || file_name.endsWith(".jar")) {
|
||||
m_type = ResourceType::ZIPFILE;
|
||||
file_name.chop(4);
|
||||
} else if (file_name.endsWith(".nilmod")) {
|
||||
m_type = ResourceType::ZIPFILE;
|
||||
file_name.chop(7);
|
||||
} else if (file_name.endsWith(".litemod")) {
|
||||
m_type = ResourceType::LITEMOD;
|
||||
file_name.chop(8);
|
||||
|
@ -12,9 +12,11 @@
|
||||
|
||||
#include "tasks/Task.h"
|
||||
|
||||
ResourceFolderModel::ResourceFolderModel(QDir dir, QObject* parent) : QAbstractListModel(parent), m_dir(dir), m_watcher(this)
|
||||
ResourceFolderModel::ResourceFolderModel(QDir dir, QObject* parent, bool create_dir) : QAbstractListModel(parent), m_dir(dir), m_watcher(this)
|
||||
{
|
||||
FS::ensureFolderPathExists(m_dir.absolutePath());
|
||||
if (create_dir) {
|
||||
FS::ensureFolderPathExists(m_dir.absolutePath());
|
||||
}
|
||||
|
||||
m_dir.setFilter(QDir::Readable | QDir::NoDotAndDotDot | QDir::Files | QDir::Dirs);
|
||||
m_dir.setSorting(QDir::Name | QDir::IgnoreCase | QDir::LocaleAware);
|
||||
|
@ -24,7 +24,7 @@ class QSortFilterProxyModel;
|
||||
class ResourceFolderModel : public QAbstractListModel {
|
||||
Q_OBJECT
|
||||
public:
|
||||
ResourceFolderModel(QDir, QObject* parent = nullptr);
|
||||
ResourceFolderModel(QDir, QObject* parent = nullptr, bool create_dir = true);
|
||||
~ResourceFolderModel() override;
|
||||
|
||||
/** Starts watching the paths for changes.
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include <quazip/quazip.h>
|
||||
#include <quazip/quazipfile.h>
|
||||
#include <toml++/toml.h>
|
||||
#include <qdcss.h>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
@ -285,6 +286,32 @@ ModDetails ReadLiteModInfo(QByteArray contents)
|
||||
return details;
|
||||
}
|
||||
|
||||
// https://git.sleeping.town/unascribed/NilLoader/src/commit/d7fc87b255fc31019ff90f80d45894927fac6efc/src/main/java/nilloader/api/NilMetadata.java#L64
|
||||
ModDetails ReadNilModInfo(QByteArray contents, QString fname)
|
||||
{
|
||||
ModDetails details;
|
||||
|
||||
QDCSS cssData = QDCSS(contents);
|
||||
auto name = cssData.get("@nilmod.name");
|
||||
auto desc = cssData.get("@nilmod.description");
|
||||
auto authors = cssData.get("@nilmod.authors");
|
||||
|
||||
if (name->has_value()) {
|
||||
details.name = name->value();
|
||||
}
|
||||
if (desc->has_value()) {
|
||||
details.description = desc->value();
|
||||
}
|
||||
if (authors->has_value()) {
|
||||
details.authors.append(authors->value());
|
||||
}
|
||||
details.version = cssData.get("@nilmod.version")->value_or("?");
|
||||
|
||||
details.mod_id = fname.remove(".nilmod.css");
|
||||
|
||||
return details;
|
||||
}
|
||||
|
||||
bool process(Mod& mod, ProcessingLevel level)
|
||||
{
|
||||
switch (mod.type()) {
|
||||
@ -401,6 +428,32 @@ bool processZIP(Mod& mod, ProcessingLevel level)
|
||||
|
||||
mod.setDetails(details);
|
||||
return true;
|
||||
} else if (zip.setCurrentFile("META-INF/nil/mappings.json")) {
|
||||
// nilloader uses the filename of the metadata file for the modid, so we can't know the exact filename
|
||||
// thankfully, there is a good file to use as a canary so we don't look for nil meta all the time
|
||||
|
||||
QString foundNilMeta;
|
||||
for (auto& fname : zip.getFileNameList()) {
|
||||
// nilmods can shade nilloader to be able to run as a standalone agent - which includes nilloader's own meta file
|
||||
if (fname.endsWith(".nilmod.css") && fname != "nilloader.nilmod.css") {
|
||||
foundNilMeta = fname;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (zip.setCurrentFile(foundNilMeta)) {
|
||||
if (!file.open(QIODevice::ReadOnly)) {
|
||||
zip.close();
|
||||
return false;
|
||||
}
|
||||
|
||||
details = ReadNilModInfo(file.readAll(), foundNilMeta);
|
||||
file.close();
|
||||
zip.close();
|
||||
|
||||
mod.setDetails(details);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
zip.close();
|
||||
|
@ -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:
|
||||
|
@ -27,6 +27,8 @@ class FlameAPI : public NetworkResourceAPI {
|
||||
default:
|
||||
case ModPlatform::ResourceType::MOD:
|
||||
return 6;
|
||||
case ModPlatform::ResourceType::RESOURCE_PACK:
|
||||
return 12;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -1,8 +1,9 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
/*
|
||||
* PolyMC - Minecraft Launcher
|
||||
* Prism Launcher - Minecraft Launcher
|
||||
* Copyright (c) 2022 flowln <flowlnlnln@gmail.com>
|
||||
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
||||
* Copyright (C) 2023 TheKodeToad <TheKodeToad@proton.me>
|
||||
*
|
||||
* 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
|
||||
@ -113,10 +114,15 @@ void Download::executeTask()
|
||||
}
|
||||
|
||||
request.setHeader(QNetworkRequest::UserAgentHeader, APPLICATION->getUserAgent().toUtf8());
|
||||
if (APPLICATION->capabilities() & Application::SupportsFlame
|
||||
&& request.url().host().contains("api.curseforge.com")) {
|
||||
// TODO remove duplication
|
||||
if (APPLICATION->capabilities() & Application::SupportsFlame && request.url().host() == QUrl(BuildConfig.FLAME_BASE_URL).host()) {
|
||||
request.setRawHeader("x-api-key", APPLICATION->getFlameAPIKey().toUtf8());
|
||||
};
|
||||
} else if (request.url().host() == QUrl(BuildConfig.MODRINTH_PROD_URL).host() ||
|
||||
request.url().host() == QUrl(BuildConfig.MODRINTH_STAGING_URL).host()) {
|
||||
QString token = APPLICATION->getModrinthAPIToken();
|
||||
if (!token.isNull())
|
||||
request.setRawHeader("Authorization", token.toUtf8());
|
||||
}
|
||||
|
||||
QNetworkReply* rep = m_network->get(request);
|
||||
|
||||
|
@ -1,8 +1,9 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
/*
|
||||
* PolyMC - Minecraft Launcher
|
||||
* Prism Launcher - Minecraft Launcher
|
||||
* Copyright (c) 2022 flowln <flowlnlnln@gmail.com>
|
||||
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
||||
* Copyright (C) 2023 TheKodeToad <TheKodeToad@proton.me>
|
||||
*
|
||||
* 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
|
||||
@ -216,10 +217,16 @@ namespace Net {
|
||||
}
|
||||
|
||||
request.setHeader(QNetworkRequest::UserAgentHeader, APPLICATION->getUserAgent().toUtf8());
|
||||
if (APPLICATION->capabilities() & Application::SupportsFlame
|
||||
&& request.url().host().contains("api.curseforge.com")) {
|
||||
// TODO remove duplication
|
||||
if (APPLICATION->capabilities() & Application::SupportsFlame && request.url().host() == QUrl(BuildConfig.FLAME_BASE_URL).host()) {
|
||||
request.setRawHeader("x-api-key", APPLICATION->getFlameAPIKey().toUtf8());
|
||||
} else if (request.url().host() == QUrl(BuildConfig.MODRINTH_PROD_URL).host() ||
|
||||
request.url().host() == QUrl(BuildConfig.MODRINTH_STAGING_URL).host()) {
|
||||
QString token = APPLICATION->getModrinthAPIToken();
|
||||
if (!token.isNull())
|
||||
request.setRawHeader("Authorization", token.toUtf8());
|
||||
}
|
||||
|
||||
//TODO other types of post requests ?
|
||||
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
|
||||
QNetworkReply* rep = m_network->post(request, m_post_data);
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -1,9 +1,10 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
/*
|
||||
* PolyMC - Minecraft Launcher
|
||||
* Prism Launcher - Minecraft Launcher
|
||||
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
||||
* Copyright (c) 2022 Jamie Mansfield <jmansfield@cadixdev.org>
|
||||
* Copyright (c) 2022 Lenny McLennington <lenny@sneed.church>
|
||||
* Copyright (C) 2023 TheKodeToad <TheKodeToad@proton.me>
|
||||
*
|
||||
* 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
|
||||
@ -147,6 +148,8 @@ void APIPage::loadSettings()
|
||||
ui->metaURL->setText(metaURL);
|
||||
QString flameKey = s->get("FlameKeyOverride").toString();
|
||||
ui->flameKey->setText(flameKey);
|
||||
QString modrinthToken = s->get("ModrinthToken").toString();
|
||||
ui->modrinthToken->setText(modrinthToken);
|
||||
QString customUserAgent = s->get("UserAgentOverride").toString();
|
||||
ui->userAgentLineEdit->setText(customUserAgent);
|
||||
}
|
||||
@ -177,6 +180,8 @@ void APIPage::applySettings()
|
||||
s->set("MetaURLOverride", metaURL);
|
||||
QString flameKey = ui->flameKey->text();
|
||||
s->set("FlameKeyOverride", flameKey);
|
||||
QString modrinthToken = ui->modrinthToken->text();
|
||||
s->set("ModrinthToken", modrinthToken);
|
||||
s->set("UserAgentOverride", ui->userAgentLineEdit->text());
|
||||
}
|
||||
|
||||
|
@ -195,6 +195,51 @@
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_modrinth">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>&Modrinth API</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="text">
|
||||
<string><html><head/><body><p>Note: you only need to set this to access private data. Read the <a href="https://docs.modrinth.com/api-spec/#section/Authentication">documentation</a> for more information.</p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>Enter a custom API token for Modrinth here.</string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::RichText</enum>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="openExternalLinks">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLineEdit" name="modrinthToken">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="placeholderText">
|
||||
<string>(None)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_flame">
|
||||
<property name="enabled">
|
||||
@ -203,16 +248,16 @@
|
||||
<property name="title">
|
||||
<string>&CurseForge Core API</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_8">
|
||||
<widget class="QLabel" name="label_10">
|
||||
<property name="text">
|
||||
<string>Note: you probably don't need to set this if CurseForge already works.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<widget class="QLabel" name="label_9">
|
||||
<property name="text">
|
||||
<string>Enter a custom API Key for CurseForge here.</string>
|
||||
</property>
|
||||
|
@ -273,3 +273,12 @@ bool CoreModFolderPage::shouldDisplay() const
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
NilModFolderPage::NilModFolderPage(BaseInstance* inst, std::shared_ptr<ModFolderModel> mods, QWidget* parent)
|
||||
: ModFolderPage(inst, mods, parent)
|
||||
{}
|
||||
|
||||
bool NilModFolderPage::shouldDisplay() const
|
||||
{
|
||||
return m_model->dir().exists();
|
||||
}
|
||||
|
@ -81,3 +81,16 @@ class CoreModFolderPage : public ModFolderPage {
|
||||
|
||||
virtual bool shouldDisplay() const override;
|
||||
};
|
||||
|
||||
class NilModFolderPage : public ModFolderPage {
|
||||
public:
|
||||
explicit NilModFolderPage(BaseInstance* inst, std::shared_ptr<ModFolderModel> mods, QWidget* parent = 0);
|
||||
virtual ~NilModFolderPage() = default;
|
||||
|
||||
virtual QString displayName() const override { return tr("Nilmods"); }
|
||||
virtual QIcon icon() const override { return APPLICATION->getThemedIcon("coremods"); }
|
||||
virtual QString id() const override { return "nilmods"; }
|
||||
virtual QString helpPage() const override { return "Nilmods"; }
|
||||
|
||||
virtual bool shouldDisplay() const override;
|
||||
};
|
||||
|
104
launcher/ui/pages/instance/ResourcePackPage.cpp
Normal file
104
launcher/ui/pages/instance/ResourcePackPage.cpp
Normal 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();
|
||||
}
|
||||
}
|
@ -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();
|
||||
};
|
||||
|
||||
|
98
launcher/ui/pages/instance/ShaderPackPage.cpp
Normal file
98
launcher/ui/pages/instance/ShaderPackPage.cpp
Normal 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();
|
||||
}
|
||||
}
|
@ -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();
|
||||
};
|
||||
|
106
launcher/ui/pages/instance/TexturePackPage.cpp
Normal file
106
launcher/ui/pages/instance/TexturePackPage.cpp
Normal 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();
|
||||
}
|
||||
}
|
@ -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();
|
||||
};
|
||||
|
@ -1,8 +1,11 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
// SPDX-FileCopyrightText: 2022-2023 Sefa Eyeoglu <contact@scrumplex.net>
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-only AND Apache-2.0
|
||||
|
||||
/*
|
||||
* Prism Launcher - Minecraft Launcher
|
||||
* Copyright (c) 2022 Jamie Mansfield <jmansfield@cadixdev.org>
|
||||
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
||||
* Copyright (C) 2022-2023 Sefa Eyeoglu <contact@scrumplex.net>
|
||||
* Copyright (C) 2022 TheKodeToad <TheKodeToad@proton.me>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
@ -282,6 +285,7 @@ void VersionPage::updateButtons(int row)
|
||||
ui->actionRevert->setEnabled(controlsEnabled && patch && patch->isRevertible());
|
||||
ui->actionDownload_All->setEnabled(controlsEnabled);
|
||||
ui->actionAdd_Empty->setEnabled(controlsEnabled);
|
||||
ui->actionImport_Components->setEnabled(controlsEnabled);
|
||||
ui->actionReload->setEnabled(controlsEnabled);
|
||||
ui->actionInstall_mods->setEnabled(controlsEnabled);
|
||||
ui->actionReplace_Minecraft_jar->setEnabled(controlsEnabled);
|
||||
@ -375,6 +379,20 @@ void VersionPage::on_actionReplace_Minecraft_jar_triggered()
|
||||
updateButtons();
|
||||
}
|
||||
|
||||
void VersionPage::on_actionImport_Components_triggered()
|
||||
{
|
||||
QStringList list = GuiUtil::BrowseForFiles("component", tr("Select components"), tr("Components (*.json)"),
|
||||
APPLICATION->settings()->get("CentralModsDir").toString(), this->parentWidget());
|
||||
|
||||
if (!list.isEmpty()) {
|
||||
if (!m_profile->installComponents(list)) {
|
||||
QMessageBox::warning(this, tr("Failed to import components"),
|
||||
tr("Some components could not be imported. Check logs for details"));
|
||||
}
|
||||
}
|
||||
|
||||
updateButtons();
|
||||
}
|
||||
|
||||
void VersionPage::on_actionAdd_Agents_triggered()
|
||||
{
|
||||
|
@ -1,7 +1,11 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
// SPDX-FileCopyrightText: 2022-2023 Sefa Eyeoglu <contact@scrumplex.net>
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-only AND Apache-2.0
|
||||
|
||||
/*
|
||||
* Prism Launcher - Minecraft Launcher
|
||||
* Copyright (c) 2022 Jamie Mansfield <jmansfield@cadixdev.org>
|
||||
* Copyright (C) 2022-2023 Sefa Eyeoglu <contact@scrumplex.net>
|
||||
* Copyright (C) 2022 TheKodeToad <TheKodeToad@proton.me>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
@ -86,6 +90,7 @@ private slots:
|
||||
void on_actionMove_down_triggered();
|
||||
void on_actionAdd_to_Minecraft_jar_triggered();
|
||||
void on_actionReplace_Minecraft_jar_triggered();
|
||||
void on_actionImport_Components_triggered();
|
||||
void on_actionAdd_Agents_triggered();
|
||||
void on_actionRevert_triggered();
|
||||
void on_actionEdit_triggered();
|
||||
|
@ -108,6 +108,7 @@
|
||||
<addaction name="actionReplace_Minecraft_jar"/>
|
||||
<addaction name="actionAdd_Agents"/>
|
||||
<addaction name="actionAdd_Empty"/>
|
||||
<addaction name="actionImport_Components"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionMinecraftFolder"/>
|
||||
<addaction name="actionLibrariesFolder"/>
|
||||
@ -226,10 +227,10 @@
|
||||
</action>
|
||||
<action name="actionAdd_Agents">
|
||||
<property name="text">
|
||||
<string>Add Agents</string>
|
||||
<string>Add Agents</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Add Java agents.</string>
|
||||
<string>Add Java agents.</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionAdd_Empty">
|
||||
@ -272,6 +273,14 @@
|
||||
<string>Open the instance's local libraries folder.</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionImport_Components">
|
||||
<property name="text">
|
||||
<string>Import Components</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Import existing component JSON files.</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
|
@ -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&);
|
||||
|
46
launcher/ui/pages/modplatform/ResourcePackModel.cpp
Normal file
46
launcher/ui/pages/modplatform/ResourcePackModel.cpp
Normal 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
|
43
launcher/ui/pages/modplatform/ResourcePackModel.h
Normal file
43
launcher/ui/pages/modplatform/ResourcePackModel.h
Normal 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
|
46
launcher/ui/pages/modplatform/ResourcePackPage.cpp
Normal file
46
launcher/ui/pages/modplatform/ResourcePackPage.cpp
Normal 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
|
52
launcher/ui/pages/modplatform/ResourcePackPage.h
Normal file
52
launcher/ui/pages/modplatform/ResourcePackPage.h
Normal 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
|
46
launcher/ui/pages/modplatform/ShaderPackModel.cpp
Normal file
46
launcher/ui/pages/modplatform/ShaderPackModel.cpp
Normal 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
|
43
launcher/ui/pages/modplatform/ShaderPackModel.h
Normal file
43
launcher/ui/pages/modplatform/ShaderPackModel.h
Normal 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
|
54
launcher/ui/pages/modplatform/ShaderPackPage.cpp
Normal file
54
launcher/ui/pages/modplatform/ShaderPackPage.cpp
Normal 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
|
54
launcher/ui/pages/modplatform/ShaderPackPage.h
Normal file
54
launcher/ui/pages/modplatform/ShaderPackPage.h
Normal 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
|
84
launcher/ui/pages/modplatform/TexturePackModel.cpp
Normal file
84
launcher/ui/pages/modplatform/TexturePackModel.cpp
Normal 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
|
27
launcher/ui/pages/modplatform/TexturePackModel.h
Normal file
27
launcher/ui/pages/modplatform/TexturePackModel.h
Normal 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
|
50
launcher/ui/pages/modplatform/TexturePackPage.h
Normal file
50
launcher/ui/pages/modplatform/TexturePackPage.h
Normal 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
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Reference in New Issue
Block a user