Code spaghetti and more chaos

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
This commit is contained in:
Trial97 2024-01-27 22:47:28 +02:00
parent 4cd236ed80
commit 7317105e4d
No known key found for this signature in database
GPG Key ID: 55EF5DA53DB36318
21 changed files with 613 additions and 391 deletions

View File

@ -110,6 +110,7 @@ QHash<int, QByteArray> BaseVersionList::roleNames() const
roles.insert(TypeRole, "type"); roles.insert(TypeRole, "type");
roles.insert(BranchRole, "branch"); roles.insert(BranchRole, "branch");
roles.insert(PathRole, "path"); roles.insert(PathRole, "path");
roles.insert(AliasRole, "alias");
roles.insert(ArchitectureRole, "architecture"); roles.insert(ArchitectureRole, "architecture");
return roles; return roles;
} }

View File

@ -48,6 +48,7 @@ class BaseVersionList : public QAbstractListModel {
TypeRole, TypeRole,
BranchRole, BranchRole,
PathRole, PathRole,
AliasRole,
ArchitectureRole, ArchitectureRole,
SortRole SortRole
}; };

View File

@ -437,6 +437,11 @@ set(JAVA_SOURCES
java/download/ArchiveJavaDownloader.h java/download/ArchiveJavaDownloader.h
java/download/ManifestJavaDownloader.cpp java/download/ManifestJavaDownloader.cpp
java/download/ManifestJavaDownloader.h java/download/ManifestJavaDownloader.h
ui/java/JavaDownload.h
ui/java/JavaDownload.cpp
ui/java/ListModel.h
ui/java/ListModel.cpp
) )
set(TRANSLATIONS_SOURCES set(TRANSLATIONS_SOURCES
@ -1107,8 +1112,6 @@ SET(LAUNCHER_SOURCES
ui/instanceview/InstanceDelegate.h ui/instanceview/InstanceDelegate.h
ui/instanceview/VisualGroup.cpp ui/instanceview/VisualGroup.cpp
ui/instanceview/VisualGroup.h ui/instanceview/VisualGroup.h
JavaDownloader.cpp
JavaDownloader.h
) )
if (NOT Apple) if (NOT Apple)
@ -1189,6 +1192,7 @@ qt_wrap_ui(LAUNCHER_UI
ui/dialogs/ScrollMessageBox.ui ui/dialogs/ScrollMessageBox.ui
ui/dialogs/BlockedModsDialog.ui ui/dialogs/BlockedModsDialog.ui
ui/dialogs/ChooseProviderDialog.ui ui/dialogs/ChooseProviderDialog.ui
ui/java/JavaDownload.ui
) )
qt_wrap_ui(PRISM_UPDATE_UI qt_wrap_ui(PRISM_UPDATE_UI

View File

@ -1,332 +0,0 @@
#include "JavaDownloader.h"
#include <QMessageBox>
#include <QPushButton>
#include <memory>
#include <utility>
#include "Application.h"
#include "FileSystem.h"
#include "InstanceList.h"
#include "Json.h"
#include "MMCZip.h"
#include "SysInfo.h"
#include "net/ChecksumValidator.h"
#include "net/NetJob.h"
#include "ui/dialogs/ProgressDialog.h"
// Quick & dirty struct to store files
struct File {
QString path;
QString url;
QByteArray hash;
bool isExec;
};
void JavaDownloader::executeTask()
{
auto OS = m_OS;
auto isLegacy = m_isLegacy;
downloadMojangJavaList(OS, isLegacy);
}
void JavaDownloader::downloadMojangJavaList(const QString& OS, bool isLegacy)
{
auto netJob = makeShared<NetJob>(QString("JRE::QueryVersions"), APPLICATION->network());
auto response = std::make_shared<QByteArray>();
setStatus(tr("Querying mojang meta"));
netJob->addNetAction(Net::Download::makeByteArray(
QUrl("https://piston-meta.mojang.com/v1/products/java-runtime/2ec0cc96c44e5a76b9c8b7c39df7210883d12871/all.json"), response));
connect(this, &Task::aborted, [isLegacy] {
QDir(FS::PathCombine(QCoreApplication::applicationDirPath(), "java", (isLegacy ? "java-legacy" : "java-current")))
.removeRecursively();
});
connect(netJob.get(), &NetJob::finished, [netJob, response, this] {
// delete so that it's not called on a deleted job
// FIXME: is this needed? qt should handle this
disconnect(this, &Task::aborted, netJob.get(), &NetJob::abort);
});
connect(netJob.get(), &NetJob::progress, this, &JavaDownloader::progress);
connect(netJob.get(), &NetJob::failed, this, &JavaDownloader::emitFailed);
connect(this, &Task::aborted, netJob.get(), &NetJob::abort);
connect(netJob.get(), &NetJob::succeeded, [response, OS, isLegacy, this, netJob] {
QJsonParseError parse_error{};
QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error);
if (parse_error.error != QJsonParseError::NoError) {
qWarning() << "Error while parsing JSON response at " << parse_error.offset << " reason: " << parse_error.errorString();
qWarning() << *response;
return;
}
auto versionArray = Json::ensureArray(Json::ensureObject(doc.object(), OS), isLegacy ? "jre-legacy" : "java-runtime-gamma");
if (!versionArray.empty()) {
parseMojangManifest(isLegacy, versionArray);
} else {
// mojang does not have a JRE for us, let's get azul zulu
downloadAzulMeta(OS, isLegacy, netJob.get());
}
});
netJob->start();
}
void JavaDownloader::parseMojangManifest(bool isLegacy, const QJsonArray& versionArray)
{
setStatus(tr("Downloading Java from Mojang"));
auto url = Json::ensureString(Json::ensureObject(Json::ensureObject(versionArray[0]), "manifest"), "url");
auto download = makeShared<NetJob>(QString("JRE::DownloadJava"), APPLICATION->network());
auto files = std::make_shared<QByteArray>();
download->addNetAction(Net::Download::makeByteArray(QUrl(url), files));
connect(download.get(), &NetJob::finished,
[download, files, this] { disconnect(this, &Task::aborted, download.get(), &NetJob::abort); });
connect(download.get(), &NetJob::progress, this, &JavaDownloader::progress);
connect(download.get(), &NetJob::failed, this, &JavaDownloader::emitFailed);
connect(this, &Task::aborted, download.get(), &NetJob::abort);
connect(download.get(), &NetJob::succeeded, [files, isLegacy, this] {
QJsonParseError parse_error{};
QJsonDocument doc = QJsonDocument::fromJson(*files, &parse_error);
if (parse_error.error != QJsonParseError::NoError) {
qWarning() << "Error while parsing JSON response at " << parse_error.offset << " reason: " << parse_error.errorString();
qWarning() << *files;
return;
}
downloadMojangJava(isLegacy, doc);
});
download->start();
}
void JavaDownloader::downloadMojangJava(bool isLegacy, const QJsonDocument& doc)
{ // valid json doc, begin making jre spot
auto output = FS::PathCombine(QCoreApplication::applicationDirPath(), QString("java"), (isLegacy ? "java-legacy" : "java-current"));
FS::ensureFolderPathExists(output);
std::vector<File> toDownload;
auto list = Json::ensureObject(Json::ensureObject(doc.object()), "files");
for (const auto& paths : list.keys()) {
auto file = FS::PathCombine(output, paths);
const QJsonObject& meta = Json::ensureObject(list, paths);
auto type = Json::ensureString(meta, "type");
if (type == "directory") {
FS::ensureFolderPathExists(file);
} else if (type == "link") {
// this is linux only !
auto path = Json::ensureString(meta, "target");
if (!path.isEmpty()) {
auto target = FS::PathCombine(file, "../" + path);
QFile(target).link(file);
}
} else if (type == "file") {
// TODO download compressed version if it exists ?
auto raw = Json::ensureObject(Json::ensureObject(meta, "downloads"), "raw");
auto isExec = Json::ensureBoolean(meta, "executable", false);
auto url = Json::ensureString(raw, "url");
if (!url.isEmpty() && QUrl(url).isValid()) {
auto f = File{ file, url, QByteArray::fromHex(Json::ensureString(raw, "sha1").toLatin1()), isExec };
toDownload.push_back(f);
}
}
}
auto elementDownload = new NetJob("JRE::FileDownload", APPLICATION->network());
for (const auto& file : toDownload) {
auto dl = Net::Download::makeFile(file.url, file.path);
if (!file.hash.isEmpty()) {
dl->addValidator(new Net::ChecksumValidator(QCryptographicHash::Sha1, file.hash));
}
if (file.isExec) {
connect(dl.get(), &Net::Download::succeeded,
[file] { QFile(file.path).setPermissions(QFile(file.path).permissions() | QFileDevice::Permissions(0x1111)); });
}
elementDownload->addNetAction(dl);
}
connect(elementDownload, &NetJob::finished, [elementDownload, this] {
disconnect(this, &Task::aborted, elementDownload, &NetJob::abort);
elementDownload->deleteLater();
});
connect(elementDownload, &NetJob::progress, this, &JavaDownloader::progress);
connect(elementDownload, &NetJob::failed, this, &JavaDownloader::emitFailed);
connect(this, &Task::aborted, elementDownload, &NetJob::abort);
connect(elementDownload, &NetJob::succeeded, [this] { emitSucceeded(); });
elementDownload->start();
}
void JavaDownloader::downloadAzulMeta(const QString& OS, bool isLegacy, const NetJob* netJob)
{
setStatus(tr("Querying Azul meta"));
QString javaVersion = isLegacy ? QString("8.0") : QString("17.0");
QString azulOS;
QString arch;
QString bitness;
mojangOStoAzul(OS, azulOS, arch, bitness);
auto metaResponse = std::make_shared<QByteArray>();
auto downloadJob = makeShared<NetJob>(QString("JRE::QueryAzulMeta"), APPLICATION->network());
downloadJob->addNetAction(
Net::Download::makeByteArray(QString("https://api.azul.com/zulu/download/community/v1.0/bundles/?"
"java_version=%1"
"&os=%2"
"&arch=%3"
"&hw_bitness=%4"
"&ext=zip" // as a zip for all os, even linux NOTE !! Linux ARM is .deb or .tar.gz only !!
"&bundle_type=jre" // jre only
"&latest=true" // only get the one latest entry
)
.arg(javaVersion, azulOS, arch, bitness),
metaResponse));
connect(downloadJob.get(), &NetJob::finished,
[downloadJob, metaResponse, this] { disconnect(this, &Task::aborted, downloadJob.get(), &NetJob::abort); });
connect(this, &Task::aborted, downloadJob.get(), &NetJob::abort);
connect(netJob, &NetJob::failed, this, &JavaDownloader::emitFailed);
connect(downloadJob.get(), &NetJob::progress, this, &JavaDownloader::progress);
connect(downloadJob.get(), &NetJob::succeeded, [metaResponse, isLegacy, this] {
QJsonParseError parse_error{};
QJsonDocument doc = QJsonDocument::fromJson(*metaResponse, &parse_error);
if (parse_error.error != QJsonParseError::NoError) {
qWarning() << "Error while parsing JSON response at " << parse_error.offset << " reason: " << parse_error.errorString();
qWarning() << *metaResponse;
return;
}
auto array = Json::ensureArray(doc.array());
if (!array.empty()) {
downloadAzulJava(isLegacy, array);
} else {
emitFailed(tr("No suitable JRE found"));
}
});
downloadJob->start();
}
void JavaDownloader::mojangOStoAzul(const QString& OS, QString& azulOS, QString& arch, QString& bitness)
{
if (OS == "mac-os-arm64") {
// macos arm64
azulOS = "macos";
arch = "arm";
bitness = "64";
} else if (OS == "linux-arm64") {
// linux arm64
azulOS = "linux";
arch = "arm";
bitness = "64";
} else if (OS == "linux-arm") {
// linux arm (32)
azulOS = "linux";
arch = "arm";
bitness = "32";
} else if (OS == "linux") {
// linux x86 64 (used for debugging, should never reach here)
azulOS = "linux";
arch = "x86";
bitness = "64";
}
}
void JavaDownloader::downloadAzulJava(bool isLegacy, const QJsonArray& array)
{ // JRE found ! download the zip
setStatus(tr("Downloading Java from Azul"));
auto downloadURL = QUrl(array[0].toObject()["url"].toString());
auto download = new NetJob(QString("JRE::DownloadJava"), APPLICATION->network());
auto path = APPLICATION->instances()->getStagedInstancePath();
auto temp = FS::PathCombine(path, "azulJRE.zip");
download->addNetAction(Net::Download::makeFile(downloadURL, temp));
connect(download, &NetJob::finished, [download, this] {
disconnect(this, &Task::aborted, download, &NetJob::abort);
download->deleteLater();
});
connect(download, &NetJob::aborted, [path] { APPLICATION->instances()->destroyStagingPath(path); });
connect(download, &NetJob::progress, this, &JavaDownloader::progress);
connect(download, &NetJob::failed, this, [this, path](QString reason) {
APPLICATION->instances()->destroyStagingPath(path);
emitFailed(std::move(reason));
});
connect(this, &Task::aborted, download, &NetJob::abort);
connect(download, &NetJob::succeeded, [isLegacy, temp, downloadURL, path, this] {
setStatus(tr("Extracting java"));
auto output = FS::PathCombine(QCoreApplication::applicationDirPath(), "java", isLegacy ? "java-legacy" : "java-current");
// This should do all of the extracting and creating folders
MMCZip::extractDir(temp, downloadURL.fileName().chopped(4), output);
APPLICATION->instances()->destroyStagingPath(path);
emitSucceeded();
});
download->start();
}
void JavaDownloader::showPrompts(QWidget* parent)
{
QString sys = SysInfo::currentSystem();
if (sys == "osx") {
sys = "mac-os";
}
QString arch = SysInfo::useQTForArch();
QString version;
if (sys == "windows") {
if (arch == "x86_64") {
version = "windows-x64";
} else if (arch == "i386") {
version = "windows-x86";
} else {
// Unknown, maybe arm, appending arch for downloader
version = "windows-" + arch;
}
} else if (sys == "mac-os") {
if (arch == "arm64") {
version = "mac-os-arm64";
} else {
version = "mac-os";
}
} else if (sys == "linux") {
if (arch == "x86_64") {
version = "linux";
} else {
// will work for i386, and arm(64)
version = "linux-" + arch;
}
} else {
// ? ? ? ? ? unknown os, at least it won't have a java version on mojang or azul, display warning
QMessageBox::warning(parent, tr("Unknown OS"),
tr("The OS you are running is not supported by Mojang or Azul. Please install Java manually."));
return;
}
// Selection using QMessageBox for java 8 or 17
QMessageBox box(
QMessageBox::Icon::Question, tr("Java version"),
tr("Do you want to download Java version 8 or 17?\n Java 8 is recommended for older Minecraft versions, below 1.17\n Java 17 "
"is recommended for newer Minecraft versions, starting from 1.17"),
QMessageBox::NoButton, parent);
auto yes = box.addButton("Java 17", QMessageBox::AcceptRole);
auto no = box.addButton("Java 8", QMessageBox::AcceptRole);
auto both = box.addButton(tr("Download both"), QMessageBox::AcceptRole);
auto cancel = box.addButton(QMessageBox::Cancel);
if (QFileInfo::exists(FS::PathCombine(QCoreApplication::applicationDirPath(), QString("java"), "java-legacy"))) {
no->setEnabled(false);
}
if (QFileInfo::exists(FS::PathCombine(QCoreApplication::applicationDirPath(), QString("java"), "java-current"))) {
yes->setEnabled(false);
}
if (!yes->isEnabled() || !no->isEnabled()) {
both->setEnabled(false);
}
if (!yes->isEnabled() && !no->isEnabled()) {
QMessageBox::information(parent, tr("Already installed!"), tr("Both versions of Java are already installed!"));
return;
}
box.exec();
if (box.clickedButton() == nullptr || box.clickedButton() == cancel) {
return;
}
bool isLegacy = box.clickedButton() == no;
auto down = new JavaDownloader(isLegacy, version);
ProgressDialog dialog(parent);
dialog.setSkipButton(true, tr("Abort"));
bool finished_successfully = dialog.execWithTask(down);
// Run another download task for the other option as well!
if (finished_successfully && box.clickedButton() == both) {
auto dwn = new JavaDownloader(false, version);
ProgressDialog dg(parent);
dg.setSkipButton(true, tr("Abort"));
dg.execWithTask(dwn);
}
}

View File

@ -1,28 +0,0 @@
#pragma once
#include <QString>
#include "net/NetJob.h"
#include "tasks/Task.h"
class JavaDownloader : public Task {
Q_OBJECT
public:
/*Downloads the java to the runtimes folder*/
explicit JavaDownloader(bool isLegacy, const QString& OS) : m_isLegacy(isLegacy), m_OS(OS) {}
void executeTask() override;
[[nodiscard]] bool canAbort() const override { return true; }
static void showPrompts(QWidget* parent = nullptr);
private:
bool m_isLegacy;
const QString& m_OS;
void downloadMojangJavaList(const QString& OS, bool isLegacy);
void parseMojangManifest(bool isLegacy, const QJsonArray& versionArray);
void downloadMojangJava(bool isLegacy, const QJsonDocument& doc);
static void mojangOStoAzul(const QString& OS, QString& azulOS, QString& arch, QString& bitness);
void downloadAzulMeta(const QString& OS, bool isLegacy, const NetJob* netJob);
void downloadAzulJava(bool isLegacy, const QJsonArray& array);
};

View File

@ -17,13 +17,7 @@ bool rosettaDetect()
if (sysctlbyname("sysctl.proc_translated", &ret, &size, NULL, 0) == -1) { if (sysctlbyname("sysctl.proc_translated", &ret, &size, NULL, 0) == -1) {
return false; return false;
} }
if (ret == 0) { return ret == 1;
return false;
}
if (ret == 1) {
return true;
}
return false;
} }
#endif #endif
@ -47,7 +41,6 @@ QString currentSystem()
QString useQTForArch() QString useQTForArch()
{ {
auto qtArch = QSysInfo::currentCpuArchitecture();
#if defined(Q_OS_MACOS) && !defined(Q_PROCESSOR_ARM) #if defined(Q_OS_MACOS) && !defined(Q_PROCESSOR_ARM)
if (rosettaDetect()) { if (rosettaDetect()) {
return "arm64"; return "arm64";
@ -55,7 +48,7 @@ QString useQTForArch()
return "x86_64"; return "x86_64";
} }
#endif #endif
return qtArch; return QSysInfo::currentCpuArchitecture();
} }
int suitableMaxMem() int suitableMaxMem()
@ -71,4 +64,36 @@ int suitableMaxMem()
return maxMemoryAlloc; return maxMemoryAlloc;
} }
QString getSupportedJavaArchitecture()
{
auto sys = currentSystem();
auto arch = useQTForArch();
if (sys == "windows") {
if (arch == "x86_64")
return "windows-x64";
if (arch == "i386")
return "windows-x86";
// Unknown, maybe arm, appending arch
return "windows-" + arch;
}
if (sys == "osx") {
if (arch == "arm64")
return "mac-os-arm64";
if (arch.contains("64"))
return "mac-os-64";
if (arch.contains("86"))
return "mac-os-86";
// Unknown, maybe something new, appending arch
return "mac-os-" + arch;
} else if (sys == "linux") {
if (arch == "x86_64")
return "linux-x64";
if (arch == "i386")
return "linux-x86";
// will work for arm32 arm(64)
return "linux-" + arch;
}
return {};
}
} // namespace SysInfo } // namespace SysInfo

View File

@ -3,5 +3,6 @@
namespace SysInfo { namespace SysInfo {
QString currentSystem(); QString currentSystem();
QString useQTForArch(); QString useQTForArch();
QString getSupportedJavaArchitecture();
int suitableMaxMem(); int suitableMaxMem();
} // namespace SysInfo } // namespace SysInfo

View File

@ -118,6 +118,8 @@ QVariant VersionProxyModel::headerData(int section, Qt::Orientation orientation,
return tr("Architecture"); return tr("Architecture");
case Path: case Path:
return tr("Path"); return tr("Path");
case Alias:
return tr("Alias");
case Time: case Time:
return tr("Released"); return tr("Released");
} }
@ -135,6 +137,8 @@ QVariant VersionProxyModel::headerData(int section, Qt::Orientation orientation,
return tr("CPU Architecture"); return tr("CPU Architecture");
case Path: case Path:
return tr("Filesystem path to this version"); return tr("Filesystem path to this version");
case Alias:
return tr("The alternative name of the java version");
case Time: case Time:
return tr("Release date of this version"); return tr("Release date of this version");
} }
@ -169,6 +173,8 @@ QVariant VersionProxyModel::data(const QModelIndex& index, int role) const
return sourceModel()->data(parentIndex, BaseVersionList::ArchitectureRole); return sourceModel()->data(parentIndex, BaseVersionList::ArchitectureRole);
case Path: case Path:
return sourceModel()->data(parentIndex, BaseVersionList::PathRole); return sourceModel()->data(parentIndex, BaseVersionList::PathRole);
case Alias:
return sourceModel()->data(parentIndex, BaseVersionList::AliasRole);
case Time: case Time:
return sourceModel()->data(parentIndex, Meta::VersionList::TimeRole).toDate(); return sourceModel()->data(parentIndex, Meta::VersionList::TimeRole).toDate();
default: default:
@ -314,6 +320,9 @@ void VersionProxyModel::setSourceModel(QAbstractItemModel* replacingRaw)
if (roles.contains(BaseVersionList::PathRole)) { if (roles.contains(BaseVersionList::PathRole)) {
m_columns.push_back(Path); m_columns.push_back(Path);
} }
if (roles.contains(BaseVersionList::AliasRole)) {
m_columns.push_back(Alias);
}
if (roles.contains(Meta::VersionList::TimeRole)) { if (roles.contains(Meta::VersionList::TimeRole)) {
m_columns.push_back(Time); m_columns.push_back(Time);
} }

View File

@ -9,7 +9,7 @@ class VersionFilterModel;
class VersionProxyModel : public QAbstractProxyModel { class VersionProxyModel : public QAbstractProxyModel {
Q_OBJECT Q_OBJECT
public: public:
enum Column { Name, ParentVersion, Branch, Type, Architecture, Path, Time }; enum Column { Name, ParentVersion, Branch, Type, Architecture, Path, Time, Alias };
using FilterMap = QHash<BaseVersionList::ModelRoles, std::shared_ptr<Filter>>; using FilterMap = QHash<BaseVersionList::ModelRoles, std::shared_ptr<Filter>>;
public: public:

View File

@ -62,7 +62,7 @@ MetaPtr parseJavaMeta(const QJsonObject& in)
} }
if (in.contains("version")) { if (in.contains("version")) {
auto obj = Json::requireObject(in, "checksum"); auto obj = Json::requireObject(in, "version");
auto name = Json::ensureString(obj, "name", ""); auto name = Json::ensureString(obj, "name", "");
auto major = Json::ensureInteger(obj, "major", 0); auto major = Json::ensureInteger(obj, "major", 0);
auto minor = Json::ensureInteger(obj, "minor", 0); auto minor = Json::ensureInteger(obj, "minor", 0);

View File

@ -113,19 +113,20 @@ bool JavaVersion::operator>(const JavaVersion& rhs)
JavaVersion::JavaVersion(int major, int minor, int security, int build, QString name) JavaVersion::JavaVersion(int major, int minor, int security, int build, QString name)
: m_major(major), m_minor(minor), m_security(security), m_name(name), m_parseable(true) : m_major(major), m_minor(minor), m_security(security), m_name(name), m_parseable(true)
{ {
QStringList versions;
if (build != 0) { if (build != 0) {
m_prerelease = QString::number(build); m_prerelease = QString::number(build);
m_string = m_prerelease; versions.push_front(m_prerelease);
} }
if (m_security != 0) if (m_security != 0)
m_string = QString::number(m_security) + "." + m_string; versions.push_front(QString::number(m_security));
else if (!m_string.isEmpty()) { else if (!versions.isEmpty())
m_string = "0." + m_string; versions.push_front("0");
}
if (m_minor != 0) if (m_minor != 0)
m_string = QString::number(m_minor) + "." + m_string; versions.push_front(QString::number(m_minor));
else if (!m_string.isEmpty()) { else if (!versions.isEmpty())
m_string = "0." + m_string; versions.push_front("0");
} versions.push_front(QString::number(m_major));
m_string = QString::number(m_major) + "." + m_string; m_string = versions.join(".");
} }

View File

@ -43,7 +43,7 @@ void ArchiveJavaDownloader::executeTask()
if (m_checksum_type == "sha256") { if (m_checksum_type == "sha256") {
hashType = QCryptographicHash::Algorithm::Sha256; hashType = QCryptographicHash::Algorithm::Sha256;
} }
action->addValidator(new Net::ChecksumValidator(hashType, m_checksum_hash.toLatin1())); action->addValidator(new Net::ChecksumValidator(hashType, QByteArray::fromHex(m_checksum_hash.toUtf8())));
} }
download->addNetAction(action); download->addNetAction(action);
auto fullPath = entry->getFullPath(); auto fullPath = entry->getFullPath();

View File

@ -46,7 +46,7 @@ void ManifestJavaDownloader::executeTask()
if (m_checksum_type == "sha256") { if (m_checksum_type == "sha256") {
hashType = QCryptographicHash::Algorithm::Sha256; hashType = QCryptographicHash::Algorithm::Sha256;
} }
action->addValidator(new Net::ChecksumValidator(hashType, m_checksum_hash.toLatin1())); action->addValidator(new Net::ChecksumValidator(hashType, QByteArray::fromHex(m_checksum_hash.toUtf8())));
} }
download->addNetAction(action); download->addNetAction(action);

View File

@ -0,0 +1,103 @@
// SPDX-License-Identifier: GPL-3.0-only
/*
* Prism Launcher - Minecraft Launcher
* Copyright (c) 2024 Trial97 <alexandru.tripon97@gmail.com>
*
* 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/>.
*/
#include "JavaDownload.h"
#include <qdialogbuttonbox.h>
#include <qlogging.h>
#include <qmessagebox.h>
#include <qpushbutton.h>
#include <memory>
#include "Application.h"
#include "BaseVersionList.h"
#include "FileSystem.h"
#include "QObjectPtr.h"
#include "SysInfo.h"
#include "java/JavaInstallList.h"
#include "java/download/ArchiveJavaDownloader.h"
#include "java/download/ManifestJavaDownloader.h"
#include "meta/Index.h"
#include "meta/Version.h"
#include "ui/dialogs/ProgressDialog.h"
#include "ui/java/ListModel.h"
#include "ui_JavaDownload.h"
JavaDownload::JavaDownload(QWidget* parent) : QDialog(parent), ui(new Ui::JavaDownload)
{
ui->setupUi(this);
ui->widget->initialize(new Java::JavaBaseVersionList("net.minecraft.java"));
ui->widget->selectCurrent();
connect(ui->widget, &VersionSelectWidget::selectedVersionChanged, this, &JavaDownload::setSelectedVersion);
auto reset = ui->buttonBox->button(QDialogButtonBox::Reset);
connect(reset, &QPushButton::clicked, this, &JavaDownload::refresh);
connect(ui->widget_2, &VersionSelectWidget::selectedVersionChanged, this, &JavaDownload::setSelectedVersion2);
}
JavaDownload::~JavaDownload()
{
delete ui;
}
void JavaDownload::setSelectedVersion(BaseVersion::Ptr version)
{
if (!version)
return;
auto dcast = std::dynamic_pointer_cast<Meta::Version>(version);
if (!dcast) {
return;
}
ui->widget_2->initialize(new Java::InstallList(dcast, this));
ui->widget_2->selectCurrent();
}
void JavaDownload::setSelectedVersion2(BaseVersion::Ptr version)
{
if (!version)
return;
m_selectedVersion = std::dynamic_pointer_cast<Java::JavaRuntime2>(ui->widget_2->selectedVersion());
}
void JavaDownload::accept()
{
if (!m_selectedVersion) {
m_selectedVersion = std::dynamic_pointer_cast<Java::JavaRuntime2>(ui->widget_2->selectedVersion());
qDebug() << "=========?" << (ui->widget_2->selectedVersion() != nullptr);
}
if (!m_selectedVersion) {
qDebug() << "faillllllllllllllllllllllllllll";
return;
}
auto meta = m_selectedVersion->meta;
Task::Ptr task;
auto final_path = FS::PathCombine(APPLICATION->dataRoot(), "java", meta->name);
qDebug() << "===============>>=>>" << meta->checksumType << meta->checksumHash;
switch (meta->downloadType) {
case JavaRuntime::DownloadType::Manifest:
task = makeShared<ManifestJavaDownloader>(meta->url, final_path, meta->checksumType, meta->checksumHash);
break;
case JavaRuntime::DownloadType::Archive:
task = makeShared<ArchiveJavaDownloader>(meta->url, final_path, meta->checksumType, meta->checksumHash);
break;
}
ProgressDialog pg(this);
pg.execWithTask(task.get());
QDialog::accept();
}
void JavaDownload::refresh()
{
ui->widget->loadList();
}

View File

@ -0,0 +1,48 @@
// SPDX-License-Identifier: GPL-3.0-only
/*
* Prism Launcher - Minecraft Launcher
* Copyright (c) 2024 Trial97 <alexandru.tripon97@gmail.com>
*
* 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/>.
*/
#pragma once
#include <QDialog>
#include "BaseVersion.h"
#include "ui/java/ListModel.h"
namespace Ui {
class JavaDownload;
}
class JavaDownload : public QDialog {
Q_OBJECT
public:
explicit JavaDownload(QWidget* parent = 0);
~JavaDownload();
void accept();
public slots:
void refresh();
protected slots:
void setSelectedVersion(BaseVersion::Ptr version);
void setSelectedVersion2(BaseVersion::Ptr version);
private:
Ui::JavaDownload* ui;
Java::JavaRuntimePtr m_selectedVersion;
};

View File

@ -0,0 +1,100 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>JavaDownload</class>
<widget class="QDialog" name="JavaDownload">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>821</width>
<height>593</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout" stretch="1,5">
<item>
<widget class="QGroupBox" name="majorGB">
<property name="title">
<string>Major</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="VersionSelectWidget" name="widget" native="true"/>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="runtimeGB">
<property name="title">
<string>Runtime</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="VersionSelectWidget" name="widget_2" native="true"/>
</item>
</layout>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok|QDialogButtonBox::Retry</set>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>VersionSelectWidget</class>
<extends>QWidget</extends>
<header>ui/widgets/VersionSelectWidget.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>JavaDownload</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>JavaDownload</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -0,0 +1,154 @@
// SPDX-License-Identifier: GPL-3.0-only
/*
* Prism Launcher - Minecraft Launcher
* Copyright (c) 2024 Trial97 <alexandru.tripon97@gmail.com>
*
* 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/>.
*/
#include "ListModel.h"
#include <qlogging.h>
#include <memory>
#include "BaseVersionList.h"
#include "StringUtils.h"
#include "SysInfo.h"
namespace Java {
InstallList::InstallList(Meta::Version::Ptr version, QObject* parent) : BaseVersionList(parent), m_version(version)
{
if (version->isLoaded())
sortVersions();
}
Task::Ptr InstallList::getLoadTask()
{
m_version->load(Net::Mode::Online);
auto task = m_version->getCurrentTask();
connect(task.get(), &Task::finished, this, &InstallList::sortVersions);
return task;
}
const BaseVersion::Ptr InstallList::at(int i) const
{
return m_vlist.at(i);
}
bool InstallList::isLoaded()
{
return m_version->isLoaded();
}
int InstallList::count() const
{
return m_vlist.count();
}
QVariant InstallList::data(const QModelIndex& index, int role) const
{
if (!index.isValid())
return QVariant();
if (index.row() > count())
return QVariant();
auto version = (m_vlist[index.row()]);
switch (role) {
case SortRole:
return -index.row();
case VersionPointerRole:
return QVariant::fromValue(std::dynamic_pointer_cast<BaseVersion>(m_vlist[index.row()]));
case VersionIdRole:
return version->descriptor();
case VersionRole:
return version->meta->version.toString();
case RecommendedRole:
return version->meta->recommended;
case AliasRole:
return version->meta->name;
case ArchitectureRole:
return version->meta->vendor;
default:
return QVariant();
}
}
BaseVersionList::RoleList InstallList::providesRoles() const
{
return { VersionPointerRole, VersionIdRole, VersionRole, RecommendedRole, AliasRole, ArchitectureRole };
}
bool sortJavas(BaseVersion::Ptr left, BaseVersion::Ptr right)
{
auto rleft = std::dynamic_pointer_cast<JavaRuntime2>(right);
auto rright = std::dynamic_pointer_cast<JavaRuntime2>(left);
return (*rleft) > (*rright);
}
void InstallList::sortVersions()
{
QString versionStr = SysInfo::getSupportedJavaArchitecture();
beginResetModel();
auto runtimes = m_version->data()->runtimes;
if (versionStr.isEmpty() || !runtimes.contains(versionStr)) {
return;
}
auto javaruntimes = runtimes.value(versionStr);
for (auto v : javaruntimes) {
m_vlist.append(std::make_shared<JavaRuntime2>(v));
}
std::sort(m_vlist.begin(), m_vlist.end(), sortJavas);
endResetModel();
}
bool JavaRuntime2::operator<(const JavaRuntime2& rhs)
{
auto id = meta->version;
if (id < rhs.meta->version) {
return true;
}
if (id > rhs.meta->version) {
return false;
}
return StringUtils::naturalCompare(meta->name, rhs.meta->name, Qt::CaseInsensitive) < 0;
}
bool JavaRuntime2::operator==(const JavaRuntime2& rhs)
{
return meta->version == rhs.meta->version && meta->name == rhs.meta->name;
}
bool JavaRuntime2::operator>(const JavaRuntime2& rhs)
{
return (!operator<(rhs)) && (!operator==(rhs));
}
bool JavaRuntime2::operator<(BaseVersion& a)
{
try {
return operator<(dynamic_cast<JavaRuntime2&>(a));
} catch (const std::bad_cast& e) {
return BaseVersion::operator<(a);
}
}
bool JavaRuntime2::operator>(BaseVersion& a)
{
try {
return operator>(dynamic_cast<JavaRuntime2&>(a));
} catch (const std::bad_cast& e) {
return BaseVersion::operator>(a);
}
}
} // namespace Java

View File

@ -0,0 +1,132 @@
// SPDX-License-Identifier: GPL-3.0-only
/*
* Prism Launcher - Minecraft Launcher
* Copyright (c) 2024 Trial97 <alexandru.tripon97@gmail.com>
*
* 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/>.
*/
#pragma once
#include <qtmetamacros.h>
#include <QAbstractListModel>
#include <QSortFilterProxyModel>
#include "java/JavaRuntime.h"
#include "meta/VersionList.h"
namespace Java {
class JavaBaseVersionList : public Meta::VersionList {
Q_OBJECT
public:
explicit JavaBaseVersionList(const QString& uid, QObject* parent = nullptr) : VersionList(uid, parent) {}
BaseVersionList::RoleList providesRoles() const { return { VersionRole, RecommendedRole, VersionPointerRole }; }
};
struct JavaRuntime2 : public BaseVersion {
JavaRuntime2() {}
JavaRuntime2(JavaRuntime::MetaPtr m) : meta(m) {}
virtual QString descriptor() override { return meta->version.toString(); }
virtual QString name() override { return meta->name; }
virtual QString typeString() const override { return meta->vendor; }
virtual bool operator<(BaseVersion& a) override;
virtual bool operator>(BaseVersion& a) override;
bool operator<(const JavaRuntime2& rhs);
bool operator==(const JavaRuntime2& rhs);
bool operator>(const JavaRuntime2& rhs);
JavaRuntime::MetaPtr meta;
};
using JavaRuntimePtr = std::shared_ptr<JavaRuntime2>;
class InstallList : public BaseVersionList {
Q_OBJECT
public:
explicit InstallList(Meta::Version::Ptr m_version, QObject* parent = 0);
Task::Ptr getLoadTask() override;
bool isLoaded() override;
const BaseVersion::Ptr at(int i) const override;
int count() const override;
void sortVersions() override;
QVariant data(const QModelIndex& index, int role) const override;
RoleList providesRoles() const override;
protected slots:
void updateListData(QList<BaseVersion::Ptr>) override {}
protected:
Meta::Version::Ptr m_version;
QList<JavaRuntimePtr> m_vlist;
};
} // namespace Java
// class FilterModel : public QSortFilterProxyModel {
// Q_OBJECT
// public:
// FilterModel(QObject* parent = Q_NULLPTR);
// enum Sorting { ByName, ByGameVersion };
// const QMap<QString, Sorting> getAvailableSortings();
// QString translateCurrentSorting();
// void setSorting(Sorting sorting);
// Sorting getCurrentSorting();
// void setSearchTerm(QString term);
// protected:
// bool filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const override;
// bool lessThan(const QModelIndex& left, const QModelIndex& right) const override;
// private:
// QMap<QString, Sorting> sortings;
// Sorting currentSorting;
// QString searchTerm;
// };
// class ListModel : public QAbstractListModel {
// Q_OBJECT
// private:
// ModpackList modpacks;
// QStringList m_failedLogos;
// QStringList m_loadingLogos;
// FTBLogoMap m_logoMap;
// QMap<QString, LogoCallback> waitingCallbacks;
// void requestLogo(QString file);
// QString translatePackType(PackType type) const;
// private slots:
// void logoFailed(QString logo);
// void logoLoaded(QString logo, QIcon out);
// public:
// ListModel(QObject* parent);
// ~ListModel();
// int rowCount(const QModelIndex& parent) const override;
// int columnCount(const QModelIndex& parent) const override;
// QVariant data(const QModelIndex& index, int role) const override;
// Qt::ItemFlags flags(const QModelIndex& index) const override;
// void fill(ModpackList modpacks);
// void addPack(Modpack modpack);
// void clear();
// void remove(int row);
// Modpack at(int row);
// void getLogo(const QString& logo, LogoCallback callback);
// };

View File

@ -36,6 +36,7 @@
#include "JavaPage.h" #include "JavaPage.h"
#include "JavaCommon.h" #include "JavaCommon.h"
#include "ui/java/JavaDownload.h"
#include "ui_JavaPage.h" #include "ui_JavaPage.h"
#include <QDir> #include <QDir>
@ -51,7 +52,6 @@
#include <FileSystem.h> #include <FileSystem.h>
#include <sys.h> #include <sys.h>
#include "Application.h" #include "Application.h"
#include "JavaDownloader.h"
#include "settings/SettingsObject.h" #include "settings/SettingsObject.h"
JavaPage::JavaPage(QWidget* parent) : QWidget(parent), ui(new Ui::JavaPage) JavaPage::JavaPage(QWidget* parent) : QWidget(parent), ui(new Ui::JavaPage)
@ -169,7 +169,8 @@ void JavaPage::on_javaTestBtn_clicked()
void JavaPage::on_javaDownloadBtn_clicked() void JavaPage::on_javaDownloadBtn_clicked()
{ {
JavaDownloader::showPrompts(this); auto jdialog = new JavaDownload(this);
jdialog->exec();
} }
void JavaPage::on_maxMemSpinBox_valueChanged([[maybe_unused]] int i) void JavaPage::on_maxMemSpinBox_valueChanged([[maybe_unused]] int i)

View File

@ -36,6 +36,7 @@
*/ */
#include "InstanceSettingsPage.h" #include "InstanceSettingsPage.h"
#include "ui/java/JavaDownload.h"
#include "ui_InstanceSettingsPage.h" #include "ui_InstanceSettingsPage.h"
#include <QDialog> #include <QDialog>
@ -53,7 +54,6 @@
#include "minecraft/auth/AccountList.h" #include "minecraft/auth/AccountList.h"
#include "FileSystem.h" #include "FileSystem.h"
#include "JavaDownloader.h"
#include "java/JavaInstallList.h" #include "java/JavaInstallList.h"
#include "java/JavaUtils.h" #include "java/JavaUtils.h"
@ -387,7 +387,8 @@ void InstanceSettingsPage::loadSettings()
void InstanceSettingsPage::on_javaDownloadBtn_clicked() void InstanceSettingsPage::on_javaDownloadBtn_clicked()
{ {
JavaDownloader::showPrompts(this); auto jdialog = new JavaDownload(this);
jdialog->exec();
} }
void InstanceSettingsPage::on_javaDetectBtn_clicked() void InstanceSettingsPage::on_javaDetectBtn_clicked()

View File

@ -13,13 +13,13 @@
#include "FileSystem.h" #include "FileSystem.h"
#include "JavaCommon.h" #include "JavaCommon.h"
#include "JavaDownloader.h"
#include "java/JavaChecker.h" #include "java/JavaChecker.h"
#include "java/JavaInstall.h" #include "java/JavaInstall.h"
#include "java/JavaInstallList.h" #include "java/JavaInstallList.h"
#include "java/JavaUtils.h" #include "java/JavaUtils.h"
#include "ui/dialogs/CustomMessageBox.h" #include "ui/dialogs/CustomMessageBox.h"
#include "ui/java/JavaDownload.h"
#include "ui/widgets/VersionSelectWidget.h" #include "ui/widgets/VersionSelectWidget.h"
#include "Application.h" #include "Application.h"
@ -274,7 +274,8 @@ void JavaSettingsWidget::on_javaBrowseBtn_clicked()
} }
void JavaSettingsWidget::on_javaDownloadBtn_clicked() void JavaSettingsWidget::on_javaDownloadBtn_clicked()
{ {
JavaDownloader::showPrompts(this); auto jdialog = new JavaDownload(this);
jdialog->exec();
} }
void JavaSettingsWidget::on_javaStatusBtn_clicked() void JavaSettingsWidget::on_javaStatusBtn_clicked()
{ {