Merge pull request #2069 from Trial97/feature/java-downloader
Feature/java downloader
This commit is contained in:
commit
eae5d70385
10
.github/workflows/build.yml
vendored
10
.github/workflows/build.yml
vendored
@ -266,23 +266,23 @@ jobs:
|
|||||||
- name: Configure CMake (macOS)
|
- name: Configure CMake (macOS)
|
||||||
if: runner.os == 'macOS' && matrix.qt_ver == 6
|
if: runner.os == 'macOS' && matrix.qt_ver == 6
|
||||||
run: |
|
run: |
|
||||||
cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_DIR }} -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DLauncher_BUILD_PLATFORM=official -DCMAKE_C_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DCMAKE_CXX_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DLauncher_QT_VERSION_MAJOR=${{ matrix.qt_ver }} -DCMAKE_OSX_ARCHITECTURES="x86_64;arm64" -G Ninja
|
cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_DIR }} -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DENABLE_JAVA_DOWNLOADER=ON -DLauncher_BUILD_PLATFORM=official -DCMAKE_C_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DCMAKE_CXX_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DLauncher_QT_VERSION_MAJOR=${{ matrix.qt_ver }} -DCMAKE_OSX_ARCHITECTURES="x86_64;arm64" -G Ninja
|
||||||
|
|
||||||
- name: Configure CMake (macOS-Legacy)
|
- name: Configure CMake (macOS-Legacy)
|
||||||
if: runner.os == 'macOS' && matrix.qt_ver == 5
|
if: runner.os == 'macOS' && matrix.qt_ver == 5
|
||||||
run: |
|
run: |
|
||||||
cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_DIR }} -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DLauncher_BUILD_PLATFORM=official -DCMAKE_C_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DCMAKE_CXX_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DLauncher_QT_VERSION_MAJOR=${{ matrix.qt_ver }} -DMACOSX_SPARKLE_UPDATE_PUBLIC_KEY="" -DMACOSX_SPARKLE_UPDATE_FEED_URL="" -G Ninja
|
cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_DIR }} -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DENABLE_JAVA_DOWNLOADER=ON -DLauncher_BUILD_PLATFORM=official -DCMAKE_C_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DCMAKE_CXX_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DLauncher_QT_VERSION_MAJOR=${{ matrix.qt_ver }} -DMACOSX_SPARKLE_UPDATE_PUBLIC_KEY="" -DMACOSX_SPARKLE_UPDATE_FEED_URL="" -G Ninja
|
||||||
|
|
||||||
- name: Configure CMake (Windows MinGW-w64)
|
- name: Configure CMake (Windows MinGW-w64)
|
||||||
if: runner.os == 'Windows' && matrix.msystem != ''
|
if: runner.os == 'Windows' && matrix.msystem != ''
|
||||||
shell: msys2 {0}
|
shell: msys2 {0}
|
||||||
run: |
|
run: |
|
||||||
cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_DIR }} -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DLauncher_BUILD_PLATFORM=official -DCMAKE_C_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DCMAKE_CXX_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DLauncher_QT_VERSION_MAJOR=6 -DCMAKE_OBJDUMP=/mingw64/bin/objdump.exe -DLauncher_BUILD_ARTIFACT=${{ matrix.name }}-Qt${{ matrix.qt_ver }} -G Ninja
|
cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_DIR }} -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DENABLE_JAVA_DOWNLOADER=ON -DLauncher_BUILD_PLATFORM=official -DCMAKE_C_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DCMAKE_CXX_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DLauncher_QT_VERSION_MAJOR=6 -DCMAKE_OBJDUMP=/mingw64/bin/objdump.exe -DLauncher_BUILD_ARTIFACT=${{ matrix.name }}-Qt${{ matrix.qt_ver }} -G Ninja
|
||||||
|
|
||||||
- name: Configure CMake (Windows MSVC)
|
- name: Configure CMake (Windows MSVC)
|
||||||
if: runner.os == 'Windows' && matrix.msystem == ''
|
if: runner.os == 'Windows' && matrix.msystem == ''
|
||||||
run: |
|
run: |
|
||||||
cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_DIR }} -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DLauncher_BUILD_PLATFORM=official -DLauncher_QT_VERSION_MAJOR=${{ matrix.qt_ver }} -DCMAKE_MSVC_RUNTIME_LIBRARY="MultiThreadedDLL" -A${{ matrix.architecture}} -DLauncher_FORCE_BUNDLED_LIBS=ON -DLauncher_BUILD_ARTIFACT=${{ matrix.name }}-Qt${{ matrix.qt_ver }}
|
cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_DIR }} -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DENABLE_JAVA_DOWNLOADER=ON -DLauncher_BUILD_PLATFORM=official -DLauncher_QT_VERSION_MAJOR=${{ matrix.qt_ver }} -DCMAKE_MSVC_RUNTIME_LIBRARY="MultiThreadedDLL" -A${{ matrix.architecture}} -DLauncher_FORCE_BUNDLED_LIBS=ON -DLauncher_BUILD_ARTIFACT=${{ matrix.name }}-Qt${{ matrix.qt_ver }}
|
||||||
# https://github.com/ccache/ccache/wiki/MS-Visual-Studio (I coudn't figure out the compiler prefix)
|
# https://github.com/ccache/ccache/wiki/MS-Visual-Studio (I coudn't figure out the compiler prefix)
|
||||||
if ("${{ env.CCACHE_VAR }}")
|
if ("${{ env.CCACHE_VAR }}")
|
||||||
{
|
{
|
||||||
@ -297,7 +297,7 @@ jobs:
|
|||||||
- name: Configure CMake (Linux)
|
- name: Configure CMake (Linux)
|
||||||
if: runner.os == 'Linux'
|
if: runner.os == 'Linux'
|
||||||
run: |
|
run: |
|
||||||
cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DLauncher_BUILD_PLATFORM=official -DCMAKE_C_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DCMAKE_CXX_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DLauncher_QT_VERSION_MAJOR=${{ matrix.qt_ver }} -DLauncher_BUILD_ARTIFACT=Linux-Qt${{ matrix.qt_ver }} -G Ninja
|
cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DENABLE_JAVA_DOWNLOADER=ON -DLauncher_BUILD_PLATFORM=official -DCMAKE_C_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DCMAKE_CXX_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DLauncher_QT_VERSION_MAJOR=${{ matrix.qt_ver }} -DLauncher_BUILD_ARTIFACT=Linux-Qt${{ matrix.qt_ver }} -G Ninja
|
||||||
|
|
||||||
##
|
##
|
||||||
# BUILD
|
# BUILD
|
||||||
|
@ -219,6 +219,19 @@ set(Launcher_SUBREDDIT_URL "https://prismlauncher.org/reddit" CACHE STRING "URL
|
|||||||
set(Launcher_FORCE_BUNDLED_LIBS OFF CACHE BOOL "Prevent using system libraries, if they are available as submodules")
|
set(Launcher_FORCE_BUNDLED_LIBS OFF CACHE BOOL "Prevent using system libraries, if they are available as submodules")
|
||||||
set(Launcher_QT_VERSION_MAJOR "6" CACHE STRING "Major Qt version to build against")
|
set(Launcher_QT_VERSION_MAJOR "6" CACHE STRING "Major Qt version to build against")
|
||||||
|
|
||||||
|
# Java downloader
|
||||||
|
set(ENABLE_JAVA_DOWNLOADER_DEFAULT ON)
|
||||||
|
|
||||||
|
# Although we recommend enabling this, we cannot guarantee binary compatibility on
|
||||||
|
# differing Linux/BSD/etc distributions. Downstream packagers should be explicitly opt-ing into this
|
||||||
|
# feature if they know it will work with their distribution.
|
||||||
|
if(UNIX AND NOT APPLE)
|
||||||
|
set(ENABLE_JAVA_DOWNLOADER_DEFAULT OFF)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Java downloader
|
||||||
|
option(ENABLE_JAVA_DOWNLOADER "Build the java downloader feature" ${ENABLE_JAVA_DOWNLOADER_DEFAULT})
|
||||||
|
|
||||||
# Native libraries
|
# Native libraries
|
||||||
if(UNIX AND APPLE)
|
if(UNIX AND APPLE)
|
||||||
set(Launcher_GLFW_LIBRARY_NAME "libglfw.dylib" CACHE STRING "Name of native glfw library")
|
set(Launcher_GLFW_LIBRARY_NAME "libglfw.dylib" CACHE STRING "Name of native glfw library")
|
||||||
|
@ -81,6 +81,9 @@ Config::Config()
|
|||||||
UPDATER_ENABLED = true;
|
UPDATER_ENABLED = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#cmakedefine01 ENABLE_JAVA_DOWNLOADER
|
||||||
|
JAVA_DOWNLOADER_ENABLED = ENABLE_JAVA_DOWNLOADER;
|
||||||
|
|
||||||
GIT_COMMIT = "@Launcher_GIT_COMMIT@";
|
GIT_COMMIT = "@Launcher_GIT_COMMIT@";
|
||||||
GIT_TAG = "@Launcher_GIT_TAG@";
|
GIT_TAG = "@Launcher_GIT_TAG@";
|
||||||
GIT_REFSPEC = "@Launcher_GIT_REFSPEC@";
|
GIT_REFSPEC = "@Launcher_GIT_REFSPEC@";
|
||||||
|
@ -67,6 +67,7 @@ class Config {
|
|||||||
QString VERSION_CHANNEL;
|
QString VERSION_CHANNEL;
|
||||||
|
|
||||||
bool UPDATER_ENABLED = false;
|
bool UPDATER_ENABLED = false;
|
||||||
|
bool JAVA_DOWNLOADER_ENABLED = false;
|
||||||
|
|
||||||
/// A short string identifying this build's platform or distribution.
|
/// A short string identifying this build's platform or distribution.
|
||||||
QString BUILD_PLATFORM;
|
QString BUILD_PLATFORM;
|
||||||
|
@ -44,6 +44,7 @@
|
|||||||
#include "BuildConfig.h"
|
#include "BuildConfig.h"
|
||||||
|
|
||||||
#include "DataMigrationTask.h"
|
#include "DataMigrationTask.h"
|
||||||
|
#include "java/JavaInstallList.h"
|
||||||
#include "net/PasteUpload.h"
|
#include "net/PasteUpload.h"
|
||||||
#include "pathmatcher/MultiMatcher.h"
|
#include "pathmatcher/MultiMatcher.h"
|
||||||
#include "pathmatcher/SimplePrefixMatcher.h"
|
#include "pathmatcher/SimplePrefixMatcher.h"
|
||||||
@ -125,6 +126,7 @@
|
|||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <sys.h>
|
#include <sys.h>
|
||||||
|
#include "SysInfo.h"
|
||||||
|
|
||||||
#ifdef Q_OS_LINUX
|
#ifdef Q_OS_LINUX
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
@ -602,6 +604,7 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
|
|||||||
m_settings->registerSetting("DownloadsDir", QStandardPaths::writableLocation(QStandardPaths::DownloadLocation));
|
m_settings->registerSetting("DownloadsDir", QStandardPaths::writableLocation(QStandardPaths::DownloadLocation));
|
||||||
m_settings->registerSetting("DownloadsDirWatchRecursive", false);
|
m_settings->registerSetting("DownloadsDirWatchRecursive", false);
|
||||||
m_settings->registerSetting("SkinsDir", "skins");
|
m_settings->registerSetting("SkinsDir", "skins");
|
||||||
|
m_settings->registerSetting("JavaDir", "java");
|
||||||
|
|
||||||
// Editors
|
// Editors
|
||||||
m_settings->registerSetting("JsonEditor", QString());
|
m_settings->registerSetting("JsonEditor", QString());
|
||||||
@ -630,7 +633,7 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
|
|||||||
|
|
||||||
// Memory
|
// Memory
|
||||||
m_settings->registerSetting({ "MinMemAlloc", "MinMemoryAlloc" }, 512);
|
m_settings->registerSetting({ "MinMemAlloc", "MinMemoryAlloc" }, 512);
|
||||||
m_settings->registerSetting({ "MaxMemAlloc", "MaxMemoryAlloc" }, suitableMaxMem());
|
m_settings->registerSetting({ "MaxMemAlloc", "MaxMemoryAlloc" }, SysInfo::suitableMaxMem());
|
||||||
m_settings->registerSetting("PermGen", 128);
|
m_settings->registerSetting("PermGen", 128);
|
||||||
|
|
||||||
// Java Settings
|
// Java Settings
|
||||||
@ -644,6 +647,9 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
|
|||||||
m_settings->registerSetting("JvmArgs", "");
|
m_settings->registerSetting("JvmArgs", "");
|
||||||
m_settings->registerSetting("IgnoreJavaCompatibility", false);
|
m_settings->registerSetting("IgnoreJavaCompatibility", false);
|
||||||
m_settings->registerSetting("IgnoreJavaWizard", false);
|
m_settings->registerSetting("IgnoreJavaWizard", false);
|
||||||
|
auto defaultEnableAutoJava = m_settings->get("JavaPath").toString().isEmpty();
|
||||||
|
m_settings->registerSetting("AutomaticJavaSwitch", defaultEnableAutoJava);
|
||||||
|
m_settings->registerSetting("AutomaticJavaDownload", defaultEnableAutoJava);
|
||||||
|
|
||||||
// Legacy settings
|
// Legacy settings
|
||||||
m_settings->registerSetting("OnlineFixes", false);
|
m_settings->registerSetting("OnlineFixes", false);
|
||||||
@ -873,6 +879,7 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
|
|||||||
m_metacache->addBase("ModrinthModpacks", QDir("cache/ModrinthModpacks").absolutePath());
|
m_metacache->addBase("ModrinthModpacks", QDir("cache/ModrinthModpacks").absolutePath());
|
||||||
m_metacache->addBase("translations", QDir("translations").absolutePath());
|
m_metacache->addBase("translations", QDir("translations").absolutePath());
|
||||||
m_metacache->addBase("meta", QDir("meta").absolutePath());
|
m_metacache->addBase("meta", QDir("meta").absolutePath());
|
||||||
|
m_metacache->addBase("java", QDir("cache/java").absolutePath());
|
||||||
m_metacache->Load();
|
m_metacache->Load();
|
||||||
qDebug() << "<> Cache initialized.";
|
qDebug() << "<> Cache initialized.";
|
||||||
}
|
}
|
||||||
@ -1740,20 +1747,6 @@ QString Application::getUserAgentUncached()
|
|||||||
return BuildConfig.USER_AGENT_UNCACHED;
|
return BuildConfig.USER_AGENT_UNCACHED;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Application::suitableMaxMem()
|
|
||||||
{
|
|
||||||
float totalRAM = (float)Sys::getSystemRam() / (float)Sys::mebibyte;
|
|
||||||
int maxMemoryAlloc;
|
|
||||||
|
|
||||||
// If totalRAM < 6GB, use (totalRAM / 1.5), else 4GB
|
|
||||||
if (totalRAM < (4096 * 1.5))
|
|
||||||
maxMemoryAlloc = (int)(totalRAM / 1.5);
|
|
||||||
else
|
|
||||||
maxMemoryAlloc = 4096;
|
|
||||||
|
|
||||||
return maxMemoryAlloc;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Application::handleDataMigration(const QString& currentData,
|
bool Application::handleDataMigration(const QString& currentData,
|
||||||
const QString& oldData,
|
const QString& oldData,
|
||||||
const QString& name,
|
const QString& name,
|
||||||
@ -1860,3 +1853,7 @@ QUrl Application::normalizeImportUrl(QString const& url)
|
|||||||
return QUrl::fromUserInput(url);
|
return QUrl::fromUserInput(url);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
const QString Application::javaPath()
|
||||||
|
{
|
||||||
|
return m_settings->get("JavaDir").toString();
|
||||||
|
}
|
||||||
|
@ -161,6 +161,9 @@ class Application : public QApplication {
|
|||||||
/// the data path the application is using
|
/// the data path the application is using
|
||||||
const QString& dataRoot() { return m_dataPath; }
|
const QString& dataRoot() { return m_dataPath; }
|
||||||
|
|
||||||
|
/// the java installed path the application is using
|
||||||
|
const QString javaPath();
|
||||||
|
|
||||||
bool isPortable() { return m_portable; }
|
bool isPortable() { return m_portable; }
|
||||||
|
|
||||||
const Capabilities capabilities() { return m_capabilities; }
|
const Capabilities capabilities() { return m_capabilities; }
|
||||||
@ -179,8 +182,6 @@ class Application : public QApplication {
|
|||||||
|
|
||||||
void ShowGlobalSettings(class QWidget* parent, QString open_page = QString());
|
void ShowGlobalSettings(class QWidget* parent, QString open_page = QString());
|
||||||
|
|
||||||
int suitableMaxMem();
|
|
||||||
|
|
||||||
bool updaterEnabled();
|
bool updaterEnabled();
|
||||||
QString updaterBinaryName();
|
QString updaterBinaryName();
|
||||||
|
|
||||||
|
@ -78,6 +78,14 @@ QVariant BaseVersionList::data(const QModelIndex& index, int role) const
|
|||||||
case TypeRole:
|
case TypeRole:
|
||||||
return version->typeString();
|
return version->typeString();
|
||||||
|
|
||||||
|
case JavaMajorRole: {
|
||||||
|
auto major = version->name();
|
||||||
|
if (major.startsWith("java")) {
|
||||||
|
major = "Java " + major.mid(4);
|
||||||
|
}
|
||||||
|
return major;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
}
|
||||||
@ -110,6 +118,8 @@ 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(ArchitectureRole, "architecture");
|
roles.insert(JavaNameRole, "javaName");
|
||||||
|
roles.insert(CPUArchitectureRole, "architecture");
|
||||||
|
roles.insert(JavaMajorRole, "javaMajor");
|
||||||
return roles;
|
return roles;
|
||||||
}
|
}
|
||||||
|
@ -48,7 +48,9 @@ class BaseVersionList : public QAbstractListModel {
|
|||||||
TypeRole,
|
TypeRole,
|
||||||
BranchRole,
|
BranchRole,
|
||||||
PathRole,
|
PathRole,
|
||||||
ArchitectureRole,
|
JavaNameRole,
|
||||||
|
JavaMajorRole,
|
||||||
|
CPUArchitectureRole,
|
||||||
SortRole
|
SortRole
|
||||||
};
|
};
|
||||||
using RoleList = QList<int>;
|
using RoleList = QList<int>;
|
||||||
|
@ -24,6 +24,8 @@ set(CORE_SOURCES
|
|||||||
NullInstance.h
|
NullInstance.h
|
||||||
MMCZip.h
|
MMCZip.h
|
||||||
MMCZip.cpp
|
MMCZip.cpp
|
||||||
|
Untar.h
|
||||||
|
Untar.cpp
|
||||||
StringUtils.h
|
StringUtils.h
|
||||||
StringUtils.cpp
|
StringUtils.cpp
|
||||||
QVariantUtils.h
|
QVariantUtils.h
|
||||||
@ -272,6 +274,8 @@ set(MINECRAFT_SOURCES
|
|||||||
minecraft/launch/ScanModFolders.h
|
minecraft/launch/ScanModFolders.h
|
||||||
minecraft/launch/VerifyJavaInstall.cpp
|
minecraft/launch/VerifyJavaInstall.cpp
|
||||||
minecraft/launch/VerifyJavaInstall.h
|
minecraft/launch/VerifyJavaInstall.h
|
||||||
|
minecraft/launch/AutoInstallJava.cpp
|
||||||
|
minecraft/launch/AutoInstallJava.h
|
||||||
|
|
||||||
minecraft/GradleSpecifier.h
|
minecraft/GradleSpecifier.h
|
||||||
minecraft/MinecraftInstance.cpp
|
minecraft/MinecraftInstance.cpp
|
||||||
@ -417,8 +421,6 @@ set(SETTINGS_SOURCES
|
|||||||
set(JAVA_SOURCES
|
set(JAVA_SOURCES
|
||||||
java/JavaChecker.h
|
java/JavaChecker.h
|
||||||
java/JavaChecker.cpp
|
java/JavaChecker.cpp
|
||||||
java/JavaCheckerJob.h
|
|
||||||
java/JavaCheckerJob.cpp
|
|
||||||
java/JavaInstall.h
|
java/JavaInstall.h
|
||||||
java/JavaInstall.cpp
|
java/JavaInstall.cpp
|
||||||
java/JavaInstallList.h
|
java/JavaInstallList.h
|
||||||
@ -427,6 +429,18 @@ set(JAVA_SOURCES
|
|||||||
java/JavaUtils.cpp
|
java/JavaUtils.cpp
|
||||||
java/JavaVersion.h
|
java/JavaVersion.h
|
||||||
java/JavaVersion.cpp
|
java/JavaVersion.cpp
|
||||||
|
|
||||||
|
java/JavaMetadata.h
|
||||||
|
java/JavaMetadata.cpp
|
||||||
|
java/download/ArchiveDownloadTask.cpp
|
||||||
|
java/download/ArchiveDownloadTask.h
|
||||||
|
java/download/ManifestDownloadTask.cpp
|
||||||
|
java/download/ManifestDownloadTask.h
|
||||||
|
|
||||||
|
ui/java/InstallJavaDialog.h
|
||||||
|
ui/java/InstallJavaDialog.cpp
|
||||||
|
ui/java/VersionList.h
|
||||||
|
ui/java/VersionList.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
set(TRANSLATIONS_SOURCES
|
set(TRANSLATIONS_SOURCES
|
||||||
@ -746,6 +760,8 @@ SET(LAUNCHER_SOURCES
|
|||||||
DataMigrationTask.cpp
|
DataMigrationTask.cpp
|
||||||
ApplicationMessage.h
|
ApplicationMessage.h
|
||||||
ApplicationMessage.cpp
|
ApplicationMessage.cpp
|
||||||
|
SysInfo.h
|
||||||
|
SysInfo.cpp
|
||||||
|
|
||||||
# GUI - general utilities
|
# GUI - general utilities
|
||||||
DesktopServices.h
|
DesktopServices.h
|
||||||
|
@ -276,6 +276,9 @@ bool ensureFolderPathExists(const QFileInfo folderPath)
|
|||||||
{
|
{
|
||||||
QDir dir;
|
QDir dir;
|
||||||
QString ensuredPath = folderPath.filePath();
|
QString ensuredPath = folderPath.filePath();
|
||||||
|
if (folderPath.exists())
|
||||||
|
return true;
|
||||||
|
|
||||||
bool success = dir.mkpath(ensuredPath);
|
bool success = dir.mkpath(ensuredPath);
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,12 @@
|
|||||||
#include "Filter.h"
|
#include "Filter.h"
|
||||||
|
|
||||||
Filter::~Filter() {}
|
|
||||||
|
|
||||||
ContainsFilter::ContainsFilter(const QString& pattern) : pattern(pattern) {}
|
ContainsFilter::ContainsFilter(const QString& pattern) : pattern(pattern) {}
|
||||||
ContainsFilter::~ContainsFilter() {}
|
|
||||||
bool ContainsFilter::accepts(const QString& value)
|
bool ContainsFilter::accepts(const QString& value)
|
||||||
{
|
{
|
||||||
return value.contains(pattern);
|
return value.contains(pattern);
|
||||||
}
|
}
|
||||||
|
|
||||||
ExactFilter::ExactFilter(const QString& pattern) : pattern(pattern) {}
|
ExactFilter::ExactFilter(const QString& pattern) : pattern(pattern) {}
|
||||||
ExactFilter::~ExactFilter() {}
|
|
||||||
bool ExactFilter::accepts(const QString& value)
|
bool ExactFilter::accepts(const QString& value)
|
||||||
{
|
{
|
||||||
return value == pattern;
|
return value == pattern;
|
||||||
@ -27,10 +23,15 @@ RegexpFilter::RegexpFilter(const QString& regexp, bool invert) : invert(invert)
|
|||||||
pattern.setPattern(regexp);
|
pattern.setPattern(regexp);
|
||||||
pattern.optimize();
|
pattern.optimize();
|
||||||
}
|
}
|
||||||
RegexpFilter::~RegexpFilter() {}
|
|
||||||
bool RegexpFilter::accepts(const QString& value)
|
bool RegexpFilter::accepts(const QString& value)
|
||||||
{
|
{
|
||||||
auto match = pattern.match(value);
|
auto match = pattern.match(value);
|
||||||
bool matched = match.hasMatch();
|
bool matched = match.hasMatch();
|
||||||
return invert ? (!matched) : (matched);
|
return invert ? (!matched) : (matched);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ExactListFilter::ExactListFilter(const QStringList& pattern) : m_pattern(pattern) {}
|
||||||
|
bool ExactListFilter::accepts(const QString& value)
|
||||||
|
{
|
||||||
|
return m_pattern.isEmpty() || m_pattern.contains(value);
|
||||||
|
}
|
@ -5,14 +5,14 @@
|
|||||||
|
|
||||||
class Filter {
|
class Filter {
|
||||||
public:
|
public:
|
||||||
virtual ~Filter();
|
virtual ~Filter() = default;
|
||||||
virtual bool accepts(const QString& value) = 0;
|
virtual bool accepts(const QString& value) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ContainsFilter : public Filter {
|
class ContainsFilter : public Filter {
|
||||||
public:
|
public:
|
||||||
ContainsFilter(const QString& pattern);
|
ContainsFilter(const QString& pattern);
|
||||||
virtual ~ContainsFilter();
|
virtual ~ContainsFilter() = default;
|
||||||
bool accepts(const QString& value) override;
|
bool accepts(const QString& value) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -22,7 +22,7 @@ class ContainsFilter : public Filter {
|
|||||||
class ExactFilter : public Filter {
|
class ExactFilter : public Filter {
|
||||||
public:
|
public:
|
||||||
ExactFilter(const QString& pattern);
|
ExactFilter(const QString& pattern);
|
||||||
virtual ~ExactFilter();
|
virtual ~ExactFilter() = default;
|
||||||
bool accepts(const QString& value) override;
|
bool accepts(const QString& value) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -32,7 +32,7 @@ class ExactFilter : public Filter {
|
|||||||
class ExactIfPresentFilter : public Filter {
|
class ExactIfPresentFilter : public Filter {
|
||||||
public:
|
public:
|
||||||
ExactIfPresentFilter(const QString& pattern);
|
ExactIfPresentFilter(const QString& pattern);
|
||||||
~ExactIfPresentFilter() override = default;
|
virtual ~ExactIfPresentFilter() override = default;
|
||||||
bool accepts(const QString& value) override;
|
bool accepts(const QString& value) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -42,10 +42,20 @@ class ExactIfPresentFilter : public Filter {
|
|||||||
class RegexpFilter : public Filter {
|
class RegexpFilter : public Filter {
|
||||||
public:
|
public:
|
||||||
RegexpFilter(const QString& regexp, bool invert);
|
RegexpFilter(const QString& regexp, bool invert);
|
||||||
virtual ~RegexpFilter();
|
virtual ~RegexpFilter() = default;
|
||||||
bool accepts(const QString& value) override;
|
bool accepts(const QString& value) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QRegularExpression pattern;
|
QRegularExpression pattern;
|
||||||
bool invert = false;
|
bool invert = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ExactListFilter : public Filter {
|
||||||
|
public:
|
||||||
|
ExactListFilter(const QStringList& pattern = {});
|
||||||
|
virtual ~ExactListFilter() = default;
|
||||||
|
bool accepts(const QString& value) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const QStringList& m_pattern;
|
||||||
|
};
|
||||||
|
@ -63,7 +63,7 @@ bool JavaCommon::checkJVMArgs(QString jvmargs, QWidget* parent)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void JavaCommon::javaWasOk(QWidget* parent, const JavaCheckResult& result)
|
void JavaCommon::javaWasOk(QWidget* parent, const JavaChecker::Result& result)
|
||||||
{
|
{
|
||||||
QString text;
|
QString text;
|
||||||
text += QObject::tr(
|
text += QObject::tr(
|
||||||
@ -79,7 +79,7 @@ void JavaCommon::javaWasOk(QWidget* parent, const JavaCheckResult& result)
|
|||||||
CustomMessageBox::selectable(parent, QObject::tr("Java test success"), text, QMessageBox::Information)->show();
|
CustomMessageBox::selectable(parent, QObject::tr("Java test success"), text, QMessageBox::Information)->show();
|
||||||
}
|
}
|
||||||
|
|
||||||
void JavaCommon::javaArgsWereBad(QWidget* parent, const JavaCheckResult& result)
|
void JavaCommon::javaArgsWereBad(QWidget* parent, const JavaChecker::Result& result)
|
||||||
{
|
{
|
||||||
auto htmlError = result.errorLog;
|
auto htmlError = result.errorLog;
|
||||||
QString text;
|
QString text;
|
||||||
@ -89,7 +89,7 @@ void JavaCommon::javaArgsWereBad(QWidget* parent, const JavaCheckResult& result)
|
|||||||
CustomMessageBox::selectable(parent, QObject::tr("Java test failure"), text, QMessageBox::Warning)->show();
|
CustomMessageBox::selectable(parent, QObject::tr("Java test failure"), text, QMessageBox::Warning)->show();
|
||||||
}
|
}
|
||||||
|
|
||||||
void JavaCommon::javaBinaryWasBad(QWidget* parent, const JavaCheckResult& result)
|
void JavaCommon::javaBinaryWasBad(QWidget* parent, const JavaChecker::Result& result)
|
||||||
{
|
{
|
||||||
QString text;
|
QString text;
|
||||||
text += QObject::tr(
|
text += QObject::tr(
|
||||||
@ -116,34 +116,26 @@ void JavaCommon::TestCheck::run()
|
|||||||
emit finished();
|
emit finished();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
checker.reset(new JavaChecker());
|
checker.reset(new JavaChecker(m_path, "", 0, 0, 0, 0, this));
|
||||||
connect(checker.get(), &JavaChecker::checkFinished, this, &JavaCommon::TestCheck::checkFinished);
|
connect(checker.get(), &JavaChecker::checkFinished, this, &JavaCommon::TestCheck::checkFinished);
|
||||||
checker->m_path = m_path;
|
checker->start();
|
||||||
checker->performCheck();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void JavaCommon::TestCheck::checkFinished(JavaCheckResult result)
|
void JavaCommon::TestCheck::checkFinished(const JavaChecker::Result& result)
|
||||||
{
|
{
|
||||||
if (result.validity != JavaCheckResult::Validity::Valid) {
|
if (result.validity != JavaChecker::Result::Validity::Valid) {
|
||||||
javaBinaryWasBad(m_parent, result);
|
javaBinaryWasBad(m_parent, result);
|
||||||
emit finished();
|
emit finished();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
checker.reset(new JavaChecker());
|
checker.reset(new JavaChecker(m_path, m_args, m_maxMem, m_maxMem, result.javaVersion.requiresPermGen() ? m_permGen : 0, 0, this));
|
||||||
connect(checker.get(), &JavaChecker::checkFinished, this, &JavaCommon::TestCheck::checkFinishedWithArgs);
|
connect(checker.get(), &JavaChecker::checkFinished, this, &JavaCommon::TestCheck::checkFinishedWithArgs);
|
||||||
checker->m_path = m_path;
|
checker->start();
|
||||||
checker->m_args = m_args;
|
|
||||||
checker->m_minMem = m_minMem;
|
|
||||||
checker->m_maxMem = m_maxMem;
|
|
||||||
if (result.javaVersion.requiresPermGen()) {
|
|
||||||
checker->m_permGen = m_permGen;
|
|
||||||
}
|
|
||||||
checker->performCheck();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void JavaCommon::TestCheck::checkFinishedWithArgs(JavaCheckResult result)
|
void JavaCommon::TestCheck::checkFinishedWithArgs(const JavaChecker::Result& result)
|
||||||
{
|
{
|
||||||
if (result.validity == JavaCheckResult::Validity::Valid) {
|
if (result.validity == JavaChecker::Result::Validity::Valid) {
|
||||||
javaWasOk(m_parent, result);
|
javaWasOk(m_parent, result);
|
||||||
emit finished();
|
emit finished();
|
||||||
return;
|
return;
|
||||||
|
@ -10,11 +10,11 @@ namespace JavaCommon {
|
|||||||
bool checkJVMArgs(QString args, QWidget* parent);
|
bool checkJVMArgs(QString args, QWidget* parent);
|
||||||
|
|
||||||
// Show a dialog saying that the Java binary was usable
|
// Show a dialog saying that the Java binary was usable
|
||||||
void javaWasOk(QWidget* parent, const JavaCheckResult& result);
|
void javaWasOk(QWidget* parent, const JavaChecker::Result& result);
|
||||||
// Show a dialog saying that the Java binary was not usable because of bad options
|
// Show a dialog saying that the Java binary was not usable because of bad options
|
||||||
void javaArgsWereBad(QWidget* parent, const JavaCheckResult& result);
|
void javaArgsWereBad(QWidget* parent, const JavaChecker::Result& result);
|
||||||
// Show a dialog saying that the Java binary was not usable
|
// Show a dialog saying that the Java binary was not usable
|
||||||
void javaBinaryWasBad(QWidget* parent, const JavaCheckResult& result);
|
void javaBinaryWasBad(QWidget* parent, const JavaChecker::Result& result);
|
||||||
// Show a dialog if we couldn't find Java Checker
|
// Show a dialog if we couldn't find Java Checker
|
||||||
void javaCheckNotFound(QWidget* parent);
|
void javaCheckNotFound(QWidget* parent);
|
||||||
|
|
||||||
@ -32,11 +32,11 @@ class TestCheck : public QObject {
|
|||||||
void finished();
|
void finished();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void checkFinished(JavaCheckResult result);
|
void checkFinished(const JavaChecker::Result& result);
|
||||||
void checkFinishedWithArgs(JavaCheckResult result);
|
void checkFinishedWithArgs(const JavaChecker::Result& result);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<JavaChecker> checker;
|
JavaChecker::Ptr checker;
|
||||||
QWidget* m_parent = nullptr;
|
QWidget* m_parent = nullptr;
|
||||||
QString m_path;
|
QString m_path;
|
||||||
QString m_args;
|
QString m_args;
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
/*
|
/*
|
||||||
* Prism Launcher - Minecraft Launcher
|
* Prism Launcher - Minecraft Launcher
|
||||||
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
||||||
* Copyright (c) 2023 Trial97 <alexandru.tripon97@gmail.com>
|
* Copyright (c) 2023-2024 Trial97 <alexandru.tripon97@gmail.com>
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -536,6 +536,10 @@ bool ExportToZipTask::abort()
|
|||||||
|
|
||||||
void ExtractZipTask::executeTask()
|
void ExtractZipTask::executeTask()
|
||||||
{
|
{
|
||||||
|
if (!m_input->isOpen() && !m_input->open(QuaZip::mdUnzip)) {
|
||||||
|
emitFailed(tr("Unable to open supplied zip file."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
m_zip_future = QtConcurrent::run(QThreadPool::globalInstance(), [this]() { return extractZip(); });
|
m_zip_future = QtConcurrent::run(QThreadPool::globalInstance(), [this]() { return extractZip(); });
|
||||||
connect(&m_zip_watcher, &QFutureWatcher<ZipResult>::finished, this, &ExtractZipTask::finish);
|
connect(&m_zip_watcher, &QFutureWatcher<ZipResult>::finished, this, &ExtractZipTask::finish);
|
||||||
m_zip_watcher.setFuture(m_zip_future);
|
m_zip_watcher.setFuture(m_zip_future);
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
/*
|
/*
|
||||||
* Prism Launcher - Minecraft Launcher
|
* Prism Launcher - Minecraft Launcher
|
||||||
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
||||||
* Copyright (c) 2023 Trial97 <alexandru.tripon97@gmail.com>
|
* Copyright (c) 2023-2024 Trial97 <alexandru.tripon97@gmail.com>
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -208,6 +208,9 @@ class ExportToZipTask : public Task {
|
|||||||
|
|
||||||
class ExtractZipTask : public Task {
|
class ExtractZipTask : public Task {
|
||||||
public:
|
public:
|
||||||
|
ExtractZipTask(QString input, QDir outputDir, QString subdirectory = "")
|
||||||
|
: ExtractZipTask(std::make_shared<QuaZip>(input), outputDir, subdirectory)
|
||||||
|
{}
|
||||||
ExtractZipTask(std::shared_ptr<QuaZip> input, QDir outputDir, QString subdirectory = "")
|
ExtractZipTask(std::shared_ptr<QuaZip> input, QDir outputDir, QString subdirectory = "")
|
||||||
: m_input(input), m_output_dir(outputDir), m_subdirectory(subdirectory)
|
: m_input(input), m_output_dir(outputDir), m_subdirectory(subdirectory)
|
||||||
{}
|
{}
|
||||||
|
99
launcher/SysInfo.cpp
Normal file
99
launcher/SysInfo.cpp
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
#include <QDebug>
|
||||||
|
#include <QString>
|
||||||
|
#include "sys.h"
|
||||||
|
#ifdef Q_OS_MACOS
|
||||||
|
#include <sys/sysctl.h>
|
||||||
|
#endif
|
||||||
|
#include <QFile>
|
||||||
|
#include <QMap>
|
||||||
|
#include <QProcess>
|
||||||
|
#include <QStandardPaths>
|
||||||
|
|
||||||
|
#ifdef Q_OS_MACOS
|
||||||
|
bool rosettaDetect()
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
size_t size = sizeof(ret);
|
||||||
|
if (sysctlbyname("sysctl.proc_translated", &ret, &size, NULL, 0) == -1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return ret == 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace SysInfo {
|
||||||
|
QString currentSystem()
|
||||||
|
{
|
||||||
|
#if defined(Q_OS_LINUX)
|
||||||
|
return "linux";
|
||||||
|
#elif defined(Q_OS_MACOS)
|
||||||
|
return "osx";
|
||||||
|
#elif defined(Q_OS_WINDOWS)
|
||||||
|
return "windows";
|
||||||
|
#elif defined(Q_OS_FREEBSD)
|
||||||
|
return "freebsd";
|
||||||
|
#elif defined(Q_OS_OPENBSD)
|
||||||
|
return "openbsd";
|
||||||
|
#else
|
||||||
|
return "unknown";
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
QString useQTForArch()
|
||||||
|
{
|
||||||
|
#if defined(Q_OS_MACOS) && !defined(Q_PROCESSOR_ARM)
|
||||||
|
if (rosettaDetect()) {
|
||||||
|
return "arm64";
|
||||||
|
} else {
|
||||||
|
return "x86_64";
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return QSysInfo::currentCpuArchitecture();
|
||||||
|
}
|
||||||
|
|
||||||
|
int suitableMaxMem()
|
||||||
|
{
|
||||||
|
float totalRAM = (float)Sys::getSystemRam() / (float)Sys::mebibyte;
|
||||||
|
int maxMemoryAlloc;
|
||||||
|
|
||||||
|
// If totalRAM < 6GB, use (totalRAM / 1.5), else 4GB
|
||||||
|
if (totalRAM < (4096 * 1.5))
|
||||||
|
maxMemoryAlloc = (int)(totalRAM / 1.5);
|
||||||
|
else
|
||||||
|
maxMemoryAlloc = 4096;
|
||||||
|
|
||||||
|
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
|
8
launcher/SysInfo.h
Normal file
8
launcher/SysInfo.h
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#include <QString>
|
||||||
|
|
||||||
|
namespace SysInfo {
|
||||||
|
QString currentSystem();
|
||||||
|
QString useQTForArch();
|
||||||
|
QString getSupportedJavaArchitecture();
|
||||||
|
int suitableMaxMem();
|
||||||
|
} // namespace SysInfo
|
260
launcher/Untar.cpp
Normal file
260
launcher/Untar.cpp
Normal file
@ -0,0 +1,260 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
/*
|
||||||
|
* Prism Launcher - Minecraft Launcher
|
||||||
|
* Copyright (c) 2023-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/>.
|
||||||
|
*
|
||||||
|
* 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 "Untar.h"
|
||||||
|
#include <quagzipfile.h>
|
||||||
|
#include <QByteArray>
|
||||||
|
#include <QFileInfo>
|
||||||
|
#include <QIODevice>
|
||||||
|
#include <QString>
|
||||||
|
#include "FileSystem.h"
|
||||||
|
|
||||||
|
// adaptation of the:
|
||||||
|
// - https://github.com/madler/zlib/blob/develop/contrib/untgz/untgz.c
|
||||||
|
// - https://en.wikipedia.org/wiki/Tar_(computing)
|
||||||
|
// - https://github.com/euroelessar/cutereader/blob/master/karchive/src/ktar.cpp
|
||||||
|
|
||||||
|
#define BLOCKSIZE 512
|
||||||
|
#define SHORTNAMESIZE 100
|
||||||
|
|
||||||
|
enum class TypeFlag : char {
|
||||||
|
Regular = '0', // regular file
|
||||||
|
ARegular = 0, // regular file
|
||||||
|
Link = '1', // link
|
||||||
|
Symlink = '2', // reserved
|
||||||
|
Character = '3', // character special
|
||||||
|
Block = '4', // block special
|
||||||
|
Directory = '5', // directory
|
||||||
|
FIFO = '6', // FIFO special
|
||||||
|
Contiguous = '7', // reserved
|
||||||
|
// Posix stuff
|
||||||
|
GlobalPosixHeader = 'g',
|
||||||
|
ExtendedPosixHeader = 'x',
|
||||||
|
// 'A'– 'Z' Vendor specific extensions(POSIX .1 - 1988)
|
||||||
|
// GNU
|
||||||
|
GNULongLink = 'K', /* long link name */
|
||||||
|
GNULongName = 'L', /* long file name */
|
||||||
|
};
|
||||||
|
|
||||||
|
// struct Header { /* byte offset */
|
||||||
|
// char name[100]; /* 0 */
|
||||||
|
// char mode[8]; /* 100 */
|
||||||
|
// char uid[8]; /* 108 */
|
||||||
|
// char gid[8]; /* 116 */
|
||||||
|
// char size[12]; /* 124 */
|
||||||
|
// char mtime[12]; /* 136 */
|
||||||
|
// char chksum[8]; /* 148 */
|
||||||
|
// TypeFlag typeflag; /* 156 */
|
||||||
|
// char linkname[100]; /* 157 */
|
||||||
|
// char magic[6]; /* 257 */
|
||||||
|
// char version[2]; /* 263 */
|
||||||
|
// char uname[32]; /* 265 */
|
||||||
|
// char gname[32]; /* 297 */
|
||||||
|
// char devmajor[8]; /* 329 */
|
||||||
|
// char devminor[8]; /* 337 */
|
||||||
|
// char prefix[155]; /* 345 */
|
||||||
|
// /* 500 */
|
||||||
|
// };
|
||||||
|
|
||||||
|
bool readLonglink(QIODevice* in, qint64 size, QByteArray& longlink)
|
||||||
|
{
|
||||||
|
qint64 n = 0;
|
||||||
|
size--; // ignore trailing null
|
||||||
|
if (size < 0) {
|
||||||
|
qCritical() << "The filename size is negative";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
longlink.resize(size + (BLOCKSIZE - size % BLOCKSIZE)); // make the size divisible by BLOCKSIZE
|
||||||
|
for (qint64 offset = 0; offset < longlink.size(); offset += BLOCKSIZE) {
|
||||||
|
n = in->read(longlink.data() + offset, BLOCKSIZE);
|
||||||
|
if (n != BLOCKSIZE) {
|
||||||
|
qCritical() << "The expected blocksize was not respected for the name";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
longlink.truncate(qstrlen(longlink.constData()));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getOctal(char* buffer, int maxlenght, bool* ok)
|
||||||
|
{
|
||||||
|
return QByteArray(buffer, qstrnlen(buffer, maxlenght)).toInt(ok, 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString decodeName(char* name)
|
||||||
|
{
|
||||||
|
return QFile::decodeName(QByteArray(name, qstrnlen(name, 100)));
|
||||||
|
}
|
||||||
|
bool Tar::extract(QIODevice* in, QString dst)
|
||||||
|
{
|
||||||
|
char buffer[BLOCKSIZE];
|
||||||
|
QString name, symlink, firstFolderName;
|
||||||
|
bool doNotReset = false, ok;
|
||||||
|
while (true) {
|
||||||
|
auto n = in->read(buffer, BLOCKSIZE);
|
||||||
|
if (n != BLOCKSIZE) { // allways expect complete blocks
|
||||||
|
qCritical() << "The expected blocksize was not respected";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (buffer[0] == 0) { // end of archive
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
int mode = getOctal(buffer + 100, 8, &ok) | QFile::ReadUser | QFile::WriteUser; // hack to ensure write and read permisions
|
||||||
|
if (!ok) {
|
||||||
|
qCritical() << "The file mode can't be read";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// there are names that are exactly 100 bytes long
|
||||||
|
// and neither longlink nor \0 terminated (bug:101472)
|
||||||
|
|
||||||
|
if (name.isEmpty()) {
|
||||||
|
name = decodeName(buffer);
|
||||||
|
if (!firstFolderName.isEmpty() && name.startsWith(firstFolderName)) {
|
||||||
|
name = name.mid(firstFolderName.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (symlink.isEmpty())
|
||||||
|
symlink = decodeName(buffer);
|
||||||
|
qint64 size = getOctal(buffer + 124, 12, &ok);
|
||||||
|
if (!ok) {
|
||||||
|
qCritical() << "The file size can't be read";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
switch (TypeFlag(buffer[156])) {
|
||||||
|
case TypeFlag::Regular:
|
||||||
|
/* fallthrough */
|
||||||
|
case TypeFlag::ARegular: {
|
||||||
|
auto fileName = FS::PathCombine(dst, name);
|
||||||
|
if (!FS::ensureFilePathExists(fileName)) {
|
||||||
|
qCritical() << "Can't ensure the file path to exist: " << fileName;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
QFile out(fileName);
|
||||||
|
if (!out.open(QFile::WriteOnly)) {
|
||||||
|
qCritical() << "Can't open file:" << fileName;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
out.setPermissions(QFile::Permissions(mode));
|
||||||
|
while (size > 0) {
|
||||||
|
QByteArray tmp(BLOCKSIZE, 0);
|
||||||
|
n = in->read(tmp.data(), BLOCKSIZE);
|
||||||
|
if (n != BLOCKSIZE) {
|
||||||
|
qCritical() << "The expected blocksize was not respected when reading file";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
tmp.truncate(qMin(qint64(BLOCKSIZE), size));
|
||||||
|
out.write(tmp);
|
||||||
|
size -= BLOCKSIZE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TypeFlag::Directory: {
|
||||||
|
if (firstFolderName.isEmpty()) {
|
||||||
|
firstFolderName = name;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
auto folderPath = FS::PathCombine(dst, name);
|
||||||
|
if (!FS::ensureFolderPathExists(folderPath)) {
|
||||||
|
qCritical() << "Can't ensure that folder exists: " << folderPath;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TypeFlag::GNULongLink: {
|
||||||
|
doNotReset = true;
|
||||||
|
QByteArray longlink;
|
||||||
|
if (readLonglink(in, size, longlink)) {
|
||||||
|
symlink = QFile::decodeName(longlink.constData());
|
||||||
|
} else {
|
||||||
|
qCritical() << "Failed to read long link";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TypeFlag::GNULongName: {
|
||||||
|
doNotReset = true;
|
||||||
|
QByteArray longlink;
|
||||||
|
if (readLonglink(in, size, longlink)) {
|
||||||
|
name = QFile::decodeName(longlink.constData());
|
||||||
|
} else {
|
||||||
|
qCritical() << "Failed to read long name";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TypeFlag::Link:
|
||||||
|
/* fallthrough */
|
||||||
|
case TypeFlag::Symlink: {
|
||||||
|
auto fileName = FS::PathCombine(dst, name);
|
||||||
|
if (!FS::create_link(FS::PathCombine(QFileInfo(fileName).path(), symlink), fileName)()) { // do not use symlinks
|
||||||
|
qCritical() << "Can't create link for:" << fileName << " to:" << FS::PathCombine(QFileInfo(fileName).path(), symlink);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
FS::ensureFilePathExists(fileName);
|
||||||
|
QFile::setPermissions(fileName, QFile::Permissions(mode));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TypeFlag::Character:
|
||||||
|
/* fallthrough */
|
||||||
|
case TypeFlag::Block:
|
||||||
|
/* fallthrough */
|
||||||
|
case TypeFlag::FIFO:
|
||||||
|
/* fallthrough */
|
||||||
|
case TypeFlag::Contiguous:
|
||||||
|
/* fallthrough */
|
||||||
|
case TypeFlag::GlobalPosixHeader:
|
||||||
|
/* fallthrough */
|
||||||
|
case TypeFlag::ExtendedPosixHeader:
|
||||||
|
/* fallthrough */
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!doNotReset) {
|
||||||
|
name.truncate(0);
|
||||||
|
symlink.truncate(0);
|
||||||
|
}
|
||||||
|
doNotReset = false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GZTar::extract(QString src, QString dst)
|
||||||
|
{
|
||||||
|
QuaGzipFile a(src);
|
||||||
|
if (!a.open(QIODevice::ReadOnly)) {
|
||||||
|
qCritical() << "Can't open tar file:" << src;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return Tar::extract(&a, dst);
|
||||||
|
}
|
46
launcher/Untar.h
Normal file
46
launcher/Untar.h
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
/*
|
||||||
|
* Prism Launcher - Minecraft Launcher
|
||||||
|
* Copyright (c) 2023-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/>.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
#include <QIODevice>
|
||||||
|
|
||||||
|
// this is a hack used for the java downloader (feel free to remove it in favor of a library)
|
||||||
|
// both extract functions will extract the first folder inside dest(disregarding the prefix)
|
||||||
|
namespace Tar {
|
||||||
|
bool extract(QIODevice* in, QString dst);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace GZTar {
|
||||||
|
bool extract(QString src, QString dst);
|
||||||
|
}
|
@ -114,10 +114,14 @@ QVariant VersionProxyModel::headerData(int section, Qt::Orientation orientation,
|
|||||||
return tr("Branch");
|
return tr("Branch");
|
||||||
case Type:
|
case Type:
|
||||||
return tr("Type");
|
return tr("Type");
|
||||||
case Architecture:
|
case CPUArchitecture:
|
||||||
return tr("Architecture");
|
return tr("Architecture");
|
||||||
case Path:
|
case Path:
|
||||||
return tr("Path");
|
return tr("Path");
|
||||||
|
case JavaName:
|
||||||
|
return tr("Java Name");
|
||||||
|
case JavaMajor:
|
||||||
|
return tr("Major Version");
|
||||||
case Time:
|
case Time:
|
||||||
return tr("Released");
|
return tr("Released");
|
||||||
}
|
}
|
||||||
@ -131,10 +135,14 @@ QVariant VersionProxyModel::headerData(int section, Qt::Orientation orientation,
|
|||||||
return tr("The version's branch");
|
return tr("The version's branch");
|
||||||
case Type:
|
case Type:
|
||||||
return tr("The version's type");
|
return tr("The version's type");
|
||||||
case Architecture:
|
case CPUArchitecture:
|
||||||
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 JavaName:
|
||||||
|
return tr("The alternative name of the java version");
|
||||||
|
case JavaMajor:
|
||||||
|
return tr("The java major version");
|
||||||
case Time:
|
case Time:
|
||||||
return tr("Release date of this version");
|
return tr("Release date of this version");
|
||||||
}
|
}
|
||||||
@ -165,10 +173,14 @@ QVariant VersionProxyModel::data(const QModelIndex& index, int role) const
|
|||||||
return sourceModel()->data(parentIndex, BaseVersionList::BranchRole);
|
return sourceModel()->data(parentIndex, BaseVersionList::BranchRole);
|
||||||
case Type:
|
case Type:
|
||||||
return sourceModel()->data(parentIndex, BaseVersionList::TypeRole);
|
return sourceModel()->data(parentIndex, BaseVersionList::TypeRole);
|
||||||
case Architecture:
|
case CPUArchitecture:
|
||||||
return sourceModel()->data(parentIndex, BaseVersionList::ArchitectureRole);
|
return sourceModel()->data(parentIndex, BaseVersionList::CPUArchitectureRole);
|
||||||
case Path:
|
case Path:
|
||||||
return sourceModel()->data(parentIndex, BaseVersionList::PathRole);
|
return sourceModel()->data(parentIndex, BaseVersionList::PathRole);
|
||||||
|
case JavaName:
|
||||||
|
return sourceModel()->data(parentIndex, BaseVersionList::JavaNameRole);
|
||||||
|
case JavaMajor:
|
||||||
|
return sourceModel()->data(parentIndex, BaseVersionList::JavaMajorRole);
|
||||||
case Time:
|
case Time:
|
||||||
return sourceModel()->data(parentIndex, Meta::VersionList::TimeRole).toDate();
|
return sourceModel()->data(parentIndex, Meta::VersionList::TimeRole).toDate();
|
||||||
default:
|
default:
|
||||||
@ -308,12 +320,18 @@ void VersionProxyModel::setSourceModel(QAbstractItemModel* replacingRaw)
|
|||||||
m_columns.push_back(ParentVersion);
|
m_columns.push_back(ParentVersion);
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
if (roles.contains(BaseVersionList::ArchitectureRole)) {
|
if (roles.contains(BaseVersionList::CPUArchitectureRole)) {
|
||||||
m_columns.push_back(Architecture);
|
m_columns.push_back(CPUArchitecture);
|
||||||
}
|
}
|
||||||
if (roles.contains(BaseVersionList::PathRole)) {
|
if (roles.contains(BaseVersionList::PathRole)) {
|
||||||
m_columns.push_back(Path);
|
m_columns.push_back(Path);
|
||||||
}
|
}
|
||||||
|
if (roles.contains(BaseVersionList::JavaNameRole)) {
|
||||||
|
m_columns.push_back(JavaName);
|
||||||
|
}
|
||||||
|
if (roles.contains(BaseVersionList::JavaMajorRole)) {
|
||||||
|
m_columns.push_back(JavaMajor);
|
||||||
|
}
|
||||||
if (roles.contains(Meta::VersionList::TimeRole)) {
|
if (roles.contains(Meta::VersionList::TimeRole)) {
|
||||||
m_columns.push_back(Time);
|
m_columns.push_back(Time);
|
||||||
}
|
}
|
||||||
|
@ -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, CPUArchitecture, Path, Time, JavaName, JavaMajor };
|
||||||
using FilterMap = QHash<BaseVersionList::ModelRoles, std::shared_ptr<Filter>>;
|
using FilterMap = QHash<BaseVersionList::ModelRoles, std::shared_ptr<Filter>>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -40,14 +40,15 @@
|
|||||||
#include <QMap>
|
#include <QMap>
|
||||||
#include <QProcess>
|
#include <QProcess>
|
||||||
|
|
||||||
#include "Application.h"
|
|
||||||
#include "Commandline.h"
|
#include "Commandline.h"
|
||||||
#include "FileSystem.h"
|
#include "FileSystem.h"
|
||||||
#include "JavaUtils.h"
|
#include "java/JavaUtils.h"
|
||||||
|
|
||||||
JavaChecker::JavaChecker(QObject* parent) : QObject(parent) {}
|
JavaChecker::JavaChecker(QString path, QString args, int minMem, int maxMem, int permGen, int id, QObject* parent)
|
||||||
|
: Task(parent), m_path(path), m_args(args), m_minMem(minMem), m_maxMem(maxMem), m_permGen(permGen), m_id(id)
|
||||||
|
{}
|
||||||
|
|
||||||
void JavaChecker::performCheck()
|
void JavaChecker::executeTask()
|
||||||
{
|
{
|
||||||
QString checkerJar = JavaUtils::getJavaCheckPath();
|
QString checkerJar = JavaUtils::getJavaCheckPath();
|
||||||
|
|
||||||
@ -72,7 +73,7 @@ void JavaChecker::performCheck()
|
|||||||
if (m_maxMem != 0) {
|
if (m_maxMem != 0) {
|
||||||
args << QString("-Xmx%1m").arg(m_maxMem);
|
args << QString("-Xmx%1m").arg(m_maxMem);
|
||||||
}
|
}
|
||||||
if (m_permGen != 64) {
|
if (m_permGen != 64 && m_permGen != 0) {
|
||||||
args << QString("-XX:PermSize=%1m").arg(m_permGen);
|
args << QString("-XX:PermSize=%1m").arg(m_permGen);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,11 +116,10 @@ void JavaChecker::finished(int exitcode, QProcess::ExitStatus status)
|
|||||||
QProcessPtr _process = process;
|
QProcessPtr _process = process;
|
||||||
process.reset();
|
process.reset();
|
||||||
|
|
||||||
JavaCheckResult result;
|
Result result = {
|
||||||
{
|
m_path,
|
||||||
result.path = m_path;
|
m_id,
|
||||||
result.id = m_id;
|
};
|
||||||
}
|
|
||||||
result.errorLog = m_stderr;
|
result.errorLog = m_stderr;
|
||||||
result.outLog = m_stdout;
|
result.outLog = m_stdout;
|
||||||
qDebug() << "STDOUT" << m_stdout;
|
qDebug() << "STDOUT" << m_stdout;
|
||||||
@ -127,8 +127,9 @@ void JavaChecker::finished(int exitcode, QProcess::ExitStatus status)
|
|||||||
qDebug() << "Java checker finished with status" << status << "exit code" << exitcode;
|
qDebug() << "Java checker finished with status" << status << "exit code" << exitcode;
|
||||||
|
|
||||||
if (status == QProcess::CrashExit || exitcode == 1) {
|
if (status == QProcess::CrashExit || exitcode == 1) {
|
||||||
result.validity = JavaCheckResult::Validity::Errored;
|
result.validity = Result::Validity::Errored;
|
||||||
emit checkFinished(result);
|
emit checkFinished(result);
|
||||||
|
emitSucceeded();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -161,8 +162,9 @@ void JavaChecker::finished(int exitcode, QProcess::ExitStatus status)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!results.contains("os.arch") || !results.contains("java.version") || !results.contains("java.vendor") || !success) {
|
if (!results.contains("os.arch") || !results.contains("java.version") || !results.contains("java.vendor") || !success) {
|
||||||
result.validity = JavaCheckResult::Validity::ReturnedInvalidData;
|
result.validity = Result::Validity::ReturnedInvalidData;
|
||||||
emit checkFinished(result);
|
emit checkFinished(result);
|
||||||
|
emitSucceeded();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -171,7 +173,7 @@ void JavaChecker::finished(int exitcode, QProcess::ExitStatus status)
|
|||||||
auto java_vendor = results["java.vendor"];
|
auto java_vendor = results["java.vendor"];
|
||||||
bool is_64 = os_arch == "x86_64" || os_arch == "amd64" || os_arch == "aarch64" || os_arch == "arm64";
|
bool is_64 = os_arch == "x86_64" || os_arch == "amd64" || os_arch == "aarch64" || os_arch == "arm64";
|
||||||
|
|
||||||
result.validity = JavaCheckResult::Validity::Valid;
|
result.validity = Result::Validity::Valid;
|
||||||
result.is_64bit = is_64;
|
result.is_64bit = is_64;
|
||||||
result.mojangPlatform = is_64 ? "64" : "32";
|
result.mojangPlatform = is_64 ? "64" : "32";
|
||||||
result.realPlatform = os_arch;
|
result.realPlatform = os_arch;
|
||||||
@ -179,6 +181,7 @@ void JavaChecker::finished(int exitcode, QProcess::ExitStatus status)
|
|||||||
result.javaVendor = java_vendor;
|
result.javaVendor = java_vendor;
|
||||||
qDebug() << "Java checker succeeded.";
|
qDebug() << "Java checker succeeded.";
|
||||||
emit checkFinished(result);
|
emit checkFinished(result);
|
||||||
|
emitSucceeded();
|
||||||
}
|
}
|
||||||
|
|
||||||
void JavaChecker::error(QProcess::ProcessError err)
|
void JavaChecker::error(QProcess::ProcessError err)
|
||||||
@ -190,15 +193,9 @@ void JavaChecker::error(QProcess::ProcessError err)
|
|||||||
qDebug() << "Native environment:";
|
qDebug() << "Native environment:";
|
||||||
qDebug() << QProcessEnvironment::systemEnvironment().toStringList();
|
qDebug() << QProcessEnvironment::systemEnvironment().toStringList();
|
||||||
killTimer.stop();
|
killTimer.stop();
|
||||||
JavaCheckResult result;
|
emit checkFinished({ m_path, m_id });
|
||||||
{
|
|
||||||
result.path = m_path;
|
|
||||||
result.id = m_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
emit checkFinished(result);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
emitSucceeded();
|
||||||
}
|
}
|
||||||
|
|
||||||
void JavaChecker::timeout()
|
void JavaChecker::timeout()
|
||||||
|
@ -3,49 +3,51 @@
|
|||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include "QObjectPtr.h"
|
|
||||||
|
|
||||||
#include "JavaVersion.h"
|
#include "JavaVersion.h"
|
||||||
|
#include "QObjectPtr.h"
|
||||||
|
#include "tasks/Task.h"
|
||||||
|
|
||||||
class JavaChecker;
|
class JavaChecker : public Task {
|
||||||
|
|
||||||
struct JavaCheckResult {
|
|
||||||
QString path;
|
|
||||||
QString mojangPlatform;
|
|
||||||
QString realPlatform;
|
|
||||||
JavaVersion javaVersion;
|
|
||||||
QString javaVendor;
|
|
||||||
QString outLog;
|
|
||||||
QString errorLog;
|
|
||||||
bool is_64bit = false;
|
|
||||||
int id;
|
|
||||||
enum class Validity { Errored, ReturnedInvalidData, Valid } validity = Validity::Errored;
|
|
||||||
};
|
|
||||||
|
|
||||||
using QProcessPtr = shared_qobject_ptr<QProcess>;
|
|
||||||
using JavaCheckerPtr = shared_qobject_ptr<JavaChecker>;
|
|
||||||
class JavaChecker : public QObject {
|
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit JavaChecker(QObject* parent = 0);
|
using QProcessPtr = shared_qobject_ptr<QProcess>;
|
||||||
void performCheck();
|
using Ptr = shared_qobject_ptr<JavaChecker>;
|
||||||
|
|
||||||
QString m_path;
|
struct Result {
|
||||||
QString m_args;
|
QString path;
|
||||||
int m_id = 0;
|
int id;
|
||||||
int m_minMem = 0;
|
QString mojangPlatform;
|
||||||
int m_maxMem = 0;
|
QString realPlatform;
|
||||||
int m_permGen = 64;
|
JavaVersion javaVersion;
|
||||||
|
QString javaVendor;
|
||||||
|
QString outLog;
|
||||||
|
QString errorLog;
|
||||||
|
bool is_64bit = false;
|
||||||
|
enum class Validity { Errored, ReturnedInvalidData, Valid } validity = Validity::Errored;
|
||||||
|
};
|
||||||
|
|
||||||
|
explicit JavaChecker(QString path, QString args, int minMem = 0, int maxMem = 0, int permGen = 0, int id = 0, QObject* parent = 0);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void checkFinished(JavaCheckResult result);
|
void checkFinished(const Result& result);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void executeTask() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QProcessPtr process;
|
QProcessPtr process;
|
||||||
QTimer killTimer;
|
QTimer killTimer;
|
||||||
QString m_stdout;
|
QString m_stdout;
|
||||||
QString m_stderr;
|
QString m_stderr;
|
||||||
public slots:
|
|
||||||
|
QString m_path;
|
||||||
|
QString m_args;
|
||||||
|
int m_minMem = 0;
|
||||||
|
int m_maxMem = 0;
|
||||||
|
int m_permGen = 64;
|
||||||
|
int m_id = 0;
|
||||||
|
|
||||||
|
private slots:
|
||||||
void timeout();
|
void timeout();
|
||||||
void finished(int exitcode, QProcess::ExitStatus);
|
void finished(int exitcode, QProcess::ExitStatus);
|
||||||
void error(QProcess::ProcessError);
|
void error(QProcess::ProcessError);
|
||||||
|
@ -1,41 +0,0 @@
|
|||||||
/* 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 "JavaCheckerJob.h"
|
|
||||||
|
|
||||||
#include <QDebug>
|
|
||||||
|
|
||||||
void JavaCheckerJob::partFinished(JavaCheckResult result)
|
|
||||||
{
|
|
||||||
num_finished++;
|
|
||||||
qDebug() << m_job_name.toLocal8Bit() << "progress:" << num_finished << "/" << javacheckers.size();
|
|
||||||
setProgress(num_finished, javacheckers.size());
|
|
||||||
|
|
||||||
javaresults.replace(result.id, result);
|
|
||||||
|
|
||||||
if (num_finished == javacheckers.size()) {
|
|
||||||
emitSucceeded();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void JavaCheckerJob::executeTask()
|
|
||||||
{
|
|
||||||
qDebug() << m_job_name.toLocal8Bit() << " started.";
|
|
||||||
for (auto iter : javacheckers) {
|
|
||||||
javaresults.append(JavaCheckResult());
|
|
||||||
connect(iter.get(), &JavaChecker::checkFinished, this, &JavaCheckerJob::partFinished);
|
|
||||||
iter->performCheck();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,56 +0,0 @@
|
|||||||
/* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <QtNetwork>
|
|
||||||
#include "JavaChecker.h"
|
|
||||||
#include "tasks/Task.h"
|
|
||||||
|
|
||||||
class JavaCheckerJob;
|
|
||||||
using JavaCheckerJobPtr = shared_qobject_ptr<JavaCheckerJob>;
|
|
||||||
|
|
||||||
// FIXME: this just seems horribly redundant
|
|
||||||
class JavaCheckerJob : public Task {
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
explicit JavaCheckerJob(QString job_name) : Task(), m_job_name(job_name) {};
|
|
||||||
virtual ~JavaCheckerJob() {};
|
|
||||||
|
|
||||||
bool addJavaCheckerAction(JavaCheckerPtr base)
|
|
||||||
{
|
|
||||||
javacheckers.append(base);
|
|
||||||
// if this is already running, the action needs to be started right away!
|
|
||||||
if (isRunning()) {
|
|
||||||
setProgress(num_finished, javacheckers.size());
|
|
||||||
connect(base.get(), &JavaChecker::checkFinished, this, &JavaCheckerJob::partFinished);
|
|
||||||
base->performCheck();
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
QList<JavaCheckResult> getResults() { return javaresults; }
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
void partFinished(JavaCheckResult result);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual void executeTask() override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
QString m_job_name;
|
|
||||||
QList<JavaCheckerPtr> javacheckers;
|
|
||||||
QList<JavaCheckResult> javaresults;
|
|
||||||
int num_finished = 0;
|
|
||||||
};
|
|
@ -1,7 +1,7 @@
|
|||||||
// SPDX-License-Identifier: GPL-3.0-only
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
/*
|
/*
|
||||||
* Prism Launcher - Minecraft Launcher
|
* Prism Launcher - Minecraft Launcher
|
||||||
* Copyright (c) 2023 Trial97 <alexandru.tripon97@gmail.com>
|
* Copyright (c) 2023-2024 Trial97 <alexandru.tripon97@gmail.com>
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// SPDX-License-Identifier: GPL-3.0-only
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
/*
|
/*
|
||||||
* Prism Launcher - Minecraft Launcher
|
* Prism Launcher - Minecraft Launcher
|
||||||
* Copyright (c) 2023 Trial97 <alexandru.tripon97@gmail.com>
|
* Copyright (c) 2023-2024 Trial97 <alexandru.tripon97@gmail.com>
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -40,6 +40,7 @@ struct JavaInstall : public BaseVersion {
|
|||||||
QString arch;
|
QString arch;
|
||||||
QString path;
|
QString path;
|
||||||
bool recommended = false;
|
bool recommended = false;
|
||||||
|
bool is_64bit = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
using JavaInstallPtr = std::shared_ptr<JavaInstall>;
|
using JavaInstallPtr = std::shared_ptr<JavaInstall>;
|
||||||
|
@ -38,13 +38,17 @@
|
|||||||
#include <QtXml>
|
#include <QtXml>
|
||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
#include "java/JavaCheckerJob.h"
|
#include "Application.h"
|
||||||
|
#include "java/JavaChecker.h"
|
||||||
#include "java/JavaInstallList.h"
|
#include "java/JavaInstallList.h"
|
||||||
#include "java/JavaUtils.h"
|
#include "java/JavaUtils.h"
|
||||||
#include "minecraft/VersionFilterData.h"
|
#include "tasks/ConcurrentTask.h"
|
||||||
|
|
||||||
JavaInstallList::JavaInstallList(QObject* parent) : BaseVersionList(parent) {}
|
JavaInstallList::JavaInstallList(QObject* parent, bool onlyManagedVersions)
|
||||||
|
: BaseVersionList(parent), m_only_managed_versions(onlyManagedVersions)
|
||||||
|
{}
|
||||||
|
|
||||||
Task::Ptr JavaInstallList::getLoadTask()
|
Task::Ptr JavaInstallList::getLoadTask()
|
||||||
{
|
{
|
||||||
@ -55,7 +59,7 @@ Task::Ptr JavaInstallList::getLoadTask()
|
|||||||
Task::Ptr JavaInstallList::getCurrentTask()
|
Task::Ptr JavaInstallList::getCurrentTask()
|
||||||
{
|
{
|
||||||
if (m_status == Status::InProgress) {
|
if (m_status == Status::InProgress) {
|
||||||
return m_loadTask;
|
return m_load_task;
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@ -64,8 +68,8 @@ void JavaInstallList::load()
|
|||||||
{
|
{
|
||||||
if (m_status != Status::InProgress) {
|
if (m_status != Status::InProgress) {
|
||||||
m_status = Status::InProgress;
|
m_status = Status::InProgress;
|
||||||
m_loadTask.reset(new JavaListLoadTask(this));
|
m_load_task.reset(new JavaListLoadTask(this, m_only_managed_versions));
|
||||||
m_loadTask->start();
|
m_load_task->start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,7 +110,7 @@ QVariant JavaInstallList::data(const QModelIndex& index, int role) const
|
|||||||
return version->recommended;
|
return version->recommended;
|
||||||
case PathRole:
|
case PathRole:
|
||||||
return version->path;
|
return version->path;
|
||||||
case ArchitectureRole:
|
case CPUArchitectureRole:
|
||||||
return version->arch;
|
return version->arch;
|
||||||
default:
|
default:
|
||||||
return QVariant();
|
return QVariant();
|
||||||
@ -115,7 +119,7 @@ QVariant JavaInstallList::data(const QModelIndex& index, int role) const
|
|||||||
|
|
||||||
BaseVersionList::RoleList JavaInstallList::providesRoles() const
|
BaseVersionList::RoleList JavaInstallList::providesRoles() const
|
||||||
{
|
{
|
||||||
return { VersionPointerRole, VersionIdRole, VersionRole, RecommendedRole, PathRole, ArchitectureRole };
|
return { VersionPointerRole, VersionIdRole, VersionRole, RecommendedRole, PathRole, CPUArchitectureRole };
|
||||||
}
|
}
|
||||||
|
|
||||||
void JavaInstallList::updateListData(QList<BaseVersion::Ptr> versions)
|
void JavaInstallList::updateListData(QList<BaseVersion::Ptr> versions)
|
||||||
@ -129,7 +133,7 @@ void JavaInstallList::updateListData(QList<BaseVersion::Ptr> versions)
|
|||||||
}
|
}
|
||||||
endResetModel();
|
endResetModel();
|
||||||
m_status = Status::Done;
|
m_status = Status::Done;
|
||||||
m_loadTask.reset();
|
m_load_task.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sortJavas(BaseVersion::Ptr left, BaseVersion::Ptr right)
|
bool sortJavas(BaseVersion::Ptr left, BaseVersion::Ptr right)
|
||||||
@ -146,35 +150,30 @@ void JavaInstallList::sortVersions()
|
|||||||
endResetModel();
|
endResetModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
JavaListLoadTask::JavaListLoadTask(JavaInstallList* vlist) : Task()
|
JavaListLoadTask::JavaListLoadTask(JavaInstallList* vlist, bool onlyManagedVersions) : Task(), m_only_managed_versions(onlyManagedVersions)
|
||||||
{
|
{
|
||||||
m_list = vlist;
|
m_list = vlist;
|
||||||
m_currentRecommended = NULL;
|
m_current_recommended = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
JavaListLoadTask::~JavaListLoadTask() {}
|
|
||||||
|
|
||||||
void JavaListLoadTask::executeTask()
|
void JavaListLoadTask::executeTask()
|
||||||
{
|
{
|
||||||
setStatus(tr("Detecting Java installations..."));
|
setStatus(tr("Detecting Java installations..."));
|
||||||
|
|
||||||
JavaUtils ju;
|
JavaUtils ju;
|
||||||
QList<QString> candidate_paths = ju.FindJavaPaths();
|
QList<QString> candidate_paths = m_only_managed_versions ? getPrismJavaBundle() : ju.FindJavaPaths();
|
||||||
|
|
||||||
m_job.reset(new JavaCheckerJob("Java detection"));
|
ConcurrentTask::Ptr job(new ConcurrentTask(this, "Java detection", APPLICATION->settings()->get("NumberOfConcurrentTasks").toInt()));
|
||||||
|
m_job.reset(job);
|
||||||
connect(m_job.get(), &Task::finished, this, &JavaListLoadTask::javaCheckerFinished);
|
connect(m_job.get(), &Task::finished, this, &JavaListLoadTask::javaCheckerFinished);
|
||||||
connect(m_job.get(), &Task::progress, this, &Task::setProgress);
|
connect(m_job.get(), &Task::progress, this, &Task::setProgress);
|
||||||
|
|
||||||
qDebug() << "Probing the following Java paths: ";
|
qDebug() << "Probing the following Java paths: ";
|
||||||
int id = 0;
|
int id = 0;
|
||||||
for (QString candidate : candidate_paths) {
|
for (QString candidate : candidate_paths) {
|
||||||
qDebug() << " " << candidate;
|
auto checker = new JavaChecker(candidate, "", 0, 0, 0, id, this);
|
||||||
|
connect(checker, &JavaChecker::checkFinished, [this](const JavaChecker::Result& result) { m_results << result; });
|
||||||
auto candidate_checker = new JavaChecker();
|
job->addTask(Task::Ptr(checker));
|
||||||
candidate_checker->m_path = candidate;
|
|
||||||
candidate_checker->m_id = id;
|
|
||||||
m_job->addJavaCheckerAction(JavaCheckerPtr(candidate_checker));
|
|
||||||
|
|
||||||
id++;
|
id++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -184,16 +183,17 @@ void JavaListLoadTask::executeTask()
|
|||||||
void JavaListLoadTask::javaCheckerFinished()
|
void JavaListLoadTask::javaCheckerFinished()
|
||||||
{
|
{
|
||||||
QList<JavaInstallPtr> candidates;
|
QList<JavaInstallPtr> candidates;
|
||||||
auto results = m_job->getResults();
|
std::sort(m_results.begin(), m_results.end(), [](const JavaChecker::Result& a, const JavaChecker::Result& b) { return a.id < b.id; });
|
||||||
|
|
||||||
qDebug() << "Found the following valid Java installations:";
|
qDebug() << "Found the following valid Java installations:";
|
||||||
for (JavaCheckResult result : results) {
|
for (auto result : m_results) {
|
||||||
if (result.validity == JavaCheckResult::Validity::Valid) {
|
if (result.validity == JavaChecker::Result::Validity::Valid) {
|
||||||
JavaInstallPtr javaVersion(new JavaInstall());
|
JavaInstallPtr javaVersion(new JavaInstall());
|
||||||
|
|
||||||
javaVersion->id = result.javaVersion;
|
javaVersion->id = result.javaVersion;
|
||||||
javaVersion->arch = result.realPlatform;
|
javaVersion->arch = result.realPlatform;
|
||||||
javaVersion->path = result.path;
|
javaVersion->path = result.path;
|
||||||
|
javaVersion->is_64bit = result.is_64bit;
|
||||||
candidates.append(javaVersion);
|
candidates.append(javaVersion);
|
||||||
|
|
||||||
qDebug() << " " << javaVersion->id.toString() << javaVersion->arch << javaVersion->path;
|
qDebug() << " " << javaVersion->id.toString() << javaVersion->arch << javaVersion->path;
|
||||||
|
@ -19,9 +19,9 @@
|
|||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
|
||||||
#include "BaseVersionList.h"
|
#include "BaseVersionList.h"
|
||||||
|
#include "java/JavaChecker.h"
|
||||||
#include "tasks/Task.h"
|
#include "tasks/Task.h"
|
||||||
|
|
||||||
#include "JavaCheckerJob.h"
|
|
||||||
#include "JavaInstall.h"
|
#include "JavaInstall.h"
|
||||||
|
|
||||||
#include "QObjectPtr.h"
|
#include "QObjectPtr.h"
|
||||||
@ -33,7 +33,7 @@ class JavaInstallList : public BaseVersionList {
|
|||||||
enum class Status { NotDone, InProgress, Done };
|
enum class Status { NotDone, InProgress, Done };
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit JavaInstallList(QObject* parent = 0);
|
explicit JavaInstallList(QObject* parent = 0, bool onlyManagedVersions = false);
|
||||||
|
|
||||||
[[nodiscard]] Task::Ptr getLoadTask() override;
|
[[nodiscard]] Task::Ptr getLoadTask() override;
|
||||||
bool isLoaded() override;
|
bool isLoaded() override;
|
||||||
@ -53,23 +53,27 @@ class JavaInstallList : public BaseVersionList {
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
Status m_status = Status::NotDone;
|
Status m_status = Status::NotDone;
|
||||||
shared_qobject_ptr<JavaListLoadTask> m_loadTask;
|
shared_qobject_ptr<JavaListLoadTask> m_load_task;
|
||||||
QList<BaseVersion::Ptr> m_vlist;
|
QList<BaseVersion::Ptr> m_vlist;
|
||||||
|
bool m_only_managed_versions;
|
||||||
};
|
};
|
||||||
|
|
||||||
class JavaListLoadTask : public Task {
|
class JavaListLoadTask : public Task {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit JavaListLoadTask(JavaInstallList* vlist);
|
explicit JavaListLoadTask(JavaInstallList* vlist, bool onlyManagedVersions = false);
|
||||||
virtual ~JavaListLoadTask();
|
virtual ~JavaListLoadTask() = default;
|
||||||
|
|
||||||
|
protected:
|
||||||
void executeTask() override;
|
void executeTask() override;
|
||||||
public slots:
|
public slots:
|
||||||
void javaCheckerFinished();
|
void javaCheckerFinished();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
shared_qobject_ptr<JavaCheckerJob> m_job;
|
Task::Ptr m_job;
|
||||||
JavaInstallList* m_list;
|
JavaInstallList* m_list;
|
||||||
JavaInstall* m_currentRecommended;
|
JavaInstall* m_current_recommended;
|
||||||
|
QList<JavaChecker::Result> m_results;
|
||||||
|
bool m_only_managed_versions;
|
||||||
};
|
};
|
||||||
|
128
launcher/java/JavaMetadata.cpp
Normal file
128
launcher/java/JavaMetadata.cpp
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
/*
|
||||||
|
* Prism Launcher - Minecraft Launcher
|
||||||
|
* Copyright (c) 2023-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 "java/JavaMetadata.h"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "Json.h"
|
||||||
|
#include "StringUtils.h"
|
||||||
|
#include "java/JavaVersion.h"
|
||||||
|
#include "minecraft/ParseUtils.h"
|
||||||
|
|
||||||
|
namespace Java {
|
||||||
|
|
||||||
|
DownloadType parseDownloadType(QString javaDownload)
|
||||||
|
{
|
||||||
|
if (javaDownload == "manifest")
|
||||||
|
return DownloadType::Manifest;
|
||||||
|
else if (javaDownload == "archive")
|
||||||
|
return DownloadType::Archive;
|
||||||
|
else
|
||||||
|
return DownloadType::Unknown;
|
||||||
|
}
|
||||||
|
QString downloadTypeToString(DownloadType javaDownload)
|
||||||
|
{
|
||||||
|
switch (javaDownload) {
|
||||||
|
case DownloadType::Manifest:
|
||||||
|
return "manifest";
|
||||||
|
case DownloadType::Archive:
|
||||||
|
return "archive";
|
||||||
|
case DownloadType::Unknown:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return "unknown";
|
||||||
|
}
|
||||||
|
MetadataPtr parseJavaMeta(const QJsonObject& in)
|
||||||
|
{
|
||||||
|
auto meta = std::make_shared<Metadata>();
|
||||||
|
|
||||||
|
meta->m_name = Json::ensureString(in, "name", "");
|
||||||
|
meta->vendor = Json::ensureString(in, "vendor", "");
|
||||||
|
meta->url = Json::ensureString(in, "url", "");
|
||||||
|
meta->releaseTime = timeFromS3Time(Json::ensureString(in, "releaseTime", ""));
|
||||||
|
meta->downloadType = parseDownloadType(Json::ensureString(in, "downloadType", ""));
|
||||||
|
meta->packageType = Json::ensureString(in, "packageType", "");
|
||||||
|
meta->runtimeOS = Json::ensureString(in, "runtimeOS", "unknown");
|
||||||
|
|
||||||
|
if (in.contains("checksum")) {
|
||||||
|
auto obj = Json::requireObject(in, "checksum");
|
||||||
|
meta->checksumHash = Json::ensureString(obj, "hash", "");
|
||||||
|
meta->checksumType = Json::ensureString(obj, "type", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (in.contains("version")) {
|
||||||
|
auto obj = Json::requireObject(in, "version");
|
||||||
|
auto name = Json::ensureString(obj, "name", "");
|
||||||
|
auto major = Json::ensureInteger(obj, "major", 0);
|
||||||
|
auto minor = Json::ensureInteger(obj, "minor", 0);
|
||||||
|
auto security = Json::ensureInteger(obj, "security", 0);
|
||||||
|
auto build = Json::ensureInteger(obj, "build", 0);
|
||||||
|
meta->version = JavaVersion(major, minor, security, build, name);
|
||||||
|
}
|
||||||
|
return meta;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Metadata::operator<(const Metadata& rhs)
|
||||||
|
{
|
||||||
|
auto id = version;
|
||||||
|
if (id < rhs.version) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (id > rhs.version) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
auto date = releaseTime;
|
||||||
|
if (date < rhs.releaseTime) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (date > rhs.releaseTime) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return StringUtils::naturalCompare(m_name, rhs.m_name, Qt::CaseInsensitive) < 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Metadata::operator==(const Metadata& rhs)
|
||||||
|
{
|
||||||
|
return version == rhs.version && m_name == rhs.m_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Metadata::operator>(const Metadata& rhs)
|
||||||
|
{
|
||||||
|
return (!operator<(rhs)) && (!operator==(rhs));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Metadata::operator<(BaseVersion& a)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
return operator<(dynamic_cast<Metadata&>(a));
|
||||||
|
} catch (const std::bad_cast& e) {
|
||||||
|
return BaseVersion::operator<(a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Metadata::operator>(BaseVersion& a)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
return operator>(dynamic_cast<Metadata&>(a));
|
||||||
|
} catch (const std::bad_cast& e) {
|
||||||
|
return BaseVersion::operator>(a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Java
|
64
launcher/java/JavaMetadata.h
Normal file
64
launcher/java/JavaMetadata.h
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
/*
|
||||||
|
* Prism Launcher - Minecraft Launcher
|
||||||
|
* Copyright (c) 2023-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 <QDateTime>
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "BaseVersion.h"
|
||||||
|
#include "java/JavaVersion.h"
|
||||||
|
|
||||||
|
namespace Java {
|
||||||
|
|
||||||
|
enum class DownloadType { Manifest, Archive, Unknown };
|
||||||
|
|
||||||
|
class Metadata : public BaseVersion {
|
||||||
|
public:
|
||||||
|
virtual QString descriptor() override { return version.toString(); }
|
||||||
|
|
||||||
|
virtual QString name() override { return m_name; }
|
||||||
|
|
||||||
|
virtual QString typeString() const override { return vendor; }
|
||||||
|
|
||||||
|
virtual bool operator<(BaseVersion& a) override;
|
||||||
|
virtual bool operator>(BaseVersion& a) override;
|
||||||
|
bool operator<(const Metadata& rhs);
|
||||||
|
bool operator==(const Metadata& rhs);
|
||||||
|
bool operator>(const Metadata& rhs);
|
||||||
|
|
||||||
|
QString m_name;
|
||||||
|
QString vendor;
|
||||||
|
QString url;
|
||||||
|
QDateTime releaseTime;
|
||||||
|
QString checksumType;
|
||||||
|
QString checksumHash;
|
||||||
|
DownloadType downloadType;
|
||||||
|
QString packageType;
|
||||||
|
JavaVersion version;
|
||||||
|
QString runtimeOS;
|
||||||
|
};
|
||||||
|
using MetadataPtr = std::shared_ptr<Metadata>;
|
||||||
|
|
||||||
|
DownloadType parseDownloadType(QString javaDownload);
|
||||||
|
QString downloadTypeToString(DownloadType javaDownload);
|
||||||
|
MetadataPtr parseJavaMeta(const QJsonObject& libObj);
|
||||||
|
|
||||||
|
} // namespace Java
|
@ -347,6 +347,7 @@ QList<QString> JavaUtils::FindJavaPaths()
|
|||||||
}
|
}
|
||||||
|
|
||||||
candidates.append(getMinecraftJavaBundle());
|
candidates.append(getMinecraftJavaBundle());
|
||||||
|
candidates.append(getPrismJavaBundle());
|
||||||
candidates = addJavasFromEnv(candidates);
|
candidates = addJavasFromEnv(candidates);
|
||||||
candidates.removeDuplicates();
|
candidates.removeDuplicates();
|
||||||
return candidates;
|
return candidates;
|
||||||
@ -391,6 +392,7 @@ QList<QString> JavaUtils::FindJavaPaths()
|
|||||||
}
|
}
|
||||||
|
|
||||||
javas.append(getMinecraftJavaBundle());
|
javas.append(getMinecraftJavaBundle());
|
||||||
|
javas.append(getPrismJavaBundle());
|
||||||
javas = addJavasFromEnv(javas);
|
javas = addJavasFromEnv(javas);
|
||||||
javas.removeDuplicates();
|
javas.removeDuplicates();
|
||||||
return javas;
|
return javas;
|
||||||
@ -454,6 +456,7 @@ QList<QString> JavaUtils::FindJavaPaths()
|
|||||||
scanJavaDirs(FS::PathCombine(home, ".gradle/jdks"));
|
scanJavaDirs(FS::PathCombine(home, ".gradle/jdks"));
|
||||||
|
|
||||||
javas.append(getMinecraftJavaBundle());
|
javas.append(getMinecraftJavaBundle());
|
||||||
|
javas.append(getPrismJavaBundle());
|
||||||
javas = addJavasFromEnv(javas);
|
javas = addJavasFromEnv(javas);
|
||||||
javas.removeDuplicates();
|
javas.removeDuplicates();
|
||||||
return javas;
|
return javas;
|
||||||
@ -467,6 +470,8 @@ QList<QString> JavaUtils::FindJavaPaths()
|
|||||||
javas.append(this->GetDefaultJava()->path);
|
javas.append(this->GetDefaultJava()->path);
|
||||||
|
|
||||||
javas.append(getMinecraftJavaBundle());
|
javas.append(getMinecraftJavaBundle());
|
||||||
|
javas.append(getPrismJavaBundle());
|
||||||
|
javas.removeDuplicates();
|
||||||
return addJavasFromEnv(javas);
|
return addJavasFromEnv(javas);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -478,12 +483,10 @@ QString JavaUtils::getJavaCheckPath()
|
|||||||
|
|
||||||
QStringList getMinecraftJavaBundle()
|
QStringList getMinecraftJavaBundle()
|
||||||
{
|
{
|
||||||
QString executable = "java";
|
|
||||||
QStringList processpaths;
|
QStringList processpaths;
|
||||||
#if defined(Q_OS_OSX)
|
#if defined(Q_OS_OSX)
|
||||||
processpaths << FS::PathCombine(QDir::homePath(), FS::PathCombine("Library", "Application Support", "minecraft", "runtime"));
|
processpaths << FS::PathCombine(QDir::homePath(), FS::PathCombine("Library", "Application Support", "minecraft", "runtime"));
|
||||||
#elif defined(Q_OS_WIN32)
|
#elif defined(Q_OS_WIN32)
|
||||||
executable += "w.exe";
|
|
||||||
|
|
||||||
auto appDataPath = QProcessEnvironment::systemEnvironment().value("APPDATA", "");
|
auto appDataPath = QProcessEnvironment::systemEnvironment().value("APPDATA", "");
|
||||||
processpaths << FS::PathCombine(QFileInfo(appDataPath).absoluteFilePath(), ".minecraft", "runtime");
|
processpaths << FS::PathCombine(QFileInfo(appDataPath).absoluteFilePath(), ".minecraft", "runtime");
|
||||||
@ -508,7 +511,7 @@ QStringList getMinecraftJavaBundle()
|
|||||||
auto binFound = false;
|
auto binFound = false;
|
||||||
for (auto& entry : entries) {
|
for (auto& entry : entries) {
|
||||||
if (entry.baseName() == "bin") {
|
if (entry.baseName() == "bin") {
|
||||||
javas.append(FS::PathCombine(entry.canonicalFilePath(), executable));
|
javas.append(FS::PathCombine(entry.canonicalFilePath(), JavaUtils::javaExecutable));
|
||||||
binFound = true;
|
binFound = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -521,3 +524,33 @@ QStringList getMinecraftJavaBundle()
|
|||||||
}
|
}
|
||||||
return javas;
|
return javas;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(Q_OS_WIN32)
|
||||||
|
const QString JavaUtils::javaExecutable = "javaw.exe";
|
||||||
|
#else
|
||||||
|
const QString JavaUtils::javaExecutable = "java";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
QStringList getPrismJavaBundle()
|
||||||
|
{
|
||||||
|
QList<QString> javas;
|
||||||
|
|
||||||
|
auto scanDir = [&](QString prefix) {
|
||||||
|
javas.append(FS::PathCombine(prefix, "jre", "bin", JavaUtils::javaExecutable));
|
||||||
|
javas.append(FS::PathCombine(prefix, "bin", JavaUtils::javaExecutable));
|
||||||
|
javas.append(FS::PathCombine(prefix, JavaUtils::javaExecutable));
|
||||||
|
};
|
||||||
|
auto scanJavaDir = [&](const QString& dirPath) {
|
||||||
|
QDir dir(dirPath);
|
||||||
|
if (!dir.exists())
|
||||||
|
return;
|
||||||
|
auto entries = dir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot);
|
||||||
|
for (auto& entry : entries) {
|
||||||
|
scanDir(entry.canonicalFilePath());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
scanJavaDir(APPLICATION->javaPath());
|
||||||
|
|
||||||
|
return javas;
|
||||||
|
}
|
||||||
|
@ -15,10 +15,9 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <QProcess>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
|
#include "java/JavaInstall.h"
|
||||||
#include "JavaChecker.h"
|
|
||||||
#include "JavaInstallList.h"
|
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
@ -27,6 +26,7 @@
|
|||||||
QString stripVariableEntries(QString name, QString target, QString remove);
|
QString stripVariableEntries(QString name, QString target, QString remove);
|
||||||
QProcessEnvironment CleanEnviroment();
|
QProcessEnvironment CleanEnviroment();
|
||||||
QStringList getMinecraftJavaBundle();
|
QStringList getMinecraftJavaBundle();
|
||||||
|
QStringList getPrismJavaBundle();
|
||||||
|
|
||||||
class JavaUtils : public QObject {
|
class JavaUtils : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@ -42,4 +42,5 @@ class JavaUtils : public QObject {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
static QString getJavaCheckPath();
|
static QString getJavaCheckPath();
|
||||||
|
static const QString javaExecutable;
|
||||||
};
|
};
|
||||||
|
@ -43,12 +43,12 @@ QString JavaVersion::toString() const
|
|||||||
return m_string;
|
return m_string;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool JavaVersion::requiresPermGen()
|
bool JavaVersion::requiresPermGen() const
|
||||||
{
|
{
|
||||||
return !m_parseable || m_major < 8;
|
return !m_parseable || m_major < 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool JavaVersion::isModular()
|
bool JavaVersion::isModular() const
|
||||||
{
|
{
|
||||||
return m_parseable && m_major >= 9;
|
return m_parseable && m_major >= 9;
|
||||||
}
|
}
|
||||||
@ -59,12 +59,6 @@ bool JavaVersion::operator<(const JavaVersion& rhs)
|
|||||||
auto major = m_major;
|
auto major = m_major;
|
||||||
auto rmajor = rhs.m_major;
|
auto rmajor = rhs.m_major;
|
||||||
|
|
||||||
// HACK: discourage using java 9
|
|
||||||
if (major > 8)
|
|
||||||
major = -major;
|
|
||||||
if (rmajor > 8)
|
|
||||||
rmajor = -rmajor;
|
|
||||||
|
|
||||||
if (major < rmajor)
|
if (major < rmajor)
|
||||||
return true;
|
return true;
|
||||||
if (major > rmajor)
|
if (major > rmajor)
|
||||||
@ -109,3 +103,24 @@ bool JavaVersion::operator>(const JavaVersion& rhs)
|
|||||||
{
|
{
|
||||||
return (!operator<(rhs)) && (!operator==(rhs));
|
return (!operator<(rhs)) && (!operator==(rhs));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
QStringList versions;
|
||||||
|
if (build != 0) {
|
||||||
|
m_prerelease = QString::number(build);
|
||||||
|
versions.push_front(m_prerelease);
|
||||||
|
}
|
||||||
|
if (m_security != 0)
|
||||||
|
versions.push_front(QString::number(m_security));
|
||||||
|
else if (!versions.isEmpty())
|
||||||
|
versions.push_front("0");
|
||||||
|
|
||||||
|
if (m_minor != 0)
|
||||||
|
versions.push_front(QString::number(m_minor));
|
||||||
|
else if (!versions.isEmpty())
|
||||||
|
versions.push_front("0");
|
||||||
|
versions.push_front(QString::number(m_major));
|
||||||
|
m_string = versions.join(".");
|
||||||
|
}
|
||||||
|
@ -16,6 +16,7 @@ class JavaVersion {
|
|||||||
public:
|
public:
|
||||||
JavaVersion() {}
|
JavaVersion() {}
|
||||||
JavaVersion(const QString& rhs);
|
JavaVersion(const QString& rhs);
|
||||||
|
JavaVersion(int major, int minor, int security, int build = 0, QString name = "");
|
||||||
|
|
||||||
JavaVersion& operator=(const QString& rhs);
|
JavaVersion& operator=(const QString& rhs);
|
||||||
|
|
||||||
@ -23,21 +24,24 @@ class JavaVersion {
|
|||||||
bool operator==(const JavaVersion& rhs);
|
bool operator==(const JavaVersion& rhs);
|
||||||
bool operator>(const JavaVersion& rhs);
|
bool operator>(const JavaVersion& rhs);
|
||||||
|
|
||||||
bool requiresPermGen();
|
bool requiresPermGen() const;
|
||||||
|
|
||||||
bool isModular();
|
bool isModular() const;
|
||||||
|
|
||||||
QString toString() const;
|
QString toString() const;
|
||||||
|
|
||||||
int major() { return m_major; }
|
int major() const { return m_major; }
|
||||||
int minor() { return m_minor; }
|
int minor() const { return m_minor; }
|
||||||
int security() { return m_security; }
|
int security() const { return m_security; }
|
||||||
|
QString build() const { return m_prerelease; }
|
||||||
|
QString name() const { return m_name; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QString m_string;
|
QString m_string;
|
||||||
int m_major = 0;
|
int m_major = 0;
|
||||||
int m_minor = 0;
|
int m_minor = 0;
|
||||||
int m_security = 0;
|
int m_security = 0;
|
||||||
|
QString m_name = "";
|
||||||
bool m_parseable = false;
|
bool m_parseable = false;
|
||||||
QString m_prerelease;
|
QString m_prerelease;
|
||||||
};
|
};
|
||||||
|
141
launcher/java/download/ArchiveDownloadTask.cpp
Normal file
141
launcher/java/download/ArchiveDownloadTask.cpp
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
/*
|
||||||
|
* Prism Launcher - Minecraft Launcher
|
||||||
|
* Copyright (c) 2023-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 "java/download/ArchiveDownloadTask.h"
|
||||||
|
#include <quazip.h>
|
||||||
|
#include <memory>
|
||||||
|
#include "MMCZip.h"
|
||||||
|
|
||||||
|
#include "Application.h"
|
||||||
|
#include "Untar.h"
|
||||||
|
#include "net/ChecksumValidator.h"
|
||||||
|
#include "net/NetJob.h"
|
||||||
|
#include "tasks/Task.h"
|
||||||
|
|
||||||
|
namespace Java {
|
||||||
|
ArchiveDownloadTask::ArchiveDownloadTask(QUrl url, QString final_path, QString checksumType, QString checksumHash)
|
||||||
|
: m_url(url), m_final_path(final_path), m_checksum_type(checksumType), m_checksum_hash(checksumHash)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void ArchiveDownloadTask::executeTask()
|
||||||
|
{
|
||||||
|
// JRE found ! download the zip
|
||||||
|
setStatus(tr("Downloading Java"));
|
||||||
|
|
||||||
|
MetaEntryPtr entry = APPLICATION->metacache()->resolveEntry("java", m_url.fileName());
|
||||||
|
|
||||||
|
auto download = makeShared<NetJob>(QString("JRE::DownloadJava"), APPLICATION->network());
|
||||||
|
auto action = Net::Download::makeCached(m_url, entry);
|
||||||
|
if (!m_checksum_hash.isEmpty() && !m_checksum_type.isEmpty()) {
|
||||||
|
auto hashType = QCryptographicHash::Algorithm::Sha1;
|
||||||
|
if (m_checksum_type == "sha256") {
|
||||||
|
hashType = QCryptographicHash::Algorithm::Sha256;
|
||||||
|
}
|
||||||
|
action->addValidator(new Net::ChecksumValidator(hashType, QByteArray::fromHex(m_checksum_hash.toUtf8())));
|
||||||
|
}
|
||||||
|
download->addNetAction(action);
|
||||||
|
auto fullPath = entry->getFullPath();
|
||||||
|
|
||||||
|
connect(download.get(), &Task::failed, this, &ArchiveDownloadTask::emitFailed);
|
||||||
|
connect(download.get(), &Task::progress, this, &ArchiveDownloadTask::setProgress);
|
||||||
|
connect(download.get(), &Task::stepProgress, this, &ArchiveDownloadTask::propagateStepProgress);
|
||||||
|
connect(download.get(), &Task::status, this, &ArchiveDownloadTask::setStatus);
|
||||||
|
connect(download.get(), &Task::details, this, &ArchiveDownloadTask::setDetails);
|
||||||
|
connect(download.get(), &Task::succeeded, [this, fullPath] {
|
||||||
|
// This should do all of the extracting and creating folders
|
||||||
|
extractJava(fullPath);
|
||||||
|
});
|
||||||
|
m_task = download;
|
||||||
|
m_task->start();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ArchiveDownloadTask::extractJava(QString input)
|
||||||
|
{
|
||||||
|
setStatus(tr("Extracting java"));
|
||||||
|
if (input.endsWith("tar")) {
|
||||||
|
setStatus(tr("Extracting Java (Progress is not reported for tar archives)"));
|
||||||
|
QFile in(input);
|
||||||
|
if (!in.open(QFile::ReadOnly)) {
|
||||||
|
emitFailed(tr("Unable to open supplied tar file."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!Tar::extract(&in, QDir(m_final_path).absolutePath())) {
|
||||||
|
emitFailed(tr("Unable to extract supplied tar file."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
emitSucceeded();
|
||||||
|
return;
|
||||||
|
} else if (input.endsWith("tar.gz") || input.endsWith("taz") || input.endsWith("tgz")) {
|
||||||
|
setStatus(tr("Extracting Java (Progress is not reported for tar archives)"));
|
||||||
|
if (!GZTar::extract(input, QDir(m_final_path).absolutePath())) {
|
||||||
|
emitFailed(tr("Unable to extract supplied tar file."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
emitSucceeded();
|
||||||
|
return;
|
||||||
|
} else if (input.endsWith("zip")) {
|
||||||
|
auto zip = std::make_shared<QuaZip>(input);
|
||||||
|
if (!zip->open(QuaZip::mdUnzip)) {
|
||||||
|
emitFailed(tr("Unable to open supplied zip file."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto files = zip->getFileNameList();
|
||||||
|
if (files.isEmpty()) {
|
||||||
|
emitFailed(tr("No files were found in the supplied zip file,"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_task = makeShared<MMCZip::ExtractZipTask>(zip, m_final_path, files[0]);
|
||||||
|
|
||||||
|
auto progressStep = std::make_shared<TaskStepProgress>();
|
||||||
|
connect(m_task.get(), &Task::finished, this, [this, progressStep] {
|
||||||
|
progressStep->state = TaskStepState::Succeeded;
|
||||||
|
stepProgress(*progressStep);
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(m_task.get(), &Task::succeeded, this, &ArchiveDownloadTask::emitSucceeded);
|
||||||
|
connect(m_task.get(), &Task::aborted, this, &ArchiveDownloadTask::emitAborted);
|
||||||
|
connect(m_task.get(), &Task::failed, this, [this, progressStep](QString reason) {
|
||||||
|
progressStep->state = TaskStepState::Failed;
|
||||||
|
stepProgress(*progressStep);
|
||||||
|
emitFailed(reason);
|
||||||
|
});
|
||||||
|
connect(m_task.get(), &Task::stepProgress, this, &ArchiveDownloadTask::propagateStepProgress);
|
||||||
|
|
||||||
|
connect(m_task.get(), &Task::progress, this, [this, progressStep](qint64 current, qint64 total) {
|
||||||
|
progressStep->update(current, total);
|
||||||
|
stepProgress(*progressStep);
|
||||||
|
});
|
||||||
|
connect(m_task.get(), &Task::status, this, [this, progressStep](QString status) {
|
||||||
|
progressStep->status = status;
|
||||||
|
stepProgress(*progressStep);
|
||||||
|
});
|
||||||
|
m_task->start();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
emitFailed(tr("Could not determine archive type!"));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ArchiveDownloadTask::abort()
|
||||||
|
{
|
||||||
|
auto aborted = canAbort();
|
||||||
|
if (m_task)
|
||||||
|
aborted = m_task->abort();
|
||||||
|
emitAborted();
|
||||||
|
return aborted;
|
||||||
|
};
|
||||||
|
} // namespace Java
|
45
launcher/java/download/ArchiveDownloadTask.h
Normal file
45
launcher/java/download/ArchiveDownloadTask.h
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
/*
|
||||||
|
* Prism Launcher - Minecraft Launcher
|
||||||
|
* Copyright (c) 2023-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 <QUrl>
|
||||||
|
#include "tasks/Task.h"
|
||||||
|
|
||||||
|
namespace Java {
|
||||||
|
class ArchiveDownloadTask : public Task {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
ArchiveDownloadTask(QUrl url, QString final_path, QString checksumType = "", QString checksumHash = "");
|
||||||
|
virtual ~ArchiveDownloadTask() = default;
|
||||||
|
|
||||||
|
[[nodiscard]] bool canAbort() const override { return true; }
|
||||||
|
void executeTask() override;
|
||||||
|
virtual bool abort() override;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void extractJava(QString input);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
QUrl m_url;
|
||||||
|
QString m_final_path;
|
||||||
|
QString m_checksum_type;
|
||||||
|
QString m_checksum_hash;
|
||||||
|
Task::Ptr m_task;
|
||||||
|
};
|
||||||
|
} // namespace Java
|
138
launcher/java/download/ManifestDownloadTask.cpp
Normal file
138
launcher/java/download/ManifestDownloadTask.cpp
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
/*
|
||||||
|
* Prism Launcher - Minecraft Launcher
|
||||||
|
* Copyright (c) 2023-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 "java/download/ManifestDownloadTask.h"
|
||||||
|
|
||||||
|
#include "Application.h"
|
||||||
|
#include "FileSystem.h"
|
||||||
|
#include "Json.h"
|
||||||
|
#include "net/ChecksumValidator.h"
|
||||||
|
#include "net/NetJob.h"
|
||||||
|
|
||||||
|
struct File {
|
||||||
|
QString path;
|
||||||
|
QString url;
|
||||||
|
QByteArray hash;
|
||||||
|
bool isExec;
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace Java {
|
||||||
|
ManifestDownloadTask::ManifestDownloadTask(QUrl url, QString final_path, QString checksumType, QString checksumHash)
|
||||||
|
: m_url(url), m_final_path(final_path), m_checksum_type(checksumType), m_checksum_hash(checksumHash)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void ManifestDownloadTask::executeTask()
|
||||||
|
{
|
||||||
|
setStatus(tr("Downloading Java"));
|
||||||
|
auto download = makeShared<NetJob>(QString("JRE::DownloadJava"), APPLICATION->network());
|
||||||
|
auto files = std::make_shared<QByteArray>();
|
||||||
|
|
||||||
|
auto action = Net::Download::makeByteArray(m_url, files);
|
||||||
|
if (!m_checksum_hash.isEmpty() && !m_checksum_type.isEmpty()) {
|
||||||
|
auto hashType = QCryptographicHash::Algorithm::Sha1;
|
||||||
|
if (m_checksum_type == "sha256") {
|
||||||
|
hashType = QCryptographicHash::Algorithm::Sha256;
|
||||||
|
}
|
||||||
|
action->addValidator(new Net::ChecksumValidator(hashType, QByteArray::fromHex(m_checksum_hash.toUtf8())));
|
||||||
|
}
|
||||||
|
download->addNetAction(action);
|
||||||
|
|
||||||
|
connect(download.get(), &Task::failed, this, &ManifestDownloadTask::emitFailed);
|
||||||
|
connect(download.get(), &Task::progress, this, &ManifestDownloadTask::setProgress);
|
||||||
|
connect(download.get(), &Task::stepProgress, this, &ManifestDownloadTask::propagateStepProgress);
|
||||||
|
connect(download.get(), &Task::status, this, &ManifestDownloadTask::setStatus);
|
||||||
|
connect(download.get(), &Task::details, this, &ManifestDownloadTask::setDetails);
|
||||||
|
|
||||||
|
connect(download.get(), &Task::succeeded, [files, 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;
|
||||||
|
emitFailed(parse_error.errorString());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
downloadJava(doc);
|
||||||
|
});
|
||||||
|
m_task = download;
|
||||||
|
m_task->start();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ManifestDownloadTask::downloadJava(const QJsonDocument& doc)
|
||||||
|
{
|
||||||
|
// valid json doc, begin making jre spot
|
||||||
|
FS::ensureFolderPathExists(m_final_path);
|
||||||
|
std::vector<File> toDownload;
|
||||||
|
auto list = Json::ensureObject(Json::ensureObject(doc.object()), "files");
|
||||||
|
for (const auto& paths : list.keys()) {
|
||||||
|
auto file = FS::PathCombine(m_final_path, 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 = makeShared<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.get(), &Task::failed, this, &ManifestDownloadTask::emitFailed);
|
||||||
|
connect(elementDownload.get(), &Task::progress, this, &ManifestDownloadTask::setProgress);
|
||||||
|
connect(elementDownload.get(), &Task::stepProgress, this, &ManifestDownloadTask::propagateStepProgress);
|
||||||
|
connect(elementDownload.get(), &Task::status, this, &ManifestDownloadTask::setStatus);
|
||||||
|
connect(elementDownload.get(), &Task::details, this, &ManifestDownloadTask::setDetails);
|
||||||
|
|
||||||
|
connect(elementDownload.get(), &Task::succeeded, this, &ManifestDownloadTask::emitSucceeded);
|
||||||
|
m_task = elementDownload;
|
||||||
|
m_task->start();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ManifestDownloadTask::abort()
|
||||||
|
{
|
||||||
|
auto aborted = canAbort();
|
||||||
|
if (m_task)
|
||||||
|
aborted = m_task->abort();
|
||||||
|
emitAborted();
|
||||||
|
return aborted;
|
||||||
|
};
|
||||||
|
} // namespace Java
|
46
launcher/java/download/ManifestDownloadTask.h
Normal file
46
launcher/java/download/ManifestDownloadTask.h
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
/*
|
||||||
|
* Prism Launcher - Minecraft Launcher
|
||||||
|
* Copyright (c) 2023-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 <QUrl>
|
||||||
|
#include "tasks/Task.h"
|
||||||
|
|
||||||
|
namespace Java {
|
||||||
|
|
||||||
|
class ManifestDownloadTask : public Task {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
ManifestDownloadTask(QUrl url, QString final_path, QString checksumType = "", QString checksumHash = "");
|
||||||
|
virtual ~ManifestDownloadTask() = default;
|
||||||
|
|
||||||
|
[[nodiscard]] bool canAbort() const override { return true; }
|
||||||
|
void executeTask() override;
|
||||||
|
virtual bool abort() override;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void downloadJava(const QJsonDocument& doc);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
QUrl m_url;
|
||||||
|
QString m_final_path;
|
||||||
|
QString m_checksum_type;
|
||||||
|
QString m_checksum_hash;
|
||||||
|
Task::Ptr m_task;
|
||||||
|
};
|
||||||
|
} // namespace Java
|
@ -37,6 +37,7 @@
|
|||||||
#include <FileSystem.h>
|
#include <FileSystem.h>
|
||||||
#include <launch/LaunchTask.h>
|
#include <launch/LaunchTask.h>
|
||||||
#include <sys.h>
|
#include <sys.h>
|
||||||
|
#include <QCryptographicHash>
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
#include <QStandardPaths>
|
#include <QStandardPaths>
|
||||||
#include "java/JavaUtils.h"
|
#include "java/JavaUtils.h"
|
||||||
@ -93,11 +94,10 @@ void CheckJava::executeTask()
|
|||||||
// if timestamps are not the same, or something is missing, check!
|
// if timestamps are not the same, or something is missing, check!
|
||||||
if (m_javaSignature != storedSignature || storedVersion.size() == 0 || storedArchitecture.size() == 0 ||
|
if (m_javaSignature != storedSignature || storedVersion.size() == 0 || storedArchitecture.size() == 0 ||
|
||||||
storedRealArchitecture.size() == 0 || storedVendor.size() == 0) {
|
storedRealArchitecture.size() == 0 || storedVendor.size() == 0) {
|
||||||
m_JavaChecker.reset(new JavaChecker);
|
m_JavaChecker.reset(new JavaChecker(realJavaPath, "", 0, 0, 0, 0, this));
|
||||||
emit logLine(QString("Checking Java version..."), MessageLevel::Launcher);
|
emit logLine(QString("Checking Java version..."), MessageLevel::Launcher);
|
||||||
connect(m_JavaChecker.get(), &JavaChecker::checkFinished, this, &CheckJava::checkJavaFinished);
|
connect(m_JavaChecker.get(), &JavaChecker::checkFinished, this, &CheckJava::checkJavaFinished);
|
||||||
m_JavaChecker->m_path = realJavaPath;
|
m_JavaChecker->start();
|
||||||
m_JavaChecker->performCheck();
|
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
auto verString = instance->settings()->get("JavaVersion").toString();
|
auto verString = instance->settings()->get("JavaVersion").toString();
|
||||||
@ -109,10 +109,10 @@ void CheckJava::executeTask()
|
|||||||
emitSucceeded();
|
emitSucceeded();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CheckJava::checkJavaFinished(JavaCheckResult result)
|
void CheckJava::checkJavaFinished(const JavaChecker::Result& result)
|
||||||
{
|
{
|
||||||
switch (result.validity) {
|
switch (result.validity) {
|
||||||
case JavaCheckResult::Validity::Errored: {
|
case JavaChecker::Result::Validity::Errored: {
|
||||||
// Error message displayed if java can't start
|
// Error message displayed if java can't start
|
||||||
emit logLine(QString("Could not start java:"), MessageLevel::Error);
|
emit logLine(QString("Could not start java:"), MessageLevel::Error);
|
||||||
emit logLines(result.errorLog.split('\n'), MessageLevel::Error);
|
emit logLines(result.errorLog.split('\n'), MessageLevel::Error);
|
||||||
@ -120,14 +120,14 @@ void CheckJava::checkJavaFinished(JavaCheckResult result)
|
|||||||
emitFailed(QString("Could not start java!"));
|
emitFailed(QString("Could not start java!"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case JavaCheckResult::Validity::ReturnedInvalidData: {
|
case JavaChecker::Result::Validity::ReturnedInvalidData: {
|
||||||
emit logLine(QString("Java checker returned some invalid data we don't understand:"), MessageLevel::Error);
|
emit logLine(QString("Java checker returned some invalid data we don't understand:"), MessageLevel::Error);
|
||||||
emit logLines(result.outLog.split('\n'), MessageLevel::Warning);
|
emit logLines(result.outLog.split('\n'), MessageLevel::Warning);
|
||||||
emit logLine("\nMinecraft might not start properly.", MessageLevel::Launcher);
|
emit logLine("\nMinecraft might not start properly.", MessageLevel::Launcher);
|
||||||
emitSucceeded();
|
emitSucceeded();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case JavaCheckResult::Validity::Valid: {
|
case JavaChecker::Result::Validity::Valid: {
|
||||||
auto instance = m_parent->instance();
|
auto instance = m_parent->instance();
|
||||||
printJavaInfo(result.javaVersion.toString(), result.mojangPlatform, result.realPlatform, result.javaVendor);
|
printJavaInfo(result.javaVersion.toString(), result.mojangPlatform, result.realPlatform, result.javaVendor);
|
||||||
instance->settings()->set("JavaVersion", result.javaVersion.toString());
|
instance->settings()->set("JavaVersion", result.javaVersion.toString());
|
||||||
|
@ -28,7 +28,7 @@ class CheckJava : public LaunchStep {
|
|||||||
virtual void executeTask();
|
virtual void executeTask();
|
||||||
virtual bool canAbort() const { return false; }
|
virtual bool canAbort() const { return false; }
|
||||||
private slots:
|
private slots:
|
||||||
void checkJavaFinished(JavaCheckResult result);
|
void checkJavaFinished(const JavaChecker::Result& result);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void printJavaInfo(const QString& version, const QString& architecture, const QString& realArchitecture, const QString& vendor);
|
void printJavaInfo(const QString& version, const QString& architecture, const QString& realArchitecture, const QString& vendor);
|
||||||
@ -37,5 +37,5 @@ class CheckJava : public LaunchStep {
|
|||||||
private:
|
private:
|
||||||
QString m_javaPath;
|
QString m_javaPath;
|
||||||
QString m_javaSignature;
|
QString m_javaSignature;
|
||||||
JavaCheckerPtr m_JavaChecker;
|
JavaChecker::Ptr m_JavaChecker;
|
||||||
};
|
};
|
||||||
|
@ -100,6 +100,13 @@ QVariant VersionList::data(const QModelIndex& index, int role) const
|
|||||||
return QVariant::fromValue(version);
|
return QVariant::fromValue(version);
|
||||||
case RecommendedRole:
|
case RecommendedRole:
|
||||||
return version->isRecommended();
|
return version->isRecommended();
|
||||||
|
case JavaMajorRole: {
|
||||||
|
auto major = version->version();
|
||||||
|
if (major.startsWith("java")) {
|
||||||
|
major = "Java " + major.mid(4);
|
||||||
|
}
|
||||||
|
return major;
|
||||||
|
}
|
||||||
// FIXME: this should be determined in whatever view/proxy is used...
|
// FIXME: this should be determined in whatever view/proxy is used...
|
||||||
// case LatestRole: return version == getLatestStable();
|
// case LatestRole: return version == getLatestStable();
|
||||||
default:
|
default:
|
||||||
@ -109,10 +116,14 @@ QVariant VersionList::data(const QModelIndex& index, int role) const
|
|||||||
|
|
||||||
BaseVersionList::RoleList VersionList::providesRoles() const
|
BaseVersionList::RoleList VersionList::providesRoles() const
|
||||||
{
|
{
|
||||||
return { VersionPointerRole, VersionRole, VersionIdRole, ParentVersionRole, TypeRole, UidRole,
|
return m_provided_roles;
|
||||||
TimeRole, RequiresRole, SortRole, RecommendedRole, LatestRole, VersionPtrRole };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VersionList::setProvidedRoles(RoleList roles)
|
||||||
|
{
|
||||||
|
m_provided_roles = roles;
|
||||||
|
};
|
||||||
|
|
||||||
QHash<int, QByteArray> VersionList::roleNames() const
|
QHash<int, QByteArray> VersionList::roleNames() const
|
||||||
{
|
{
|
||||||
QHash<int, QByteArray> roles = BaseVersionList::roleNames();
|
QHash<int, QByteArray> roles = BaseVersionList::roleNames();
|
||||||
|
@ -48,6 +48,8 @@ class VersionList : public BaseVersionList, public BaseEntity {
|
|||||||
RoleList providesRoles() const override;
|
RoleList providesRoles() const override;
|
||||||
QHash<int, QByteArray> roleNames() const override;
|
QHash<int, QByteArray> roleNames() const override;
|
||||||
|
|
||||||
|
void setProvidedRoles(RoleList roles);
|
||||||
|
|
||||||
QString localFilename() const override;
|
QString localFilename() const override;
|
||||||
|
|
||||||
QString uid() const { return m_uid; }
|
QString uid() const { return m_uid; }
|
||||||
@ -83,6 +85,9 @@ class VersionList : public BaseVersionList, public BaseEntity {
|
|||||||
|
|
||||||
Version::Ptr m_recommended;
|
Version::Ptr m_recommended;
|
||||||
|
|
||||||
|
RoleList m_provided_roles = { VersionPointerRole, VersionRole, VersionIdRole, ParentVersionRole, TypeRole, UidRole,
|
||||||
|
TimeRole, RequiresRole, SortRole, RecommendedRole, LatestRole, VersionPtrRole };
|
||||||
|
|
||||||
void setupAddedVersion(int row, const Version::Ptr& version);
|
void setupAddedVersion(int row, const Version::Ptr& version);
|
||||||
};
|
};
|
||||||
} // namespace Meta
|
} // namespace Meta
|
||||||
|
@ -164,6 +164,11 @@ void LaunchProfile::applyCompatibleJavaMajors(QList<int>& javaMajor)
|
|||||||
{
|
{
|
||||||
m_compatibleJavaMajors.append(javaMajor);
|
m_compatibleJavaMajors.append(javaMajor);
|
||||||
}
|
}
|
||||||
|
void LaunchProfile::applyCompatibleJavaName(QString javaName)
|
||||||
|
{
|
||||||
|
if (!javaName.isEmpty())
|
||||||
|
m_compatibleJavaName = javaName;
|
||||||
|
}
|
||||||
|
|
||||||
void LaunchProfile::applyLibrary(LibraryPtr library, const RuntimeContext& runtimeContext)
|
void LaunchProfile::applyLibrary(LibraryPtr library, const RuntimeContext& runtimeContext)
|
||||||
{
|
{
|
||||||
@ -334,6 +339,11 @@ const QList<int>& LaunchProfile::getCompatibleJavaMajors() const
|
|||||||
return m_compatibleJavaMajors;
|
return m_compatibleJavaMajors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const QString LaunchProfile::getCompatibleJavaName() const
|
||||||
|
{
|
||||||
|
return m_compatibleJavaName;
|
||||||
|
}
|
||||||
|
|
||||||
void LaunchProfile::getLibraryFiles(const RuntimeContext& runtimeContext,
|
void LaunchProfile::getLibraryFiles(const RuntimeContext& runtimeContext,
|
||||||
QStringList& jars,
|
QStringList& jars,
|
||||||
QStringList& nativeJars,
|
QStringList& nativeJars,
|
||||||
|
@ -59,6 +59,7 @@ class LaunchProfile : public ProblemProvider {
|
|||||||
void applyMavenFile(LibraryPtr library, const RuntimeContext& runtimeContext);
|
void applyMavenFile(LibraryPtr library, const RuntimeContext& runtimeContext);
|
||||||
void applyAgent(AgentPtr agent, const RuntimeContext& runtimeContext);
|
void applyAgent(AgentPtr agent, const RuntimeContext& runtimeContext);
|
||||||
void applyCompatibleJavaMajors(QList<int>& javaMajor);
|
void applyCompatibleJavaMajors(QList<int>& javaMajor);
|
||||||
|
void applyCompatibleJavaName(QString javaName);
|
||||||
void applyMainJar(LibraryPtr jar);
|
void applyMainJar(LibraryPtr jar);
|
||||||
void applyProblemSeverity(ProblemSeverity severity);
|
void applyProblemSeverity(ProblemSeverity severity);
|
||||||
/// clear the profile
|
/// clear the profile
|
||||||
@ -80,6 +81,7 @@ class LaunchProfile : public ProblemProvider {
|
|||||||
const QList<LibraryPtr>& getMavenFiles() const;
|
const QList<LibraryPtr>& getMavenFiles() const;
|
||||||
const QList<AgentPtr>& getAgents() const;
|
const QList<AgentPtr>& getAgents() const;
|
||||||
const QList<int>& getCompatibleJavaMajors() const;
|
const QList<int>& getCompatibleJavaMajors() const;
|
||||||
|
const QString getCompatibleJavaName() const;
|
||||||
const LibraryPtr getMainJar() const;
|
const LibraryPtr getMainJar() const;
|
||||||
void getLibraryFiles(const RuntimeContext& runtimeContext,
|
void getLibraryFiles(const RuntimeContext& runtimeContext,
|
||||||
QStringList& jars,
|
QStringList& jars,
|
||||||
@ -150,5 +152,7 @@ class LaunchProfile : public ProblemProvider {
|
|||||||
/// compatible java major versions
|
/// compatible java major versions
|
||||||
QList<int> m_compatibleJavaMajors;
|
QList<int> m_compatibleJavaMajors;
|
||||||
|
|
||||||
|
QString m_compatibleJavaName;
|
||||||
|
|
||||||
ProblemSeverity m_problemSeverity = ProblemSeverity::None;
|
ProblemSeverity m_problemSeverity = ProblemSeverity::None;
|
||||||
};
|
};
|
||||||
|
@ -38,6 +38,8 @@
|
|||||||
#include "MinecraftInstance.h"
|
#include "MinecraftInstance.h"
|
||||||
#include "Application.h"
|
#include "Application.h"
|
||||||
#include "BuildConfig.h"
|
#include "BuildConfig.h"
|
||||||
|
#include "QObjectPtr.h"
|
||||||
|
#include "minecraft/launch/AutoInstallJava.h"
|
||||||
#include "minecraft/launch/CreateGameFolders.h"
|
#include "minecraft/launch/CreateGameFolders.h"
|
||||||
#include "minecraft/launch/ExtractNatives.h"
|
#include "minecraft/launch/ExtractNatives.h"
|
||||||
#include "minecraft/launch/PrintInstanceInfo.h"
|
#include "minecraft/launch/PrintInstanceInfo.h"
|
||||||
@ -134,25 +136,21 @@ void MinecraftInstance::loadSpecificSettings()
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// Java Settings
|
// Java Settings
|
||||||
auto javaOverride = m_settings->registerSetting("OverrideJava", false);
|
|
||||||
auto locationOverride = m_settings->registerSetting("OverrideJavaLocation", false);
|
auto locationOverride = m_settings->registerSetting("OverrideJavaLocation", false);
|
||||||
auto argsOverride = m_settings->registerSetting("OverrideJavaArgs", false);
|
auto argsOverride = m_settings->registerSetting("OverrideJavaArgs", false);
|
||||||
|
m_settings->registerSetting("AutomaticJava", false);
|
||||||
// combinations
|
|
||||||
auto javaOrLocation = std::make_shared<OrSetting>("JavaOrLocationOverride", javaOverride, locationOverride);
|
|
||||||
auto javaOrArgs = std::make_shared<OrSetting>("JavaOrArgsOverride", javaOverride, argsOverride);
|
|
||||||
|
|
||||||
if (auto global_settings = globalSettings()) {
|
if (auto global_settings = globalSettings()) {
|
||||||
m_settings->registerOverride(global_settings->getSetting("JavaPath"), javaOrLocation);
|
m_settings->registerOverride(global_settings->getSetting("JavaPath"), locationOverride);
|
||||||
m_settings->registerOverride(global_settings->getSetting("JvmArgs"), javaOrArgs);
|
m_settings->registerOverride(global_settings->getSetting("JvmArgs"), argsOverride);
|
||||||
m_settings->registerOverride(global_settings->getSetting("IgnoreJavaCompatibility"), javaOrLocation);
|
m_settings->registerOverride(global_settings->getSetting("IgnoreJavaCompatibility"), locationOverride);
|
||||||
|
|
||||||
// special!
|
// special!
|
||||||
m_settings->registerPassthrough(global_settings->getSetting("JavaSignature"), javaOrLocation);
|
m_settings->registerPassthrough(global_settings->getSetting("JavaSignature"), locationOverride);
|
||||||
m_settings->registerPassthrough(global_settings->getSetting("JavaArchitecture"), javaOrLocation);
|
m_settings->registerPassthrough(global_settings->getSetting("JavaArchitecture"), locationOverride);
|
||||||
m_settings->registerPassthrough(global_settings->getSetting("JavaRealArchitecture"), javaOrLocation);
|
m_settings->registerPassthrough(global_settings->getSetting("JavaRealArchitecture"), locationOverride);
|
||||||
m_settings->registerPassthrough(global_settings->getSetting("JavaVersion"), javaOrLocation);
|
m_settings->registerPassthrough(global_settings->getSetting("JavaVersion"), locationOverride);
|
||||||
m_settings->registerPassthrough(global_settings->getSetting("JavaVendor"), javaOrLocation);
|
m_settings->registerPassthrough(global_settings->getSetting("JavaVendor"), locationOverride);
|
||||||
|
|
||||||
// Window Size
|
// Window Size
|
||||||
auto windowSetting = m_settings->registerSetting("OverrideWindow", false);
|
auto windowSetting = m_settings->registerSetting("OverrideWindow", false);
|
||||||
@ -1060,11 +1058,6 @@ shared_qobject_ptr<LaunchTask> MinecraftInstance::createLaunchTask(AuthSessionPt
|
|||||||
process->appendStep(makeShared<TextPrint>(pptr, "Minecraft folder is:\n" + gameRoot() + "\n\n", MessageLevel::Launcher));
|
process->appendStep(makeShared<TextPrint>(pptr, "Minecraft folder is:\n" + gameRoot() + "\n\n", MessageLevel::Launcher));
|
||||||
}
|
}
|
||||||
|
|
||||||
// check java
|
|
||||||
{
|
|
||||||
process->appendStep(makeShared<CheckJava>(pptr));
|
|
||||||
}
|
|
||||||
|
|
||||||
// create the .minecraft folder and server-resource-packs (workaround for Minecraft bug MCL-3732)
|
// create the .minecraft folder and server-resource-packs (workaround for Minecraft bug MCL-3732)
|
||||||
{
|
{
|
||||||
process->appendStep(makeShared<CreateGameFolders>(pptr));
|
process->appendStep(makeShared<CreateGameFolders>(pptr));
|
||||||
@ -1107,6 +1100,12 @@ shared_qobject_ptr<LaunchTask> MinecraftInstance::createLaunchTask(AuthSessionPt
|
|||||||
process->appendStep(makeShared<Update>(pptr, Net::Mode::Offline));
|
process->appendStep(makeShared<Update>(pptr, Net::Mode::Offline));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check java
|
||||||
|
{
|
||||||
|
process->appendStep(makeShared<AutoInstallJava>(pptr));
|
||||||
|
process->appendStep(makeShared<CheckJava>(pptr));
|
||||||
|
}
|
||||||
|
|
||||||
// if there are any jar mods
|
// if there are any jar mods
|
||||||
{
|
{
|
||||||
process->appendStep(makeShared<ModMinecraftJar>(pptr));
|
process->appendStep(makeShared<ModMinecraftJar>(pptr));
|
||||||
|
@ -185,6 +185,9 @@ void MojangVersionFormat::readVersionProperties(const QJsonObject& in, VersionFi
|
|||||||
out->compatibleJavaMajors.append(requireInteger(compatible));
|
out->compatibleJavaMajors.append(requireInteger(compatible));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (in.contains("compatibleJavaName")) {
|
||||||
|
out->compatibleJavaName = requireString(in.value("compatibleJavaName"));
|
||||||
|
}
|
||||||
|
|
||||||
if (in.contains("downloads")) {
|
if (in.contains("downloads")) {
|
||||||
auto downloadsObj = requireObject(in, "downloads");
|
auto downloadsObj = requireObject(in, "downloads");
|
||||||
@ -259,6 +262,9 @@ void MojangVersionFormat::writeVersionProperties(const VersionFile* in, QJsonObj
|
|||||||
}
|
}
|
||||||
out.insert("compatibleJavaMajors", compatibleJavaMajorsOut);
|
out.insert("compatibleJavaMajors", compatibleJavaMajorsOut);
|
||||||
}
|
}
|
||||||
|
if (!in->compatibleJavaName.isEmpty()) {
|
||||||
|
writeString(out, "compatibleJavaName", in->compatibleJavaName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonDocument MojangVersionFormat::versionFileToJson(const VersionFilePtr& patch)
|
QJsonDocument MojangVersionFormat::versionFileToJson(const VersionFilePtr& patch)
|
||||||
|
@ -36,6 +36,8 @@
|
|||||||
#include "OneSixVersionFormat.h"
|
#include "OneSixVersionFormat.h"
|
||||||
#include <Json.h>
|
#include <Json.h>
|
||||||
#include <minecraft/MojangVersionFormat.h>
|
#include <minecraft/MojangVersionFormat.h>
|
||||||
|
#include <QList>
|
||||||
|
#include "java/JavaMetadata.h"
|
||||||
#include "minecraft/Agent.h"
|
#include "minecraft/Agent.h"
|
||||||
#include "minecraft/ParseUtils.h"
|
#include "minecraft/ParseUtils.h"
|
||||||
|
|
||||||
@ -255,6 +257,13 @@ VersionFilePtr OneSixVersionFormat::versionFileFromJson(const QJsonDocument& doc
|
|||||||
out->m_volatile = requireBoolean(root, "volatile");
|
out->m_volatile = requireBoolean(root, "volatile");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (root.contains("runtimes")) {
|
||||||
|
out->runtimes = {};
|
||||||
|
for (auto runtime : ensureArray(root, "runtimes")) {
|
||||||
|
out->runtimes.append(Java::parseJavaMeta(ensureObject(runtime)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* removed features that shouldn't be used */
|
/* removed features that shouldn't be used */
|
||||||
if (root.contains("tweakers")) {
|
if (root.contains("tweakers")) {
|
||||||
out->addProblem(ProblemSeverity::Error, QObject::tr("Version file contains unsupported element 'tweakers'"));
|
out->addProblem(ProblemSeverity::Error, QObject::tr("Version file contains unsupported element 'tweakers'"));
|
||||||
|
@ -73,6 +73,7 @@ void VersionFile::applyTo(LaunchProfile* profile, const RuntimeContext& runtimeC
|
|||||||
profile->applyMods(mods);
|
profile->applyMods(mods);
|
||||||
profile->applyTraits(traits);
|
profile->applyTraits(traits);
|
||||||
profile->applyCompatibleJavaMajors(compatibleJavaMajors);
|
profile->applyCompatibleJavaMajors(compatibleJavaMajors);
|
||||||
|
profile->applyCompatibleJavaName(compatibleJavaName);
|
||||||
|
|
||||||
for (auto library : libraries) {
|
for (auto library : libraries) {
|
||||||
profile->applyLibrary(library, runtimeContext);
|
profile->applyLibrary(library, runtimeContext);
|
||||||
|
@ -36,6 +36,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
|
#include <QHash>
|
||||||
|
#include <QList>
|
||||||
#include <QSet>
|
#include <QSet>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
@ -45,6 +47,7 @@
|
|||||||
#include "Agent.h"
|
#include "Agent.h"
|
||||||
#include "Library.h"
|
#include "Library.h"
|
||||||
#include "ProblemProvider.h"
|
#include "ProblemProvider.h"
|
||||||
|
#include "java/JavaMetadata.h"
|
||||||
#include "minecraft/Rule.h"
|
#include "minecraft/Rule.h"
|
||||||
|
|
||||||
class PackProfile;
|
class PackProfile;
|
||||||
@ -98,6 +101,9 @@ class VersionFile : public ProblemContainer {
|
|||||||
/// Mojang: list of compatible java majors
|
/// Mojang: list of compatible java majors
|
||||||
QList<int> compatibleJavaMajors;
|
QList<int> compatibleJavaMajors;
|
||||||
|
|
||||||
|
/// Mojang: the name of recommended java version
|
||||||
|
QString compatibleJavaName;
|
||||||
|
|
||||||
/// Mojang: type of the Minecraft version
|
/// Mojang: type of the Minecraft version
|
||||||
QString type;
|
QString type;
|
||||||
|
|
||||||
@ -149,6 +155,8 @@ class VersionFile : public ProblemContainer {
|
|||||||
/// is volatile -- may be removed as soon as it is no longer needed by something else
|
/// is volatile -- may be removed as soon as it is no longer needed by something else
|
||||||
bool m_volatile = false;
|
bool m_volatile = false;
|
||||||
|
|
||||||
|
QList<Java::MetadataPtr> runtimes;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Mojang: DEPRECATED list of 'downloads' - client jar, server jar, windows server exe, maybe more.
|
// Mojang: DEPRECATED list of 'downloads' - client jar, server jar, windows server exe, maybe more.
|
||||||
QMap<QString, std::shared_ptr<MojangDownloadInfo>> mojangDownloads;
|
QMap<QString, std::shared_ptr<MojangDownloadInfo>> mojangDownloads;
|
||||||
|
242
launcher/minecraft/launch/AutoInstallJava.cpp
Normal file
242
launcher/minecraft/launch/AutoInstallJava.cpp
Normal file
@ -0,0 +1,242 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
/*
|
||||||
|
* Prism Launcher - Minecraft Launcher
|
||||||
|
* Copyright (c) 2023-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/>.
|
||||||
|
*
|
||||||
|
* 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 "AutoInstallJava.h"
|
||||||
|
#include <QDir>
|
||||||
|
#include <QFileInfo>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "Application.h"
|
||||||
|
#include "FileSystem.h"
|
||||||
|
#include "MessageLevel.h"
|
||||||
|
#include "SysInfo.h"
|
||||||
|
#include "java/JavaInstall.h"
|
||||||
|
#include "java/JavaInstallList.h"
|
||||||
|
#include "java/JavaUtils.h"
|
||||||
|
#include "java/JavaVersion.h"
|
||||||
|
#include "java/download/ArchiveDownloadTask.h"
|
||||||
|
#include "java/download/ManifestDownloadTask.h"
|
||||||
|
#include "meta/Index.h"
|
||||||
|
#include "minecraft/MinecraftInstance.h"
|
||||||
|
#include "minecraft/PackProfile.h"
|
||||||
|
#include "net/Mode.h"
|
||||||
|
|
||||||
|
AutoInstallJava::AutoInstallJava(LaunchTask* parent)
|
||||||
|
: LaunchStep(parent)
|
||||||
|
, m_instance(std::dynamic_pointer_cast<MinecraftInstance>(m_parent->instance()))
|
||||||
|
, m_supported_arch(SysInfo::getSupportedJavaArchitecture()) {};
|
||||||
|
|
||||||
|
void AutoInstallJava::executeTask()
|
||||||
|
{
|
||||||
|
auto settings = m_instance->settings();
|
||||||
|
if (!APPLICATION->settings()->get("AutomaticJavaSwitch").toBool() ||
|
||||||
|
(settings->get("OverrideJavaLocation").toBool() && QFileInfo::exists(settings->get("JavaPath").toString()))) {
|
||||||
|
emitSucceeded();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto packProfile = m_instance->getPackProfile();
|
||||||
|
if (!APPLICATION->settings()->get("AutomaticJavaDownload").toBool()) {
|
||||||
|
auto javas = APPLICATION->javalist();
|
||||||
|
m_current_task = javas->getLoadTask();
|
||||||
|
connect(m_current_task.get(), &Task::finished, this, [this, javas, packProfile] {
|
||||||
|
for (auto i = 0; i < javas->count(); i++) {
|
||||||
|
auto java = std::dynamic_pointer_cast<JavaInstall>(javas->at(i));
|
||||||
|
if (java && packProfile->getProfile()->getCompatibleJavaMajors().contains(java->id.major())) {
|
||||||
|
if (!java->is_64bit) {
|
||||||
|
emit logLine(tr("The automatic Java mechanism detected a 32-bit installation of Java."), MessageLevel::Info);
|
||||||
|
}
|
||||||
|
setJavaPath(java->path);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
emit logLine(tr("No compatible Java version was found. Using the default one."), MessageLevel::Warning);
|
||||||
|
emitSucceeded();
|
||||||
|
});
|
||||||
|
connect(m_current_task.get(), &Task::progress, this, &AutoInstallJava::setProgress);
|
||||||
|
connect(m_current_task.get(), &Task::stepProgress, this, &AutoInstallJava::propagateStepProgress);
|
||||||
|
connect(m_current_task.get(), &Task::status, this, &AutoInstallJava::setStatus);
|
||||||
|
connect(m_current_task.get(), &Task::details, this, &AutoInstallJava::setDetails);
|
||||||
|
emit progressReportingRequest();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (m_supported_arch.isEmpty()) {
|
||||||
|
emit logLine(tr("Your system (%1-%2) is not compatible with automatic Java installation. Using the default Java path.")
|
||||||
|
.arg(SysInfo::currentSystem(), SysInfo::useQTForArch()),
|
||||||
|
MessageLevel::Warning);
|
||||||
|
emitSucceeded();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto wantedJavaName = packProfile->getProfile()->getCompatibleJavaName();
|
||||||
|
if (wantedJavaName.isEmpty()) {
|
||||||
|
emit logLine(tr("Your meta information is out of date or doesn't have the information necessary to determine what installation of "
|
||||||
|
"Java should be used. "
|
||||||
|
"Using the default Java path."),
|
||||||
|
MessageLevel::Warning);
|
||||||
|
emitSucceeded();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
QDir javaDir(APPLICATION->javaPath());
|
||||||
|
auto wantedJavaPath = javaDir.absoluteFilePath(wantedJavaName);
|
||||||
|
if (QFileInfo::exists(wantedJavaPath)) {
|
||||||
|
setJavaPathFromPartial();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto versionList = APPLICATION->metadataIndex()->get("net.minecraft.java");
|
||||||
|
m_current_task = versionList->getLoadTask();
|
||||||
|
connect(m_current_task.get(), &Task::succeeded, this, &AutoInstallJava::tryNextMajorJava);
|
||||||
|
connect(m_current_task.get(), &Task::failed, this, &AutoInstallJava::emitFailed);
|
||||||
|
connect(m_current_task.get(), &Task::progress, this, &AutoInstallJava::setProgress);
|
||||||
|
connect(m_current_task.get(), &Task::stepProgress, this, &AutoInstallJava::propagateStepProgress);
|
||||||
|
connect(m_current_task.get(), &Task::status, this, &AutoInstallJava::setStatus);
|
||||||
|
connect(m_current_task.get(), &Task::details, this, &AutoInstallJava::setDetails);
|
||||||
|
if (!m_current_task->isRunning()) {
|
||||||
|
m_current_task->start();
|
||||||
|
}
|
||||||
|
emit progressReportingRequest();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AutoInstallJava::setJavaPath(QString path)
|
||||||
|
{
|
||||||
|
auto settings = m_instance->settings();
|
||||||
|
settings->set("OverrideJavaLocation", true);
|
||||||
|
settings->set("JavaPath", path);
|
||||||
|
settings->set("AutomaticJava", true);
|
||||||
|
emit logLine(tr("Compatible Java found at: %1.").arg(path), MessageLevel::Info);
|
||||||
|
emitSucceeded();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AutoInstallJava::setJavaPathFromPartial()
|
||||||
|
{
|
||||||
|
auto packProfile = m_instance->getPackProfile();
|
||||||
|
auto javaName = packProfile->getProfile()->getCompatibleJavaName();
|
||||||
|
QDir javaDir(APPLICATION->javaPath());
|
||||||
|
// just checking if the executable is there should suffice
|
||||||
|
// but if needed this can be achieved through refreshing the javalist
|
||||||
|
// and retrieving the path that contains the java name
|
||||||
|
auto relativeBinary = FS::PathCombine(javaName, "bin", JavaUtils::javaExecutable);
|
||||||
|
auto finalPath = javaDir.absoluteFilePath(relativeBinary);
|
||||||
|
if (QFileInfo::exists(finalPath)) {
|
||||||
|
setJavaPath(finalPath);
|
||||||
|
} else {
|
||||||
|
emit logLine(tr("No compatible Java version was found (the binary file does not exist). Using the default one."),
|
||||||
|
MessageLevel::Warning);
|
||||||
|
emitSucceeded();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AutoInstallJava::downloadJava(Meta::Version::Ptr version, QString javaName)
|
||||||
|
{
|
||||||
|
auto runtimes = version->data()->runtimes;
|
||||||
|
for (auto java : runtimes) {
|
||||||
|
if (java->runtimeOS == m_supported_arch && java->name() == javaName) {
|
||||||
|
QDir javaDir(APPLICATION->javaPath());
|
||||||
|
auto final_path = javaDir.absoluteFilePath(java->m_name);
|
||||||
|
switch (java->downloadType) {
|
||||||
|
case Java::DownloadType::Manifest:
|
||||||
|
m_current_task = makeShared<Java::ManifestDownloadTask>(java->url, final_path, java->checksumType, java->checksumHash);
|
||||||
|
break;
|
||||||
|
case Java::DownloadType::Archive:
|
||||||
|
m_current_task = makeShared<Java::ArchiveDownloadTask>(java->url, final_path, java->checksumType, java->checksumHash);
|
||||||
|
break;
|
||||||
|
case Java::DownloadType::Unknown:
|
||||||
|
emitFailed(tr("Could not determine Java download type!"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto deletePath = [final_path] { FS::deletePath(final_path); };
|
||||||
|
connect(m_current_task.get(), &Task::failed, this, [this, deletePath](QString reason) {
|
||||||
|
deletePath();
|
||||||
|
emitFailed(reason);
|
||||||
|
});
|
||||||
|
connect(this, &Task::aborted, this, [this, deletePath] {
|
||||||
|
m_current_task->abort();
|
||||||
|
deletePath();
|
||||||
|
});
|
||||||
|
connect(m_current_task.get(), &Task::succeeded, this, &AutoInstallJava::setJavaPathFromPartial);
|
||||||
|
connect(m_current_task.get(), &Task::failed, this, &AutoInstallJava::tryNextMajorJava);
|
||||||
|
connect(m_current_task.get(), &Task::progress, this, &AutoInstallJava::setProgress);
|
||||||
|
connect(m_current_task.get(), &Task::stepProgress, this, &AutoInstallJava::propagateStepProgress);
|
||||||
|
connect(m_current_task.get(), &Task::status, this, &AutoInstallJava::setStatus);
|
||||||
|
connect(m_current_task.get(), &Task::details, this, &AutoInstallJava::setDetails);
|
||||||
|
m_current_task->start();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tryNextMajorJava();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AutoInstallJava::tryNextMajorJava()
|
||||||
|
{
|
||||||
|
if (!isRunning())
|
||||||
|
return;
|
||||||
|
auto versionList = APPLICATION->metadataIndex()->get("net.minecraft.java");
|
||||||
|
auto packProfile = m_instance->getPackProfile();
|
||||||
|
auto wantedJavaName = packProfile->getProfile()->getCompatibleJavaName();
|
||||||
|
auto majorJavaVersions = packProfile->getProfile()->getCompatibleJavaMajors();
|
||||||
|
if (m_majorJavaVersionIndex >= majorJavaVersions.length()) {
|
||||||
|
emit logLine(
|
||||||
|
tr("No versions of Java were found for your operating system: %1-%2").arg(SysInfo::currentSystem(), SysInfo::useQTForArch()),
|
||||||
|
MessageLevel::Warning);
|
||||||
|
emit logLine(tr("No compatible version of Java was found. Using the default one."), MessageLevel::Warning);
|
||||||
|
emitSucceeded();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto majorJavaVersion = majorJavaVersions[m_majorJavaVersionIndex];
|
||||||
|
m_majorJavaVersionIndex++;
|
||||||
|
|
||||||
|
auto javaMajor = versionList->getVersion(QString("java%1").arg(majorJavaVersion));
|
||||||
|
|
||||||
|
if (javaMajor->isLoaded()) {
|
||||||
|
downloadJava(javaMajor, wantedJavaName);
|
||||||
|
} else {
|
||||||
|
m_current_task = APPLICATION->metadataIndex()->loadVersion("net.minecraft.java", javaMajor->version(), Net::Mode::Online);
|
||||||
|
connect(m_current_task.get(), &Task::succeeded, this,
|
||||||
|
[this, javaMajor, wantedJavaName] { downloadJava(javaMajor, wantedJavaName); });
|
||||||
|
connect(m_current_task.get(), &Task::failed, this, &AutoInstallJava::tryNextMajorJava);
|
||||||
|
connect(m_current_task.get(), &Task::progress, this, &AutoInstallJava::setProgress);
|
||||||
|
connect(m_current_task.get(), &Task::stepProgress, this, &AutoInstallJava::propagateStepProgress);
|
||||||
|
connect(m_current_task.get(), &Task::status, this, &AutoInstallJava::setStatus);
|
||||||
|
connect(m_current_task.get(), &Task::details, this, &AutoInstallJava::setDetails);
|
||||||
|
if (!m_current_task->isRunning()) {
|
||||||
|
m_current_task->start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bool AutoInstallJava::abort()
|
||||||
|
{
|
||||||
|
if (m_current_task && m_current_task->canAbort())
|
||||||
|
return m_current_task->abort();
|
||||||
|
return true;
|
||||||
|
}
|
68
launcher/minecraft/launch/AutoInstallJava.h
Normal file
68
launcher/minecraft/launch/AutoInstallJava.h
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
/*
|
||||||
|
* Prism Launcher - Minecraft Launcher
|
||||||
|
* Copyright (c) 2023-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/>.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <launch/LaunchStep.h>
|
||||||
|
#include <launch/LaunchTask.h>
|
||||||
|
#include "java/JavaMetadata.h"
|
||||||
|
#include "meta/Version.h"
|
||||||
|
#include "minecraft/MinecraftInstance.h"
|
||||||
|
#include "tasks/Task.h"
|
||||||
|
|
||||||
|
class AutoInstallJava : public LaunchStep {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit AutoInstallJava(LaunchTask* parent);
|
||||||
|
~AutoInstallJava() override = default;
|
||||||
|
|
||||||
|
void executeTask() override;
|
||||||
|
bool canAbort() const override { return m_current_task ? m_current_task->canAbort() : false; }
|
||||||
|
bool abort() override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void setJavaPath(QString path);
|
||||||
|
void setJavaPathFromPartial();
|
||||||
|
void downloadJava(Meta::Version::Ptr version, QString javaName);
|
||||||
|
void tryNextMajorJava();
|
||||||
|
|
||||||
|
private:
|
||||||
|
MinecraftInstancePtr m_instance;
|
||||||
|
Task::Ptr m_current_task;
|
||||||
|
|
||||||
|
qsizetype m_majorJavaVersionIndex = 0;
|
||||||
|
const QString m_supported_arch;
|
||||||
|
};
|
@ -34,7 +34,12 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "VerifyJavaInstall.h"
|
#include "VerifyJavaInstall.h"
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "Application.h"
|
||||||
|
#include "MessageLevel.h"
|
||||||
|
#include "java/JavaInstall.h"
|
||||||
|
#include "java/JavaInstallList.h"
|
||||||
#include "java/JavaVersion.h"
|
#include "java/JavaVersion.h"
|
||||||
#include "minecraft/MinecraftInstance.h"
|
#include "minecraft/MinecraftInstance.h"
|
||||||
#include "minecraft/PackProfile.h"
|
#include "minecraft/PackProfile.h"
|
||||||
@ -46,6 +51,15 @@ void VerifyJavaInstall::executeTask()
|
|||||||
auto settings = instance->settings();
|
auto settings = instance->settings();
|
||||||
auto storedVersion = settings->get("JavaVersion").toString();
|
auto storedVersion = settings->get("JavaVersion").toString();
|
||||||
auto ignoreCompatibility = settings->get("IgnoreJavaCompatibility").toBool();
|
auto ignoreCompatibility = settings->get("IgnoreJavaCompatibility").toBool();
|
||||||
|
auto javaArchitecture = settings->get("JavaArchitecture").toString();
|
||||||
|
auto maxMemAlloc = settings->get("MaxMemAlloc").toInt();
|
||||||
|
|
||||||
|
if (javaArchitecture == "32" && maxMemAlloc > 2048) {
|
||||||
|
emit logLine(tr("Max memory allocation exceeds the supported value.\n"
|
||||||
|
"The selected installation of Java is 32-bit and doesn't support more than 2048MiB of RAM.\n"
|
||||||
|
"The instance may not start due to this."),
|
||||||
|
MessageLevel::Error);
|
||||||
|
}
|
||||||
|
|
||||||
auto compatibleMajors = packProfile->getProfile()->getCompatibleJavaMajors();
|
auto compatibleMajors = packProfile->getProfile()->getCompatibleJavaMajors();
|
||||||
|
|
||||||
|
@ -353,5 +353,11 @@
|
|||||||
<file>scalable/instances/neoforged.svg</file>
|
<file>scalable/instances/neoforged.svg</file>
|
||||||
<file>128x128/instances/forge.png</file> <!-- LGPL3 Forge Development LLC -->
|
<file>128x128/instances/forge.png</file> <!-- LGPL3 Forge Development LLC -->
|
||||||
<file>128x128/instances/liteloader.png</file> <!-- CC-BY-SA 4.0 LiteLoader -->
|
<file>128x128/instances/liteloader.png</file> <!-- CC-BY-SA 4.0 LiteLoader -->
|
||||||
|
|
||||||
|
<!-- java providers -->
|
||||||
|
<file>scalable/adoptium.svg</file> <!-- The Adoptium Logo is a registered trademark of the Eclipse Foundation. -->
|
||||||
|
<file>scalable/azul.svg</file> <!-- Azul, Zulu, Azul Systems, the Azul Systems logo, Azul Zulu are either registered trademarks or trademarks of Azul Systems, registered in the U.S. and elsewhere. -->
|
||||||
|
<file>scalable/mojang.svg</file> <!-- The Mojang Logo is a registered trademark of Mojang AB. -->
|
||||||
|
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
180
launcher/resources/multimc/scalable/adoptium.svg
Normal file
180
launcher/resources/multimc/scalable/adoptium.svg
Normal file
@ -0,0 +1,180 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
sodipodi:docname="Eclipse_Adoptium_Logo_A_only_no_outline.svg"
|
||||||
|
inkscape:version="1.3 (0e150ed6c4, 2023-07-21)"
|
||||||
|
id="svg8"
|
||||||
|
version="1.1"
|
||||||
|
viewBox="0 0 800 800"
|
||||||
|
height="800"
|
||||||
|
width="800"
|
||||||
|
inkscape:export-filename="Eclipse_Adoptium_Logo.png"
|
||||||
|
inkscape:export-xdpi="61.439999"
|
||||||
|
inkscape:export-ydpi="61.439999"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/">
|
||||||
|
<defs
|
||||||
|
id="defs2">
|
||||||
|
<clipPath
|
||||||
|
clipPathUnits="userSpaceOnUse"
|
||||||
|
id="clipPath242">
|
||||||
|
<path
|
||||||
|
d="m 987.855,678.469 -0.019,-0.008 -107.453,233.098 -81.121,-175.989 235.718,-106.09 0.01,0.02 c -21.01,10.078 -37.838,27.52 -47.135,48.969 z"
|
||||||
|
id="path240" />
|
||||||
|
</clipPath>
|
||||||
|
<linearGradient
|
||||||
|
x1="0"
|
||||||
|
y1="0"
|
||||||
|
x2="1"
|
||||||
|
y2="0"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
gradientTransform="matrix(-481.882,253.823,253.823,481.882,1152.35,658.95)"
|
||||||
|
spreadMethod="pad"
|
||||||
|
id="linearGradient248">
|
||||||
|
<stop
|
||||||
|
style="stop-opacity:1;stop-color:#421644"
|
||||||
|
offset="0"
|
||||||
|
id="stop244" />
|
||||||
|
<stop
|
||||||
|
style="stop-opacity:1;stop-color:#151530"
|
||||||
|
offset="1"
|
||||||
|
id="stop246" />
|
||||||
|
</linearGradient>
|
||||||
|
<clipPath
|
||||||
|
clipPathUnits="userSpaceOnUse"
|
||||||
|
id="clipPath258">
|
||||||
|
<path
|
||||||
|
d="m 1164.62,758.102 0.08,0.039 -194.618,422.029 c -0.547,1.32 -1.184,2.59 -1.789,3.88 l -1.453,3.16 -0.059,-0.03 c -0.324,0.65 -0.703,1.27 -1.054,1.9 7.382,-13.68 11.589,-29.34 11.589,-45.98 0,-14.34 -3.191,-27.91 -8.777,-40.15 l 0.059,-0.03 -88.215,-191.361 107.453,-233.098 0.019,0.008 c 14.915,-34.387 49.125,-58.457 89.005,-58.457 53.57,0 96.99,43.429 96.99,97 0,14.707 -3.37,28.597 -9.23,41.09 z"
|
||||||
|
id="path256" />
|
||||||
|
</clipPath>
|
||||||
|
<linearGradient
|
||||||
|
x1="0"
|
||||||
|
y1="0"
|
||||||
|
x2="1"
|
||||||
|
y2="0"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
gradientTransform="matrix(265.274,-595.434,-595.434,-265.274,846.292,1230.46)"
|
||||||
|
spreadMethod="pad"
|
||||||
|
id="linearGradient264">
|
||||||
|
<stop
|
||||||
|
style="stop-opacity:1;stop-color:#a21058"
|
||||||
|
offset="0"
|
||||||
|
id="stop260" />
|
||||||
|
<stop
|
||||||
|
style="stop-opacity:1;stop-color:#421644"
|
||||||
|
offset="1"
|
||||||
|
id="stop262" />
|
||||||
|
</linearGradient>
|
||||||
|
<clipPath
|
||||||
|
clipPathUnits="userSpaceOnUse"
|
||||||
|
id="clipPath274">
|
||||||
|
<path
|
||||||
|
d="m 880.316,1240.11 c -37.687,0 -70.273,-21.54 -86.328,-52.93 l -0.058,0.03 -1.457,-3.16 c -0.606,-1.29 -1.239,-2.56 -1.785,-3.88 l -194.622,-422.029 0.079,-0.039 c -5.86,-12.493 -9.227,-26.383 -9.227,-41.09 0,-53.571 43.418,-97 96.992,-97 39.871,0 74.09,24.07 89.004,58.457 l 0.02,-0.008 195.664,424.459 -0.059,0.03 c 5.586,12.24 8.777,25.81 8.777,40.15 0,53.58 -43.425,97.01 -97,97.01 z"
|
||||||
|
id="path272" />
|
||||||
|
</clipPath>
|
||||||
|
<linearGradient
|
||||||
|
x1="0"
|
||||||
|
y1="0"
|
||||||
|
x2="1"
|
||||||
|
y2="0"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
gradientTransform="matrix(259.548,595.434,595.434,-259.548,649.304,625.36)"
|
||||||
|
spreadMethod="pad"
|
||||||
|
id="linearGradient280">
|
||||||
|
<stop
|
||||||
|
style="stop-opacity:1;stop-color:#ee1a6d"
|
||||||
|
offset="0"
|
||||||
|
id="stop276" />
|
||||||
|
<stop
|
||||||
|
style="stop-opacity:1;stop-color:#a21058"
|
||||||
|
offset="1"
|
||||||
|
id="stop278" />
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
<sodipodi:namedview
|
||||||
|
height="100mm"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:window-y="-8"
|
||||||
|
inkscape:window-x="1912"
|
||||||
|
inkscape:window-height="1057"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:document-rotation="0"
|
||||||
|
inkscape:current-layer="g216"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
inkscape:cy="396.88538"
|
||||||
|
inkscape:cx="322.07976"
|
||||||
|
inkscape:zoom="0.72187089"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
borderopacity="1.0"
|
||||||
|
bordercolor="#666666"
|
||||||
|
pagecolor="#494949"
|
||||||
|
id="base"
|
||||||
|
inkscape:showpageshadow="0"
|
||||||
|
inkscape:pagecheckerboard="1"
|
||||||
|
inkscape:deskcolor="#505050" />
|
||||||
|
<metadata
|
||||||
|
id="metadata5">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
id="layer1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
inkscape:label="Layer 1">
|
||||||
|
<g
|
||||||
|
inkscape:export-ydpi="96"
|
||||||
|
inkscape:export-xdpi="96"
|
||||||
|
transform="matrix(0.0826697,0,0,-0.0826697,-36.864228,126.62103)"
|
||||||
|
id="g216">
|
||||||
|
<g
|
||||||
|
id="g236"
|
||||||
|
transform="matrix(13.679999,0,0,13.679976,-6760.5652,-16025.746)">
|
||||||
|
<g
|
||||||
|
clip-path="url(#clipPath242)"
|
||||||
|
id="g238">
|
||||||
|
<path
|
||||||
|
id="path250"
|
||||||
|
style="fill:url(#linearGradient248);fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||||
|
d="m 987.855,678.469 -0.019,-0.008 -107.453,233.098 -81.121,-175.989 235.718,-106.09 0.01,0.02 c -21.01,10.078 -37.838,27.52 -47.135,48.969" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g252"
|
||||||
|
transform="matrix(13.679999,0,0,13.679976,-6760.5652,-16025.746)">
|
||||||
|
<g
|
||||||
|
clip-path="url(#clipPath258)"
|
||||||
|
id="g254">
|
||||||
|
<path
|
||||||
|
id="path266"
|
||||||
|
style="fill:url(#linearGradient264);fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||||
|
d="m 1164.62,758.102 0.08,0.039 -194.618,422.029 c -0.547,1.32 -1.184,2.59 -1.789,3.88 l -1.453,3.16 -0.059,-0.03 c -0.324,0.65 -0.703,1.27 -1.054,1.9 7.382,-13.68 11.589,-29.34 11.589,-45.98 0,-14.34 -3.191,-27.91 -8.777,-40.15 l 0.059,-0.03 -88.215,-191.361 107.453,-233.098 0.019,0.008 c 14.915,-34.387 49.125,-58.457 89.005,-58.457 53.57,0 96.99,43.429 96.99,97 0,14.707 -3.37,28.597 -9.23,41.09" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g268"
|
||||||
|
transform="matrix(1.2000009,0,0,1.1999989,-853.84911,665.71675)">
|
||||||
|
<g
|
||||||
|
clip-path="url(#clipPath274)"
|
||||||
|
id="g270"
|
||||||
|
transform="matrix(11.39999,0,0,11.39999,-4922.2595,-13909.564)">
|
||||||
|
<path
|
||||||
|
id="path282"
|
||||||
|
style="fill:url(#linearGradient280);fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||||
|
d="m 880.316,1240.11 c -37.687,0 -70.273,-21.54 -86.328,-52.93 l -0.058,0.03 -1.457,-3.16 c -0.606,-1.29 -1.239,-2.56 -1.785,-3.88 l -194.622,-422.029 0.079,-0.039 c -5.86,-12.493 -9.227,-26.383 -9.227,-41.09 0,-53.571 43.418,-97 96.992,-97 39.871,0 74.09,24.07 89.004,58.457 l 0.02,-0.008 195.664,424.459 -0.059,0.03 c 5.586,12.24 8.777,25.81 8.777,40.15 0,53.58 -43.425,97.01 -97,97.01" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 6.7 KiB |
17
launcher/resources/multimc/scalable/azul.svg
Normal file
17
launcher/resources/multimc/scalable/azul.svg
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 64 64" fill="none" style="scroll-behavior: auto !important;">
|
||||||
|
<path d="M26.792 4.49429L7.62244 44.4309C7.20797 45.2944 8.12743 46.1903 8.97988 45.7536L28.26 35.8772C28.6557 35.6745 29.1376 35.7574 29.4429 36.0805L53.2128 61.2399C53.994 62.0668 55.3295 61.1553 54.844 60.1264L28.5979 4.50031C28.2386 3.73874 27.1564 3.73514 26.792 4.49429Z" fill="#00374A"/>
|
||||||
|
<path d="M26.792 4.49429L7.62244 44.4309C7.20797 45.2944 8.12743 46.1903 8.97988 45.7536L28.26 35.8772C28.6557 35.6745 29.1376 35.7574 29.4429 36.0805L53.2128 61.2399C53.994 62.0668 55.3295 61.1553 54.844 60.1264L28.5979 4.50031C28.2386 3.73874 27.1564 3.73514 26.792 4.49429Z" fill="url(#paint0_linear_3578_2134)" fill-opacity="0.7" style="mix-blend-mode:overlay"/>
|
||||||
|
<path d="M34.0172 15.5765L60.9237 19.1042C61.9046 19.2329 62.1231 20.5555 61.2357 20.9928L33.4872 34.6659L9.3254 45.9918C8.34481 46.4514 7.43514 45.2419 8.14881 44.4273L33.135 15.909C33.3551 15.6578 33.686 15.5331 34.0172 15.5765Z" fill="#006588"/>
|
||||||
|
<path d="M34.0172 15.5765L60.9237 19.1042C61.9046 19.2329 62.1231 20.5555 61.2357 20.9928L33.4872 34.6659L9.3254 45.9918C8.34481 46.4514 7.43514 45.2419 8.14881 44.4273L33.135 15.909C33.3551 15.6578 33.686 15.5331 34.0172 15.5765Z" fill="url(#paint1_linear_3578_2134)" fill-opacity="0.7" style="mix-blend-mode:overlay"/>
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="paint0_linear_3578_2134" x1="31.2618" y1="2.59998" x2="31.2618" y2="65.8" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop stop-color="white" stop-opacity="0"/>
|
||||||
|
<stop offset="1" stop-color="white"/>
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient id="paint1_linear_3578_2134" x1="46.2268" y1="4.17812" x2="31.5574" y2="56.1518" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop stop-color="white" stop-opacity="0"/>
|
||||||
|
<stop offset="1" stop-color="white"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.9 KiB |
55
launcher/resources/multimc/scalable/mojang.svg
Normal file
55
launcher/resources/multimc/scalable/mojang.svg
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
version="1.1"
|
||||||
|
width="800"
|
||||||
|
height="800"
|
||||||
|
viewBox="0 0 800 800"
|
||||||
|
xml:space="preserve"
|
||||||
|
style="scroll-behavior: auto !important;"
|
||||||
|
id="svg4"
|
||||||
|
sodipodi:docname="Mojang_Studios_Logo_(2020,_icon).svg"
|
||||||
|
inkscape:export-filename="Mojang_Studios_Logo_(2020,_icon).png"
|
||||||
|
inkscape:export-xdpi="61.439999"
|
||||||
|
inkscape:export-ydpi="61.439999"
|
||||||
|
inkscape:version="1.3 (0e150ed6c4, 2023-07-21)"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
|
||||||
|
id="namedview4"
|
||||||
|
pagecolor="#505050"
|
||||||
|
bordercolor="#ffffff"
|
||||||
|
borderopacity="1"
|
||||||
|
inkscape:showpageshadow="0"
|
||||||
|
inkscape:pageopacity="0"
|
||||||
|
inkscape:pagecheckerboard="1"
|
||||||
|
inkscape:deskcolor="#505050"
|
||||||
|
inkscape:zoom="1.46625"
|
||||||
|
inkscape:cx="374.08355"
|
||||||
|
inkscape:cy="369.30946"
|
||||||
|
inkscape:window-width="2560"
|
||||||
|
inkscape:window-height="1369"
|
||||||
|
inkscape:window-x="6392"
|
||||||
|
inkscape:window-y="802"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="g3" /> <desc
|
||||||
|
id="desc1">Created with Fabric.js 3.6.3</desc> <defs
|
||||||
|
id="defs1"> </defs> <g
|
||||||
|
transform="matrix(2 0 0 2 399.75 399.75)"
|
||||||
|
id="g4"> <g
|
||||||
|
style=""
|
||||||
|
id="g3"> <g
|
||||||
|
transform="matrix(3.37 0 0 3.37 0 0)"
|
||||||
|
id="g1"> <polygon
|
||||||
|
style="display:inline;opacity:1;fill:#f0313b;fill-rule:nonzero;stroke:#f0313b;stroke-width:8;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0"
|
||||||
|
vector-effect="non-scaling-stroke"
|
||||||
|
points="50,50 50,-50 -50,-50 -50,50 "
|
||||||
|
id="polygon1" /> </g> <g
|
||||||
|
transform="matrix(3.78 0 0 3.78 0.01 0)"
|
||||||
|
id="g2"> <path
|
||||||
|
style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(255,255,255); fill-rule: nonzero; opacity: 1;"
|
||||||
|
vector-effect="non-scaling-stroke"
|
||||||
|
transform=" translate(-44.68, -41.16)"
|
||||||
|
d="M 13.51988 41.11152 q 0 -12.31086 0.0047 -24.62173 c 0.00469 -2.87722 0.16418 -3.03875 3.01027 -3.04146 q 21.527 -0.02051 43.054 -0.01353 c 2.06114 0.0004 2.36366 0.32134 2.39718 2.42144 c 0.0238 1.49194 -0.01523 2.98567 0.03993 4.47616 a 6.77817 6.77817 0 0 0 6.69647 6.91868 c 1.65784 0.11443 3.328 0.04044 4.99213 0.07612 c 1.797 0.03852 2.04939 0.30467 2.12207 2.13943 c 0.01137 0.28664 0.01239 0.57383 0.01247 0.86076 q 0.00432 17.64834 0.00423 35.29668 c -0.00158 3.2118 -0.0499 3.24957 -3.28974 3.26017 q -3.78871 0.01236 -7.57745 -0.01166 c -2.96088 -0.02069 -3.03087 -0.09046 -3.032 -2.98084 q -0.00659 -16.87367 -0.00343 -33.74735 c 0 -0.40175 0.01018 -0.80387 -0.00321 -1.20519 a 3.329 3.329 0 0 0 -3.548 -3.56756 c -1.08962 -0.032 -2.18238 -0.03167 -3.27158 0.01034 a 3.34773 3.34773 0 0 0 -3.482 3.47659 c -0.03516 0.62965 -0.02128 1.26231 -0.02172 1.8936 q -0.00641 9.21165 -0.01056 18.42326 c -0.00046 0.68869 0.01794 1.37909 -0.02307 2.06567 c -0.075 1.25525 -0.44257 1.71282 -1.65149 1.72825 q -5.25132 0.06705 -10.50391 -0.00754 c -1.2165 -0.01879 -1.58169 -0.48679 -1.66785 -1.72683 c -0.03575 -0.51435 -0.01843 -1.03265 -0.019 -1.54914 q -0.0112 -9.81428 -0.0222 -19.62854 a 13.12088 13.12088 0 0 0 -0.05025 -1.71908 a 3.25128 3.25128 0 0 0 -3.10179 -2.93609 a 33.39881 33.39881 0 0 0 -3.95853 0.00271 a 3.1568 3.1568 0 0 0 -3.15611 3.21043 c -0.05842 1.26029 -0.03349 2.52474 -0.03457 3.78735 q -0.01343 15.66842 -0.02277 31.33681 c -0.00035 0.45913 0.01748 0.92 -0.01557 1.377 c -0.09 1.24451 -0.45629 1.713 -1.67232 1.72878 q -5.25117 0.06813 -10.50381 -0.01831 c -1.23915 -0.02079 -1.58295 -0.457 -1.6812 -1.71692 c -0.04454 -0.5709 -0.02489 -1.1472 -0.025 -1.72107 q -0.00183 -12.13872 -0.00083 -24.27744 Z"
|
||||||
|
stroke-linecap="round"
|
||||||
|
id="path1" /> </g> </g> </g> </svg>
|
After Width: | Height: | Size: 3.8 KiB |
@ -26,10 +26,6 @@ class QDialogButtonBox;
|
|||||||
class VersionSelectWidget;
|
class VersionSelectWidget;
|
||||||
class QPushButton;
|
class QPushButton;
|
||||||
|
|
||||||
namespace Ui {
|
|
||||||
class VersionSelectDialog;
|
|
||||||
}
|
|
||||||
|
|
||||||
class VersionProxyModel;
|
class VersionProxyModel;
|
||||||
|
|
||||||
class VersionSelectDialog : public QDialog {
|
class VersionSelectDialog : public QDialog {
|
||||||
|
338
launcher/ui/java/InstallJavaDialog.cpp
Normal file
338
launcher/ui/java/InstallJavaDialog.cpp
Normal file
@ -0,0 +1,338 @@
|
|||||||
|
// 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 "InstallJavaDialog.h"
|
||||||
|
|
||||||
|
#include <QCheckBox>
|
||||||
|
#include <QDialogButtonBox>
|
||||||
|
#include <QMessageBox>
|
||||||
|
#include <QPushButton>
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
#include <QWidget>
|
||||||
|
|
||||||
|
#include "Application.h"
|
||||||
|
#include "BaseVersionList.h"
|
||||||
|
#include "FileSystem.h"
|
||||||
|
#include "Filter.h"
|
||||||
|
#include "java/download/ArchiveDownloadTask.h"
|
||||||
|
#include "java/download/ManifestDownloadTask.h"
|
||||||
|
#include "meta/Index.h"
|
||||||
|
#include "meta/VersionList.h"
|
||||||
|
#include "minecraft/MinecraftInstance.h"
|
||||||
|
#include "minecraft/PackProfile.h"
|
||||||
|
#include "ui/dialogs/CustomMessageBox.h"
|
||||||
|
#include "ui/dialogs/ProgressDialog.h"
|
||||||
|
#include "ui/java/VersionList.h"
|
||||||
|
#include "ui/widgets/PageContainer.h"
|
||||||
|
#include "ui/widgets/VersionSelectWidget.h"
|
||||||
|
|
||||||
|
class InstallJavaPage : public QWidget, public BasePage {
|
||||||
|
public:
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit InstallJavaPage(const QString& id, const QString& iconName, const QString& name, QWidget* parent = nullptr)
|
||||||
|
: QWidget(parent), uid(id), iconName(iconName), name(name)
|
||||||
|
{
|
||||||
|
setObjectName(QStringLiteral("VersionSelectWidget"));
|
||||||
|
horizontalLayout = new QHBoxLayout(this);
|
||||||
|
horizontalLayout->setObjectName(QStringLiteral("horizontalLayout"));
|
||||||
|
horizontalLayout->setContentsMargins(0, 0, 0, 0);
|
||||||
|
|
||||||
|
majorVersionSelect = new VersionSelectWidget(this);
|
||||||
|
majorVersionSelect->selectCurrent();
|
||||||
|
majorVersionSelect->setEmptyString(tr("No java versions are currently available in the meta."));
|
||||||
|
majorVersionSelect->setEmptyErrorString(tr("Couldn't load or download the java version lists!"));
|
||||||
|
horizontalLayout->addWidget(majorVersionSelect, 1);
|
||||||
|
|
||||||
|
javaVersionSelect = new VersionSelectWidget(this);
|
||||||
|
javaVersionSelect->setEmptyString(tr("No java versions are currently available for your OS."));
|
||||||
|
javaVersionSelect->setEmptyErrorString(tr("Couldn't load or download the java version lists!"));
|
||||||
|
horizontalLayout->addWidget(javaVersionSelect, 4);
|
||||||
|
connect(majorVersionSelect, &VersionSelectWidget::selectedVersionChanged, this, &InstallJavaPage::setSelectedVersion);
|
||||||
|
connect(majorVersionSelect, &VersionSelectWidget::selectedVersionChanged, this, &InstallJavaPage::selectionChanged);
|
||||||
|
connect(javaVersionSelect, &VersionSelectWidget::selectedVersionChanged, this, &InstallJavaPage::selectionChanged);
|
||||||
|
|
||||||
|
QMetaObject::connectSlotsByName(this);
|
||||||
|
}
|
||||||
|
~InstallJavaPage()
|
||||||
|
{
|
||||||
|
delete horizontalLayout;
|
||||||
|
delete majorVersionSelect;
|
||||||
|
delete javaVersionSelect;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! loads the list if needed.
|
||||||
|
void initialize(Meta::VersionList::Ptr vlist)
|
||||||
|
{
|
||||||
|
vlist->setProvidedRoles({ BaseVersionList::JavaMajorRole, BaseVersionList::RecommendedRole, BaseVersionList::VersionPointerRole });
|
||||||
|
majorVersionSelect->initialize(vlist.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
void setSelectedVersion(BaseVersion::Ptr version)
|
||||||
|
{
|
||||||
|
auto dcast = std::dynamic_pointer_cast<Meta::Version>(version);
|
||||||
|
if (!dcast) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
javaVersionSelect->initialize(new Java::VersionList(dcast, this));
|
||||||
|
javaVersionSelect->selectCurrent();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString id() const override { return uid; }
|
||||||
|
QString displayName() const override { return name; }
|
||||||
|
QIcon icon() const override { return APPLICATION->getThemedIcon(iconName); }
|
||||||
|
|
||||||
|
void openedImpl() override
|
||||||
|
{
|
||||||
|
if (loaded)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const auto versions = APPLICATION->metadataIndex()->get(uid);
|
||||||
|
if (!versions)
|
||||||
|
return;
|
||||||
|
|
||||||
|
initialize(versions);
|
||||||
|
loaded = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setParentContainer(BasePageContainer* container) override
|
||||||
|
{
|
||||||
|
auto dialog = dynamic_cast<QDialog*>(dynamic_cast<PageContainer*>(container)->parent());
|
||||||
|
connect(javaVersionSelect->view(), &QAbstractItemView::doubleClicked, dialog, &QDialog::accept);
|
||||||
|
}
|
||||||
|
|
||||||
|
BaseVersion::Ptr selectedVersion() const { return javaVersionSelect->selectedVersion(); }
|
||||||
|
void selectSearch() { javaVersionSelect->selectSearch(); }
|
||||||
|
void loadList()
|
||||||
|
{
|
||||||
|
majorVersionSelect->loadList();
|
||||||
|
javaVersionSelect->loadList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void setRecommendedMajors(const QStringList& majors)
|
||||||
|
{
|
||||||
|
m_recommended_majors = majors;
|
||||||
|
recommendedFilterChanged();
|
||||||
|
}
|
||||||
|
void setRecomend(bool recomend)
|
||||||
|
{
|
||||||
|
m_recommend = recomend;
|
||||||
|
recommendedFilterChanged();
|
||||||
|
}
|
||||||
|
void recommendedFilterChanged()
|
||||||
|
{
|
||||||
|
if (m_recommend) {
|
||||||
|
majorVersionSelect->setFilter(BaseVersionList::ModelRoles::JavaMajorRole, new ExactListFilter(m_recommended_majors));
|
||||||
|
} else {
|
||||||
|
majorVersionSelect->setFilter(BaseVersionList::ModelRoles::JavaMajorRole, new ExactListFilter());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void selectionChanged();
|
||||||
|
|
||||||
|
private:
|
||||||
|
const QString uid;
|
||||||
|
const QString iconName;
|
||||||
|
const QString name;
|
||||||
|
bool loaded = false;
|
||||||
|
|
||||||
|
QHBoxLayout* horizontalLayout = nullptr;
|
||||||
|
VersionSelectWidget* majorVersionSelect = nullptr;
|
||||||
|
VersionSelectWidget* javaVersionSelect = nullptr;
|
||||||
|
|
||||||
|
QStringList m_recommended_majors;
|
||||||
|
bool m_recommend;
|
||||||
|
};
|
||||||
|
|
||||||
|
static InstallJavaPage* pageCast(BasePage* page)
|
||||||
|
{
|
||||||
|
auto result = dynamic_cast<InstallJavaPage*>(page);
|
||||||
|
Q_ASSERT(result != nullptr);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
namespace Java {
|
||||||
|
QStringList getRecommendedJavaVersionsFromVersionList(Meta::VersionList::Ptr list)
|
||||||
|
{
|
||||||
|
QStringList recommendedJavas;
|
||||||
|
for (auto ver : list->versions()) {
|
||||||
|
auto major = ver->version();
|
||||||
|
if (major.startsWith("java")) {
|
||||||
|
major = "Java " + major.mid(4);
|
||||||
|
}
|
||||||
|
recommendedJavas.append(major);
|
||||||
|
}
|
||||||
|
return recommendedJavas;
|
||||||
|
}
|
||||||
|
|
||||||
|
InstallDialog::InstallDialog(const QString& uid, BaseInstance* instance, QWidget* parent)
|
||||||
|
: QDialog(parent), container(new PageContainer(this, QString(), this)), buttons(new QDialogButtonBox(this))
|
||||||
|
{
|
||||||
|
auto layout = new QVBoxLayout(this);
|
||||||
|
|
||||||
|
container->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
|
||||||
|
layout->addWidget(container);
|
||||||
|
|
||||||
|
auto buttonLayout = new QHBoxLayout(this);
|
||||||
|
auto refreshLayout = new QHBoxLayout(this);
|
||||||
|
|
||||||
|
auto refreshButton = new QPushButton(tr("&Refresh"), this);
|
||||||
|
connect(refreshButton, &QPushButton::clicked, this, [this] { pageCast(container->selectedPage())->loadList(); });
|
||||||
|
refreshLayout->addWidget(refreshButton);
|
||||||
|
|
||||||
|
auto recommendedCheckBox = new QCheckBox("Recommended", this);
|
||||||
|
recommendedCheckBox->setCheckState(Qt::CheckState::Checked);
|
||||||
|
connect(recommendedCheckBox, &QCheckBox::stateChanged, this, [this](int state) {
|
||||||
|
for (BasePage* page : container->getPages()) {
|
||||||
|
pageCast(page)->setRecomend(state == Qt::Checked);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
refreshLayout->addWidget(recommendedCheckBox);
|
||||||
|
buttonLayout->addLayout(refreshLayout);
|
||||||
|
|
||||||
|
buttons->setOrientation(Qt::Horizontal);
|
||||||
|
buttons->setStandardButtons(QDialogButtonBox::Cancel | QDialogButtonBox::Ok);
|
||||||
|
buttons->button(QDialogButtonBox::Ok)->setText(tr("Download"));
|
||||||
|
connect(buttons, &QDialogButtonBox::accepted, this, &QDialog::accept);
|
||||||
|
connect(buttons, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
||||||
|
buttonLayout->addWidget(buttons);
|
||||||
|
|
||||||
|
layout->addLayout(buttonLayout);
|
||||||
|
|
||||||
|
setWindowTitle(dialogTitle());
|
||||||
|
setWindowModality(Qt::WindowModal);
|
||||||
|
resize(840, 480);
|
||||||
|
|
||||||
|
QStringList recommendedJavas;
|
||||||
|
if (auto mcInst = dynamic_cast<MinecraftInstance*>(instance); mcInst) {
|
||||||
|
auto mc = mcInst->getPackProfile()->getComponent("net.minecraft");
|
||||||
|
if (mc) {
|
||||||
|
auto file = mc->getVersionFile(); // no need for load as it should already be loaded
|
||||||
|
if (file) {
|
||||||
|
for (auto major : file->compatibleJavaMajors) {
|
||||||
|
recommendedJavas.append(QString("Java %1").arg(major));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const auto versions = APPLICATION->metadataIndex()->get("net.minecraft.java");
|
||||||
|
if (versions) {
|
||||||
|
if (versions->isLoaded()) {
|
||||||
|
recommendedJavas = getRecommendedJavaVersionsFromVersionList(versions);
|
||||||
|
} else {
|
||||||
|
auto newTask = versions->getLoadTask();
|
||||||
|
if (newTask) {
|
||||||
|
connect(newTask.get(), &Task::succeeded, this, [this, versions] {
|
||||||
|
auto recommendedJavas = getRecommendedJavaVersionsFromVersionList(versions);
|
||||||
|
for (BasePage* page : container->getPages()) {
|
||||||
|
pageCast(page)->setRecommendedMajors(recommendedJavas);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (!newTask->isRunning())
|
||||||
|
newTask->start();
|
||||||
|
} else {
|
||||||
|
recommendedJavas = getRecommendedJavaVersionsFromVersionList(versions);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (BasePage* page : container->getPages()) {
|
||||||
|
if (page->id() == uid)
|
||||||
|
container->selectPage(page->id());
|
||||||
|
|
||||||
|
auto cast = pageCast(page);
|
||||||
|
cast->setRecomend(true);
|
||||||
|
connect(cast, &InstallJavaPage::selectionChanged, this, [this, cast] { validate(cast); });
|
||||||
|
if (!recommendedJavas.isEmpty()) {
|
||||||
|
cast->setRecommendedMajors(recommendedJavas);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
connect(container, &PageContainer::selectedPageChanged, this, [this](BasePage* previous, BasePage* selected) { validate(selected); });
|
||||||
|
pageCast(container->selectedPage())->selectSearch();
|
||||||
|
validate(container->selectedPage());
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<BasePage*> InstallDialog::getPages()
|
||||||
|
{
|
||||||
|
return {
|
||||||
|
// Mojang
|
||||||
|
new InstallJavaPage("net.minecraft.java", "mojang", tr("Mojang")),
|
||||||
|
// Adoptium
|
||||||
|
new InstallJavaPage("net.adoptium.java", "adoptium", tr("Adoptium")),
|
||||||
|
// Azul
|
||||||
|
new InstallJavaPage("com.azul.java", "azul", tr("Azul Zulu")),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
QString InstallDialog::dialogTitle()
|
||||||
|
{
|
||||||
|
return tr("Install Java");
|
||||||
|
}
|
||||||
|
|
||||||
|
void InstallDialog::validate(BasePage* selected)
|
||||||
|
{
|
||||||
|
buttons->button(QDialogButtonBox::Ok)->setEnabled(!!std::dynamic_pointer_cast<Java::Metadata>(pageCast(selected)->selectedVersion()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void InstallDialog::done(int result)
|
||||||
|
{
|
||||||
|
if (result == Accepted) {
|
||||||
|
auto* page = pageCast(container->selectedPage());
|
||||||
|
if (page->selectedVersion()) {
|
||||||
|
auto meta = std::dynamic_pointer_cast<Java::Metadata>(page->selectedVersion());
|
||||||
|
if (meta) {
|
||||||
|
Task::Ptr task;
|
||||||
|
auto final_path = FS::PathCombine(APPLICATION->javaPath(), meta->m_name);
|
||||||
|
auto deletePath = [final_path] { FS::deletePath(final_path); };
|
||||||
|
switch (meta->downloadType) {
|
||||||
|
case Java::DownloadType::Manifest:
|
||||||
|
task = makeShared<ManifestDownloadTask>(meta->url, final_path, meta->checksumType, meta->checksumHash);
|
||||||
|
break;
|
||||||
|
case Java::DownloadType::Archive:
|
||||||
|
task = makeShared<ArchiveDownloadTask>(meta->url, final_path, meta->checksumType, meta->checksumHash);
|
||||||
|
break;
|
||||||
|
case Java::DownloadType::Unknown:
|
||||||
|
QString error = QString(tr("Could not determine Java download type!"));
|
||||||
|
CustomMessageBox::selectable(this, tr("Error"), error, QMessageBox::Warning)->show();
|
||||||
|
deletePath();
|
||||||
|
}
|
||||||
|
connect(task.get(), &Task::failed, this, [this, &deletePath](QString reason) {
|
||||||
|
QString error = QString("Java download failed: %1").arg(reason);
|
||||||
|
CustomMessageBox::selectable(this, tr("Error"), error, QMessageBox::Warning)->show();
|
||||||
|
deletePath();
|
||||||
|
});
|
||||||
|
connect(task.get(), &Task::aborted, this, deletePath);
|
||||||
|
ProgressDialog pg(this);
|
||||||
|
pg.setSkipButton(true, tr("Abort"));
|
||||||
|
pg.execWithTask(task.get());
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QDialog::done(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Java
|
||||||
|
|
||||||
|
#include "InstallJavaDialog.moc"
|
47
launcher/ui/java/InstallJavaDialog.h
Normal file
47
launcher/ui/java/InstallJavaDialog.h
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
// 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 "BaseInstance.h"
|
||||||
|
#include "ui/pages/BasePageProvider.h"
|
||||||
|
|
||||||
|
class MinecraftInstance;
|
||||||
|
class PageContainer;
|
||||||
|
class PackProfile;
|
||||||
|
class QDialogButtonBox;
|
||||||
|
|
||||||
|
namespace Java {
|
||||||
|
class InstallDialog final : public QDialog, private BasePageProvider {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit InstallDialog(const QString& uid = QString(), BaseInstance* instance = nullptr, QWidget* parent = nullptr);
|
||||||
|
|
||||||
|
QList<BasePage*> getPages() override;
|
||||||
|
QString dialogTitle() override;
|
||||||
|
|
||||||
|
void validate(BasePage* selected);
|
||||||
|
void done(int result) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
PageContainer* container;
|
||||||
|
QDialogButtonBox* buttons;
|
||||||
|
};
|
||||||
|
} // namespace Java
|
126
launcher/ui/java/VersionList.cpp
Normal file
126
launcher/ui/java/VersionList.cpp
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
// 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 "VersionList.h"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "BaseVersionList.h"
|
||||||
|
#include "SysInfo.h"
|
||||||
|
#include "java/JavaMetadata.h"
|
||||||
|
#include "meta/VersionList.h"
|
||||||
|
|
||||||
|
namespace Java {
|
||||||
|
|
||||||
|
VersionList::VersionList(Meta::Version::Ptr version, QObject* parent) : BaseVersionList(parent), m_version(version)
|
||||||
|
{
|
||||||
|
if (version->isLoaded())
|
||||||
|
sortVersions();
|
||||||
|
}
|
||||||
|
|
||||||
|
Task::Ptr VersionList::getLoadTask()
|
||||||
|
{
|
||||||
|
auto task = m_version->loadTask(Net::Mode::Online);
|
||||||
|
connect(task.get(), &Task::finished, this, &VersionList::sortVersions);
|
||||||
|
return task;
|
||||||
|
}
|
||||||
|
|
||||||
|
const BaseVersion::Ptr VersionList::at(int i) const
|
||||||
|
{
|
||||||
|
return m_vlist.at(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VersionList::isLoaded()
|
||||||
|
{
|
||||||
|
return m_version->isLoaded();
|
||||||
|
}
|
||||||
|
|
||||||
|
int VersionList::count() const
|
||||||
|
{
|
||||||
|
return m_vlist.count();
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant VersionList::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->version.toString();
|
||||||
|
case RecommendedRole:
|
||||||
|
return false; // do not recommend any version
|
||||||
|
case JavaNameRole:
|
||||||
|
return version->name();
|
||||||
|
case JavaMajorRole: {
|
||||||
|
auto major = version->version.toString();
|
||||||
|
if (major.startsWith("java")) {
|
||||||
|
major = "Java " + major.mid(4);
|
||||||
|
}
|
||||||
|
return major;
|
||||||
|
}
|
||||||
|
case TypeRole:
|
||||||
|
return version->packageType;
|
||||||
|
case Meta::VersionList::TimeRole:
|
||||||
|
return version->releaseTime;
|
||||||
|
default:
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BaseVersionList::RoleList VersionList::providesRoles() const
|
||||||
|
{
|
||||||
|
return { VersionPointerRole, VersionIdRole, VersionRole, RecommendedRole, JavaNameRole, TypeRole, Meta::VersionList::TimeRole };
|
||||||
|
}
|
||||||
|
|
||||||
|
bool sortJavas(BaseVersion::Ptr left, BaseVersion::Ptr right)
|
||||||
|
{
|
||||||
|
auto rleft = std::dynamic_pointer_cast<Java::Metadata>(right);
|
||||||
|
auto rright = std::dynamic_pointer_cast<Java::Metadata>(left);
|
||||||
|
return (*rleft) < (*rright);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VersionList::sortVersions()
|
||||||
|
{
|
||||||
|
if (!m_version || !m_version->data())
|
||||||
|
return;
|
||||||
|
QString versionStr = SysInfo::getSupportedJavaArchitecture();
|
||||||
|
beginResetModel();
|
||||||
|
auto runtimes = m_version->data()->runtimes;
|
||||||
|
m_vlist = {};
|
||||||
|
if (!versionStr.isEmpty() && !runtimes.isEmpty()) {
|
||||||
|
std::copy_if(runtimes.begin(), runtimes.end(), std::back_inserter(m_vlist),
|
||||||
|
[versionStr](Java::MetadataPtr val) { return val->runtimeOS == versionStr; });
|
||||||
|
std::sort(m_vlist.begin(), m_vlist.end(), sortJavas);
|
||||||
|
} else {
|
||||||
|
qWarning() << "No Java versions found for your operating system." << SysInfo::currentSystem() << " " << SysInfo::useQTForArch();
|
||||||
|
}
|
||||||
|
endResetModel();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Java
|
50
launcher/ui/java/VersionList.h
Normal file
50
launcher/ui/java/VersionList.h
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
// 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 "BaseVersionList.h"
|
||||||
|
#include "java/JavaMetadata.h"
|
||||||
|
#include "meta/Version.h"
|
||||||
|
|
||||||
|
namespace Java {
|
||||||
|
|
||||||
|
class VersionList : public BaseVersionList {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit VersionList(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<Java::MetadataPtr> m_vlist;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Java
|
@ -16,7 +16,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <memory>
|
|
||||||
#include "ui/pages/BasePage.h"
|
#include "ui/pages/BasePage.h"
|
||||||
|
|
||||||
class BasePageProvider {
|
class BasePageProvider {
|
||||||
|
@ -35,12 +35,18 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "JavaPage.h"
|
#include "JavaPage.h"
|
||||||
|
#include "BuildConfig.h"
|
||||||
#include "JavaCommon.h"
|
#include "JavaCommon.h"
|
||||||
|
#include "java/JavaInstall.h"
|
||||||
|
#include "ui/dialogs/CustomMessageBox.h"
|
||||||
|
#include "ui/java/InstallJavaDialog.h"
|
||||||
#include "ui_JavaPage.h"
|
#include "ui_JavaPage.h"
|
||||||
|
|
||||||
|
#include <QCheckBox>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QFileDialog>
|
#include <QFileDialog>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
|
#include <QStringListModel>
|
||||||
#include <QTabBar>
|
#include <QTabBar>
|
||||||
|
|
||||||
#include "ui/dialogs/VersionSelectDialog.h"
|
#include "ui/dialogs/VersionSelectDialog.h"
|
||||||
@ -56,7 +62,22 @@
|
|||||||
JavaPage::JavaPage(QWidget* parent) : QWidget(parent), ui(new Ui::JavaPage)
|
JavaPage::JavaPage(QWidget* parent) : QWidget(parent), ui(new Ui::JavaPage)
|
||||||
{
|
{
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
ui->tabWidget->tabBar()->hide();
|
|
||||||
|
if (BuildConfig.JAVA_DOWNLOADER_ENABLED) {
|
||||||
|
ui->managedJavaList->initialize(new JavaInstallList(this, true));
|
||||||
|
ui->managedJavaList->setResizeOn(2);
|
||||||
|
ui->managedJavaList->selectCurrent();
|
||||||
|
ui->managedJavaList->setEmptyString(tr("No managed java versions are installed"));
|
||||||
|
ui->managedJavaList->setEmptyErrorString(tr("Couldn't load the managed java list!"));
|
||||||
|
connect(ui->autodetectJavaCheckBox, &QCheckBox::stateChanged, this, [this] {
|
||||||
|
ui->autodownloadCheckBox->setEnabled(ui->autodetectJavaCheckBox->isChecked());
|
||||||
|
if (!ui->autodetectJavaCheckBox->isChecked())
|
||||||
|
ui->autodownloadCheckBox->setChecked(false);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
ui->autodownloadCheckBox->setHidden(true);
|
||||||
|
ui->tabWidget->tabBar()->hide();
|
||||||
|
}
|
||||||
|
|
||||||
loadSettings();
|
loadSettings();
|
||||||
updateThresholds();
|
updateThresholds();
|
||||||
@ -94,6 +115,8 @@ void JavaPage::applySettings()
|
|||||||
s->set("JvmArgs", ui->jvmArgsTextBox->toPlainText().replace("\n", " "));
|
s->set("JvmArgs", ui->jvmArgsTextBox->toPlainText().replace("\n", " "));
|
||||||
s->set("IgnoreJavaCompatibility", ui->skipCompatibilityCheckbox->isChecked());
|
s->set("IgnoreJavaCompatibility", ui->skipCompatibilityCheckbox->isChecked());
|
||||||
s->set("IgnoreJavaWizard", ui->skipJavaWizardCheckbox->isChecked());
|
s->set("IgnoreJavaWizard", ui->skipJavaWizardCheckbox->isChecked());
|
||||||
|
s->set("AutomaticJavaSwitch", ui->autodetectJavaCheckBox->isChecked());
|
||||||
|
s->set("AutomaticJavaDownload", ui->autodownloadCheckBox->isChecked());
|
||||||
JavaCommon::checkJVMArgs(s->get("JvmArgs").toString(), this->parentWidget());
|
JavaCommon::checkJVMArgs(s->get("JvmArgs").toString(), this->parentWidget());
|
||||||
}
|
}
|
||||||
void JavaPage::loadSettings()
|
void JavaPage::loadSettings()
|
||||||
@ -116,6 +139,8 @@ void JavaPage::loadSettings()
|
|||||||
ui->jvmArgsTextBox->setPlainText(s->get("JvmArgs").toString());
|
ui->jvmArgsTextBox->setPlainText(s->get("JvmArgs").toString());
|
||||||
ui->skipCompatibilityCheckbox->setChecked(s->get("IgnoreJavaCompatibility").toBool());
|
ui->skipCompatibilityCheckbox->setChecked(s->get("IgnoreJavaCompatibility").toBool());
|
||||||
ui->skipJavaWizardCheckbox->setChecked(s->get("IgnoreJavaWizard").toBool());
|
ui->skipJavaWizardCheckbox->setChecked(s->get("IgnoreJavaWizard").toBool());
|
||||||
|
ui->autodetectJavaCheckBox->setChecked(s->get("AutomaticJavaSwitch").toBool());
|
||||||
|
ui->autodownloadCheckBox->setChecked(s->get("AutomaticJavaSwitch").toBool() && s->get("AutomaticJavaDownload").toBool());
|
||||||
}
|
}
|
||||||
|
|
||||||
void JavaPage::on_javaDetectBtn_clicked()
|
void JavaPage::on_javaDetectBtn_clicked()
|
||||||
@ -134,6 +159,14 @@ void JavaPage::on_javaDetectBtn_clicked()
|
|||||||
if (vselect.result() == QDialog::Accepted && vselect.selectedVersion()) {
|
if (vselect.result() == QDialog::Accepted && vselect.selectedVersion()) {
|
||||||
java = std::dynamic_pointer_cast<JavaInstall>(vselect.selectedVersion());
|
java = std::dynamic_pointer_cast<JavaInstall>(vselect.selectedVersion());
|
||||||
ui->javaPathTextBox->setText(java->path);
|
ui->javaPathTextBox->setText(java->path);
|
||||||
|
if (!java->is_64bit && APPLICATION->settings()->get("MaxMemAlloc").toInt() > 2048) {
|
||||||
|
CustomMessageBox::selectable(this, tr("Confirm Selection"),
|
||||||
|
tr("You selected a 32-bit version of Java.\n"
|
||||||
|
"This installation does not support more than 2048MiB of RAM.\n"
|
||||||
|
"Please make sure that the maximum memory value is lower."),
|
||||||
|
QMessageBox::Warning, QMessageBox::Ok, QMessageBox::Ok)
|
||||||
|
->exec();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -166,6 +199,13 @@ void JavaPage::on_javaTestBtn_clicked()
|
|||||||
checker->run();
|
checker->run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void JavaPage::on_downloadJavaButton_clicked()
|
||||||
|
{
|
||||||
|
auto jdialog = new Java::InstallDialog({}, nullptr, this);
|
||||||
|
jdialog->exec();
|
||||||
|
ui->managedJavaList->loadList();
|
||||||
|
}
|
||||||
|
|
||||||
void JavaPage::on_maxMemSpinBox_valueChanged([[maybe_unused]] int i)
|
void JavaPage::on_maxMemSpinBox_valueChanged([[maybe_unused]] int i)
|
||||||
{
|
{
|
||||||
updateThresholds();
|
updateThresholds();
|
||||||
@ -210,3 +250,35 @@ void JavaPage::updateThresholds()
|
|||||||
ui->labelMaxMemIcon->setPixmap(pix);
|
ui->labelMaxMemIcon->setPixmap(pix);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void JavaPage::on_removeJavaButton_clicked()
|
||||||
|
{
|
||||||
|
auto version = ui->managedJavaList->selectedVersion();
|
||||||
|
auto dcast = std::dynamic_pointer_cast<JavaInstall>(version);
|
||||||
|
if (!dcast) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
QDir dir(APPLICATION->javaPath());
|
||||||
|
|
||||||
|
auto entries = dir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot);
|
||||||
|
for (auto& entry : entries) {
|
||||||
|
if (dcast->path.startsWith(entry.canonicalFilePath())) {
|
||||||
|
auto response = CustomMessageBox::selectable(this, tr("Confirm Deletion"),
|
||||||
|
tr("You are about to remove the Java installation named \"%1\".\n"
|
||||||
|
"Are you sure?")
|
||||||
|
.arg(entry.fileName()),
|
||||||
|
QMessageBox::Warning, QMessageBox::Yes | QMessageBox::No, QMessageBox::No)
|
||||||
|
->exec();
|
||||||
|
|
||||||
|
if (response == QMessageBox::Yes) {
|
||||||
|
FS::deletePath(entry.canonicalFilePath());
|
||||||
|
ui->managedJavaList->loadList();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void JavaPage::on_refreshJavaButton_clicked()
|
||||||
|
{
|
||||||
|
ui->managedJavaList->loadList();
|
||||||
|
}
|
||||||
|
@ -38,7 +38,7 @@
|
|||||||
#include <Application.h>
|
#include <Application.h>
|
||||||
#include <QObjectPtr.h>
|
#include <QObjectPtr.h>
|
||||||
#include <QDialog>
|
#include <QDialog>
|
||||||
#include <memory>
|
#include <QStringListModel>
|
||||||
#include "JavaCommon.h"
|
#include "JavaCommon.h"
|
||||||
#include "ui/pages/BasePage.h"
|
#include "ui/pages/BasePage.h"
|
||||||
|
|
||||||
@ -72,6 +72,9 @@ class JavaPage : public QWidget, public BasePage {
|
|||||||
void on_javaDetectBtn_clicked();
|
void on_javaDetectBtn_clicked();
|
||||||
void on_javaTestBtn_clicked();
|
void on_javaTestBtn_clicked();
|
||||||
void on_javaBrowseBtn_clicked();
|
void on_javaBrowseBtn_clicked();
|
||||||
|
void on_downloadJavaButton_clicked();
|
||||||
|
void on_removeJavaButton_clicked();
|
||||||
|
void on_refreshJavaButton_clicked();
|
||||||
void on_maxMemSpinBox_valueChanged(int i);
|
void on_maxMemSpinBox_valueChanged(int i);
|
||||||
void checkerFinished();
|
void checkerFinished();
|
||||||
|
|
||||||
|
@ -6,8 +6,8 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>545</width>
|
<width>559</width>
|
||||||
<height>580</height>
|
<height>659</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
@ -34,9 +34,9 @@
|
|||||||
<property name="currentIndex">
|
<property name="currentIndex">
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QWidget" name="tab">
|
<widget class="QWidget" name="general">
|
||||||
<attribute name="title">
|
<attribute name="title">
|
||||||
<string notr="true">Tab 1</string>
|
<string notr="true">General</string>
|
||||||
</attribute>
|
</attribute>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||||
<item>
|
<item>
|
||||||
@ -160,25 +160,6 @@
|
|||||||
<string>Java Runtime</string>
|
<string>Java Runtime</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" name="gridLayout_3">
|
<layout class="QGridLayout" name="gridLayout_3">
|
||||||
<item row="7" column="0" colspan="3">
|
|
||||||
<widget class="QPlainTextEdit" name="jvmArgsTextBox">
|
|
||||||
<property name="enabled">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="maximumSize">
|
|
||||||
<size>
|
|
||||||
<width>16777215</width>
|
|
||||||
<height>100</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="4" column="0">
|
<item row="4" column="0">
|
||||||
<widget class="QCheckBox" name="skipCompatibilityCheckbox">
|
<widget class="QCheckBox" name="skipCompatibilityCheckbox">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
@ -225,7 +206,7 @@
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item row="6" column="0">
|
<item row="8" column="0">
|
||||||
<widget class="QLabel" name="labelJVMArgs">
|
<widget class="QLabel" name="labelJVMArgs">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||||
@ -241,6 +222,45 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="5" column="0">
|
||||||
|
<widget class="QCheckBox" name="skipJavaWizardCheckbox">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>If enabled, the launcher will not prompt you to choose a Java version if one isn't found.</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Skip Java &Wizard</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="9" column="0" colspan="3">
|
||||||
|
<widget class="QPlainTextEdit" name="jvmArgsTextBox">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>16777215</width>
|
||||||
|
<height>100</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="6" column="0">
|
||||||
|
<widget class="QCheckBox" name="autodetectJavaCheckBox">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Automatically selects the Java version that is compatible with the current Minecraft instance, based on the major version required.</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Autodetect Java version</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item row="1" column="0" colspan="3">
|
<item row="1" column="0" colspan="3">
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
<item>
|
<item>
|
||||||
@ -277,13 +297,16 @@
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item row="5" column="0">
|
<item row="7" column="0">
|
||||||
<widget class="QCheckBox" name="skipJavaWizardCheckbox">
|
<widget class="QCheckBox" name="autodownloadCheckBox">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>If enabled, the launcher will not prompt you to choose a Java version if one isn't found.</string>
|
<string>Automatically downloads and selects the Java version recommended by Mojang.</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Skip Java &Wizard</string>
|
<string>Auto-download Mojang Java</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -305,16 +328,106 @@
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
|
<widget class="QWidget" name="management">
|
||||||
|
<attribute name="title">
|
||||||
|
<string>Management</string>
|
||||||
|
</attribute>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="groupBox">
|
||||||
|
<property name="title">
|
||||||
|
<string>Downloaded Java Versions</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||||
|
<item>
|
||||||
|
<widget class="VersionSelectWidget" name="managedJavaList" native="true">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QVBoxLayout" name="managedJavaBtnLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="downloadJavaButton">
|
||||||
|
<property name="text">
|
||||||
|
<string>Download</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="removeJavaButton">
|
||||||
|
<property name="text">
|
||||||
|
<string>Remove</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="verticalSpacer_2">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>40</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="refreshJavaButton">
|
||||||
|
<property name="text">
|
||||||
|
<string>Refresh</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="managementSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>40</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
|
<customwidgets>
|
||||||
|
<customwidget>
|
||||||
|
<class>VersionSelectWidget</class>
|
||||||
|
<extends>QWidget</extends>
|
||||||
|
<header>ui/widgets/VersionSelectWidget.h</header>
|
||||||
|
<container>1</container>
|
||||||
|
</customwidget>
|
||||||
|
</customwidgets>
|
||||||
<tabstops>
|
<tabstops>
|
||||||
<tabstop>minMemSpinBox</tabstop>
|
<tabstop>minMemSpinBox</tabstop>
|
||||||
<tabstop>maxMemSpinBox</tabstop>
|
<tabstop>maxMemSpinBox</tabstop>
|
||||||
<tabstop>permGenSpinBox</tabstop>
|
<tabstop>permGenSpinBox</tabstop>
|
||||||
<tabstop>javaBrowseBtn</tabstop>
|
|
||||||
<tabstop>javaPathTextBox</tabstop>
|
<tabstop>javaPathTextBox</tabstop>
|
||||||
|
<tabstop>javaBrowseBtn</tabstop>
|
||||||
|
<tabstop>javaDetectBtn</tabstop>
|
||||||
|
<tabstop>javaTestBtn</tabstop>
|
||||||
|
<tabstop>skipCompatibilityCheckbox</tabstop>
|
||||||
|
<tabstop>skipJavaWizardCheckbox</tabstop>
|
||||||
|
<tabstop>jvmArgsTextBox</tabstop>
|
||||||
<tabstop>tabWidget</tabstop>
|
<tabstop>tabWidget</tabstop>
|
||||||
</tabstops>
|
</tabstops>
|
||||||
<resources/>
|
<resources/>
|
||||||
|
@ -173,6 +173,16 @@ void LauncherPage::on_downloadsDirBrowseBtn_clicked()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LauncherPage::on_javaDirBrowseBtn_clicked()
|
||||||
|
{
|
||||||
|
QString raw_dir = QFileDialog::getExistingDirectory(this, tr("Java Folder"), ui->javaDirTextBox->text());
|
||||||
|
|
||||||
|
if (!raw_dir.isEmpty() && QDir(raw_dir).exists()) {
|
||||||
|
QString cooked_dir = FS::NormalizePath(raw_dir);
|
||||||
|
ui->javaDirTextBox->setText(cooked_dir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void LauncherPage::on_skinsDirBrowseBtn_clicked()
|
void LauncherPage::on_skinsDirBrowseBtn_clicked()
|
||||||
{
|
{
|
||||||
QString raw_dir = QFileDialog::getExistingDirectory(this, tr("Skins Folder"), ui->skinsDirTextBox->text());
|
QString raw_dir = QFileDialog::getExistingDirectory(this, tr("Skins Folder"), ui->skinsDirTextBox->text());
|
||||||
@ -223,6 +233,7 @@ void LauncherPage::applySettings()
|
|||||||
s->set("IconsDir", ui->iconsDirTextBox->text());
|
s->set("IconsDir", ui->iconsDirTextBox->text());
|
||||||
s->set("DownloadsDir", ui->downloadsDirTextBox->text());
|
s->set("DownloadsDir", ui->downloadsDirTextBox->text());
|
||||||
s->set("SkinsDir", ui->skinsDirTextBox->text());
|
s->set("SkinsDir", ui->skinsDirTextBox->text());
|
||||||
|
s->set("JavaDir", ui->javaDirTextBox->text());
|
||||||
s->set("DownloadsDirWatchRecursive", ui->downloadsDirWatchRecursiveCheckBox->isChecked());
|
s->set("DownloadsDirWatchRecursive", ui->downloadsDirWatchRecursiveCheckBox->isChecked());
|
||||||
|
|
||||||
auto sortMode = (InstSortMode)ui->sortingModeGroup->checkedId();
|
auto sortMode = (InstSortMode)ui->sortingModeGroup->checkedId();
|
||||||
@ -289,6 +300,7 @@ void LauncherPage::loadSettings()
|
|||||||
ui->iconsDirTextBox->setText(s->get("IconsDir").toString());
|
ui->iconsDirTextBox->setText(s->get("IconsDir").toString());
|
||||||
ui->downloadsDirTextBox->setText(s->get("DownloadsDir").toString());
|
ui->downloadsDirTextBox->setText(s->get("DownloadsDir").toString());
|
||||||
ui->skinsDirTextBox->setText(s->get("SkinsDir").toString());
|
ui->skinsDirTextBox->setText(s->get("SkinsDir").toString());
|
||||||
|
ui->javaDirTextBox->setText(s->get("JavaDir").toString());
|
||||||
ui->downloadsDirWatchRecursiveCheckBox->setChecked(s->get("DownloadsDirWatchRecursive").toBool());
|
ui->downloadsDirWatchRecursiveCheckBox->setChecked(s->get("DownloadsDirWatchRecursive").toBool());
|
||||||
|
|
||||||
QString sortMode = s->get("InstSortMode").toString();
|
QString sortMode = s->get("InstSortMode").toString();
|
||||||
|
@ -73,6 +73,7 @@ class LauncherPage : public QWidget, public BasePage {
|
|||||||
void on_modsDirBrowseBtn_clicked();
|
void on_modsDirBrowseBtn_clicked();
|
||||||
void on_iconsDirBrowseBtn_clicked();
|
void on_iconsDirBrowseBtn_clicked();
|
||||||
void on_downloadsDirBrowseBtn_clicked();
|
void on_downloadsDirBrowseBtn_clicked();
|
||||||
|
void on_javaDirBrowseBtn_clicked();
|
||||||
void on_skinsDirBrowseBtn_clicked();
|
void on_skinsDirBrowseBtn_clicked();
|
||||||
void on_metadataDisableBtn_clicked();
|
void on_metadataDisableBtn_clicked();
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>511</width>
|
<width>511</width>
|
||||||
<height>691</height>
|
<height>726</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
@ -94,7 +94,7 @@
|
|||||||
<string>Folders</string>
|
<string>Folders</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" name="foldersBoxLayout">
|
<layout class="QGridLayout" name="foldersBoxLayout">
|
||||||
<item row="4" column="0">
|
<item row="8" column="0">
|
||||||
<widget class="QLabel" name="labelDownloadsDir">
|
<widget class="QLabel" name="labelDownloadsDir">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>&Downloads:</string>
|
<string>&Downloads:</string>
|
||||||
@ -104,42 +104,59 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="0">
|
<item row="8" column="2">
|
||||||
<widget class="QLabel" name="labelInstDir">
|
|
||||||
<property name="text">
|
|
||||||
<string>I&nstances:</string>
|
|
||||||
</property>
|
|
||||||
<property name="buddy">
|
|
||||||
<cstring>instDirTextBox</cstring>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="1">
|
|
||||||
<widget class="QLineEdit" name="instDirTextBox"/>
|
|
||||||
</item>
|
|
||||||
<item row="4" column="1">
|
|
||||||
<widget class="QLineEdit" name="downloadsDirTextBox"/>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="1">
|
|
||||||
<widget class="QLineEdit" name="iconsDirTextBox"/>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="1">
|
|
||||||
<widget class="QLineEdit" name="skinsDirTextBox"/>
|
|
||||||
</item>
|
|
||||||
<item row="4" column="2">
|
|
||||||
<widget class="QToolButton" name="downloadsDirBrowseBtn">
|
<widget class="QToolButton" name="downloadsDirBrowseBtn">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Browse</string>
|
<string>Browse</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="1">
|
<item row="2" column="1">
|
||||||
<widget class="QLineEdit" name="modsDirTextBox"/>
|
<widget class="QLineEdit" name="iconsDirTextBox"/>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="2">
|
<item row="3" column="1">
|
||||||
<widget class="QToolButton" name="modsDirBrowseBtn">
|
<widget class="QLineEdit" name="javaDirTextBox"/>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="0">
|
||||||
|
<widget class="QLabel" name="labelSkinsDir">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Browse</string>
|
<string>&Skins:</string>
|
||||||
|
</property>
|
||||||
|
<property name="buddy">
|
||||||
|
<cstring>skinsDirTextBox</cstring>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0">
|
||||||
|
<widget class="QLabel" name="labelIconsDir">
|
||||||
|
<property name="text">
|
||||||
|
<string>&Icons:</string>
|
||||||
|
</property>
|
||||||
|
<property name="buddy">
|
||||||
|
<cstring>iconsDirTextBox</cstring>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="9" column="1" colspan="2">
|
||||||
|
<widget class="QCheckBox" name="downloadsDirWatchRecursiveCheckBox">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>When enabled, in addition to the downloads folder, its sub folders will also be searched when looking for resources (e.g. when looking for blocked mods on CurseForge).</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Check downloads folder recursively</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="8" column="1">
|
||||||
|
<widget class="QLineEdit" name="downloadsDirTextBox"/>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="0">
|
||||||
|
<widget class="QLabel" name="labelJavaDir">
|
||||||
|
<property name="text">
|
||||||
|
<string>&Java:</string>
|
||||||
|
</property>
|
||||||
|
<property name="buddy">
|
||||||
|
<cstring>javaDirTextBox</cstring>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -153,6 +170,22 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="4" column="1">
|
||||||
|
<widget class="QLineEdit" name="skinsDirTextBox"/>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="QLineEdit" name="modsDirTextBox"/>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QLineEdit" name="instDirTextBox"/>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="2">
|
||||||
|
<widget class="QToolButton" name="modsDirBrowseBtn">
|
||||||
|
<property name="text">
|
||||||
|
<string>Browse</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item row="0" column="2">
|
<item row="0" column="2">
|
||||||
<widget class="QToolButton" name="instDirBrowseBtn">
|
<widget class="QToolButton" name="instDirBrowseBtn">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
@ -167,40 +200,27 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="0">
|
<item row="0" column="0">
|
||||||
<widget class="QLabel" name="labelIconsDir">
|
<widget class="QLabel" name="labelInstDir">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>&Icons:</string>
|
<string>I&nstances:</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="buddy">
|
<property name="buddy">
|
||||||
<cstring>iconsDirTextBox</cstring>
|
<cstring>instDirTextBox</cstring>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="2">
|
<item row="3" column="2">
|
||||||
<widget class="QToolButton" name="skinsDirBrowseBtn">
|
<widget class="QToolButton" name="javaDirBrowseBtn">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Browse</string>
|
<string>Browse</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="0">
|
<item row="4" column="2">
|
||||||
<widget class="QLabel" name="labelSkinsDir">
|
<widget class="QToolButton" name="skinsDirBrowseBtn">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>&Skins:</string>
|
<string>Browse</string>
|
||||||
</property>
|
|
||||||
<property name="buddy">
|
|
||||||
<cstring>skinsDirTextBox</cstring>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="5" column="1" colspan="2">
|
|
||||||
<widget class="QCheckBox" name="downloadsDirWatchRecursiveCheckBox">
|
|
||||||
<property name="toolTip">
|
|
||||||
<string>When enabled, in addition to the downloads folder, its sub folders will also be searched when looking for resources (e.g. when looking for blocked mods on CurseForge).</string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Check downloads folder recursively</string>
|
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
@ -38,6 +38,9 @@
|
|||||||
#include "InstanceSettingsPage.h"
|
#include "InstanceSettingsPage.h"
|
||||||
#include "minecraft/MinecraftInstance.h"
|
#include "minecraft/MinecraftInstance.h"
|
||||||
#include "minecraft/WorldList.h"
|
#include "minecraft/WorldList.h"
|
||||||
|
#include "settings/Setting.h"
|
||||||
|
#include "ui/dialogs/CustomMessageBox.h"
|
||||||
|
#include "ui/java/InstallJavaDialog.h"
|
||||||
#include "ui_InstanceSettingsPage.h"
|
#include "ui_InstanceSettingsPage.h"
|
||||||
|
|
||||||
#include <QDialog>
|
#include <QDialog>
|
||||||
@ -64,6 +67,8 @@ InstanceSettingsPage::InstanceSettingsPage(BaseInstance* inst, QWidget* parent)
|
|||||||
m_settings = inst->settings();
|
m_settings = inst->settings();
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
|
||||||
|
ui->javaDownloadBtn->setHidden(!BuildConfig.JAVA_DOWNLOADER_ENABLED);
|
||||||
|
|
||||||
connect(ui->openGlobalJavaSettingsButton, &QCommandLinkButton::clicked, this, &InstanceSettingsPage::globalSettingsButtonClicked);
|
connect(ui->openGlobalJavaSettingsButton, &QCommandLinkButton::clicked, this, &InstanceSettingsPage::globalSettingsButtonClicked);
|
||||||
connect(APPLICATION, &Application::globalSettingsAboutToOpen, this, &InstanceSettingsPage::applySettings);
|
connect(APPLICATION, &Application::globalSettingsAboutToOpen, this, &InstanceSettingsPage::applySettings);
|
||||||
connect(APPLICATION, &Application::globalSettingsClosed, this, &InstanceSettingsPage::loadSettings);
|
connect(APPLICATION, &Application::globalSettingsClosed, this, &InstanceSettingsPage::loadSettings);
|
||||||
@ -204,9 +209,6 @@ void InstanceSettingsPage::applySettings()
|
|||||||
m_settings->reset("JvmArgs");
|
m_settings->reset("JvmArgs");
|
||||||
}
|
}
|
||||||
|
|
||||||
// old generic 'override both' is removed.
|
|
||||||
m_settings->reset("OverrideJava");
|
|
||||||
|
|
||||||
// Custom Commands
|
// Custom Commands
|
||||||
bool custcmd = ui->customCommands->checked();
|
bool custcmd = ui->customCommands->checked();
|
||||||
m_settings->set("OverrideCommands", custcmd);
|
m_settings->set("OverrideCommands", custcmd);
|
||||||
@ -342,10 +344,11 @@ void InstanceSettingsPage::loadSettings()
|
|||||||
ui->labelPermgenNote->setVisible(permGenVisible);
|
ui->labelPermgenNote->setVisible(permGenVisible);
|
||||||
|
|
||||||
// Java Settings
|
// Java Settings
|
||||||
bool overrideJava = m_settings->get("OverrideJava").toBool();
|
bool overrideLocation = m_settings->get("OverrideJavaLocation").toBool();
|
||||||
bool overrideLocation = m_settings->get("OverrideJavaLocation").toBool() || overrideJava;
|
bool overrideArgs = m_settings->get("OverrideJavaArgs").toBool();
|
||||||
bool overrideArgs = m_settings->get("OverrideJavaArgs").toBool() || overrideJava;
|
|
||||||
|
|
||||||
|
connect(m_settings->getSetting("OverrideJavaLocation").get(), &Setting::SettingChanged, ui->javaSettingsGroupBox,
|
||||||
|
[this] { ui->javaSettingsGroupBox->setChecked(m_settings->get("OverrideJavaLocation").toBool()); });
|
||||||
ui->javaSettingsGroupBox->setChecked(overrideLocation);
|
ui->javaSettingsGroupBox->setChecked(overrideLocation);
|
||||||
ui->javaPathTextBox->setText(m_settings->get("JavaPath").toString());
|
ui->javaPathTextBox->setText(m_settings->get("JavaPath").toString());
|
||||||
ui->skipCompatibilityCheckbox->setChecked(m_settings->get("IgnoreJavaCompatibility").toBool());
|
ui->skipCompatibilityCheckbox->setChecked(m_settings->get("IgnoreJavaCompatibility").toBool());
|
||||||
@ -431,6 +434,12 @@ void InstanceSettingsPage::loadSettings()
|
|||||||
ui->onlineFixes->setChecked(m_settings->get("OnlineFixes").toBool());
|
ui->onlineFixes->setChecked(m_settings->get("OnlineFixes").toBool());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void InstanceSettingsPage::on_javaDownloadBtn_clicked()
|
||||||
|
{
|
||||||
|
auto jdialog = new Java::InstallDialog({}, m_instance, this);
|
||||||
|
jdialog->exec();
|
||||||
|
}
|
||||||
|
|
||||||
void InstanceSettingsPage::on_javaDetectBtn_clicked()
|
void InstanceSettingsPage::on_javaDetectBtn_clicked()
|
||||||
{
|
{
|
||||||
if (JavaUtils::getJavaCheckPath().isEmpty()) {
|
if (JavaUtils::getJavaCheckPath().isEmpty()) {
|
||||||
@ -452,6 +461,15 @@ void InstanceSettingsPage::on_javaDetectBtn_clicked()
|
|||||||
ui->labelPermGen->setVisible(visible);
|
ui->labelPermGen->setVisible(visible);
|
||||||
ui->labelPermgenNote->setVisible(visible);
|
ui->labelPermgenNote->setVisible(visible);
|
||||||
m_settings->set("PermGenVisible", visible);
|
m_settings->set("PermGenVisible", visible);
|
||||||
|
|
||||||
|
if (!java->is_64bit && m_settings->get("MaxMemAlloc").toInt() > 2048) {
|
||||||
|
CustomMessageBox::selectable(this, tr("Confirm Selection"),
|
||||||
|
tr("You selected a 32-bit version of Java.\n"
|
||||||
|
"This installation does not support more than 2048MiB of RAM.\n"
|
||||||
|
"Please make sure that the maximum memory value is lower."),
|
||||||
|
QMessageBox::Warning, QMessageBox::Ok, QMessageBox::Ok)
|
||||||
|
->exec();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,6 +69,7 @@ class InstanceSettingsPage : public QWidget, public BasePage {
|
|||||||
void on_javaDetectBtn_clicked();
|
void on_javaDetectBtn_clicked();
|
||||||
void on_javaTestBtn_clicked();
|
void on_javaTestBtn_clicked();
|
||||||
void on_javaBrowseBtn_clicked();
|
void on_javaBrowseBtn_clicked();
|
||||||
|
void on_javaDownloadBtn_clicked();
|
||||||
void on_maxMemSpinBox_valueChanged(int i);
|
void on_maxMemSpinBox_valueChanged(int i);
|
||||||
void on_serverJoinAddressButton_toggled(bool checked);
|
void on_serverJoinAddressButton_toggled(bool checked);
|
||||||
void on_worldJoinButton_toggled(bool checked);
|
void on_worldJoinButton_toggled(bool checked);
|
||||||
|
@ -84,6 +84,13 @@
|
|||||||
</item>
|
</item>
|
||||||
<item row="2" column="0">
|
<item row="2" column="0">
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="javaDownloadBtn">
|
||||||
|
<property name="text">
|
||||||
|
<string>Download Java</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QPushButton" name="javaDetectBtn">
|
<widget class="QPushButton" name="javaDetectBtn">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
@ -764,6 +771,12 @@
|
|||||||
<tabstop>openGlobalJavaSettingsButton</tabstop>
|
<tabstop>openGlobalJavaSettingsButton</tabstop>
|
||||||
<tabstop>settingsTabs</tabstop>
|
<tabstop>settingsTabs</tabstop>
|
||||||
<tabstop>javaSettingsGroupBox</tabstop>
|
<tabstop>javaSettingsGroupBox</tabstop>
|
||||||
|
<tabstop>javaPathTextBox</tabstop>
|
||||||
|
<tabstop>javaBrowseBtn</tabstop>
|
||||||
|
<tabstop>javaDownloadBtn</tabstop>
|
||||||
|
<tabstop>javaDetectBtn</tabstop>
|
||||||
|
<tabstop>javaTestBtn</tabstop>
|
||||||
|
<tabstop>skipCompatibilityCheckbox</tabstop>
|
||||||
<tabstop>memoryGroupBox</tabstop>
|
<tabstop>memoryGroupBox</tabstop>
|
||||||
<tabstop>minMemSpinBox</tabstop>
|
<tabstop>minMemSpinBox</tabstop>
|
||||||
<tabstop>maxMemSpinBox</tabstop>
|
<tabstop>maxMemSpinBox</tabstop>
|
||||||
@ -783,6 +796,18 @@
|
|||||||
<tabstop>useNativeOpenALCheck</tabstop>
|
<tabstop>useNativeOpenALCheck</tabstop>
|
||||||
<tabstop>showGameTime</tabstop>
|
<tabstop>showGameTime</tabstop>
|
||||||
<tabstop>recordGameTime</tabstop>
|
<tabstop>recordGameTime</tabstop>
|
||||||
|
<tabstop>miscellaneousSettingsBox</tabstop>
|
||||||
|
<tabstop>closeAfterLaunchCheck</tabstop>
|
||||||
|
<tabstop>quitAfterGameStopCheck</tabstop>
|
||||||
|
<tabstop>perfomanceGroupBox</tabstop>
|
||||||
|
<tabstop>enableFeralGamemodeCheck</tabstop>
|
||||||
|
<tabstop>enableMangoHud</tabstop>
|
||||||
|
<tabstop>useDiscreteGpuCheck</tabstop>
|
||||||
|
<tabstop>gameTimeGroupBox</tabstop>
|
||||||
|
<tabstop>serverJoinGroupBox</tabstop>
|
||||||
|
<tabstop>serverJoinAddress</tabstop>
|
||||||
|
<tabstop>instanceAccountGroupBox</tabstop>
|
||||||
|
<tabstop>instanceAccountSelector</tabstop>
|
||||||
</tabstops>
|
</tabstops>
|
||||||
<resources/>
|
<resources/>
|
||||||
<connections/>
|
<connections/>
|
||||||
|
@ -393,6 +393,11 @@ void VersionPage::on_actionChange_version_triggered()
|
|||||||
bool important = false;
|
bool important = false;
|
||||||
if (uid == "net.minecraft") {
|
if (uid == "net.minecraft") {
|
||||||
important = true;
|
important = true;
|
||||||
|
if (APPLICATION->settings()->get("AutomaticJavaSwitch").toBool() && m_inst->settings()->get("AutomaticJava").toBool() &&
|
||||||
|
m_inst->settings()->get("OverrideJavaLocation").toBool()) {
|
||||||
|
m_inst->settings()->set("OverrideJavaLocation", false);
|
||||||
|
m_inst->settings()->set("JavaPath", "");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
m_profile->setComponentVersion(uid, vselect.selectedVersion()->descriptor(), important);
|
m_profile->setComponentVersion(uid, vselect.selectedVersion()->descriptor(), important);
|
||||||
m_profile->resolve(Net::Mode::Online);
|
m_profile->resolve(Net::Mode::Online);
|
||||||
|
@ -12,12 +12,8 @@
|
|||||||
|
|
||||||
#include <sys.h>
|
#include <sys.h>
|
||||||
|
|
||||||
#include "FileSystem.h"
|
|
||||||
#include "JavaCommon.h"
|
#include "JavaCommon.h"
|
||||||
#include "java/JavaInstall.h"
|
|
||||||
#include "java/JavaUtils.h"
|
|
||||||
|
|
||||||
#include "ui/dialogs/CustomMessageBox.h"
|
|
||||||
#include "ui/widgets/JavaSettingsWidget.h"
|
#include "ui/widgets/JavaSettingsWidget.h"
|
||||||
#include "ui/widgets/VersionSelectWidget.h"
|
#include "ui/widgets/VersionSelectWidget.h"
|
||||||
|
|
||||||
@ -57,6 +53,8 @@ bool JavaWizardPage::validatePage()
|
|||||||
{
|
{
|
||||||
auto settings = APPLICATION->settings();
|
auto settings = APPLICATION->settings();
|
||||||
auto result = m_java_widget->validate();
|
auto result = m_java_widget->validate();
|
||||||
|
settings->set("AutomaticJavaSwitch", m_java_widget->autoDetectJava());
|
||||||
|
settings->set("AutomaticJavaDownload", m_java_widget->autoDownloadJava());
|
||||||
switch (result) {
|
switch (result) {
|
||||||
default:
|
default:
|
||||||
case JavaSettingsWidget::ValidationStatus::Bad: {
|
case JavaSettingsWidget::ValidationStatus::Bad: {
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include <QGroupBox>
|
#include <QGroupBox>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QLineEdit>
|
#include <QLineEdit>
|
||||||
|
#include <QMessageBox>
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
#include <QSpinBox>
|
#include <QSpinBox>
|
||||||
#include <QToolButton>
|
#include <QToolButton>
|
||||||
@ -11,12 +12,16 @@
|
|||||||
|
|
||||||
#include <sys.h>
|
#include <sys.h>
|
||||||
|
|
||||||
|
#include "DesktopServices.h"
|
||||||
#include "FileSystem.h"
|
#include "FileSystem.h"
|
||||||
#include "JavaCommon.h"
|
#include "JavaCommon.h"
|
||||||
|
#include "java/JavaChecker.h"
|
||||||
#include "java/JavaInstall.h"
|
#include "java/JavaInstall.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/InstallJavaDialog.h"
|
||||||
#include "ui/widgets/VersionSelectWidget.h"
|
#include "ui/widgets/VersionSelectWidget.h"
|
||||||
|
|
||||||
#include "Application.h"
|
#include "Application.h"
|
||||||
@ -38,6 +43,9 @@ JavaSettingsWidget::JavaSettingsWidget(QWidget* parent) : QWidget(parent)
|
|||||||
connect(m_javaBrowseBtn, &QPushButton::clicked, this, &JavaSettingsWidget::on_javaBrowseBtn_clicked);
|
connect(m_javaBrowseBtn, &QPushButton::clicked, this, &JavaSettingsWidget::on_javaBrowseBtn_clicked);
|
||||||
connect(m_javaPathTextBox, &QLineEdit::textEdited, this, &JavaSettingsWidget::javaPathEdited);
|
connect(m_javaPathTextBox, &QLineEdit::textEdited, this, &JavaSettingsWidget::javaPathEdited);
|
||||||
connect(m_javaStatusBtn, &QToolButton::clicked, this, &JavaSettingsWidget::on_javaStatusBtn_clicked);
|
connect(m_javaStatusBtn, &QToolButton::clicked, this, &JavaSettingsWidget::on_javaStatusBtn_clicked);
|
||||||
|
if (BuildConfig.JAVA_DOWNLOADER_ENABLED) {
|
||||||
|
connect(m_javaDownloadBtn, &QPushButton::clicked, this, &JavaSettingsWidget::javaDownloadBtn_clicked);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void JavaSettingsWidget::setupUi()
|
void JavaSettingsWidget::setupUi()
|
||||||
@ -120,6 +128,38 @@ void JavaSettingsWidget::setupUi()
|
|||||||
|
|
||||||
m_verticalLayout->addWidget(m_memoryGroupBox);
|
m_verticalLayout->addWidget(m_memoryGroupBox);
|
||||||
|
|
||||||
|
m_horizontalBtnLayout = new QHBoxLayout();
|
||||||
|
m_horizontalBtnLayout->setObjectName(QStringLiteral("horizontalBtnLayout"));
|
||||||
|
|
||||||
|
if (BuildConfig.JAVA_DOWNLOADER_ENABLED) {
|
||||||
|
m_javaDownloadBtn = new QPushButton(tr("Download Java"), this);
|
||||||
|
m_horizontalBtnLayout->addWidget(m_javaDownloadBtn);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_verticalLayout->addLayout(m_horizontalBtnLayout);
|
||||||
|
|
||||||
|
m_autoJavaGroupBox = new QGroupBox(this);
|
||||||
|
m_autoJavaGroupBox->setObjectName(QStringLiteral("autoJavaGroupBox"));
|
||||||
|
m_veriticalJavaLayout = new QVBoxLayout(m_autoJavaGroupBox);
|
||||||
|
m_veriticalJavaLayout->setObjectName(QStringLiteral("veriticalJavaLayout"));
|
||||||
|
|
||||||
|
m_autodetectJavaCheckBox = new QCheckBox(m_autoJavaGroupBox);
|
||||||
|
m_autodetectJavaCheckBox->setObjectName("autodetectJavaCheckBox");
|
||||||
|
m_veriticalJavaLayout->addWidget(m_autodetectJavaCheckBox);
|
||||||
|
|
||||||
|
if (BuildConfig.JAVA_DOWNLOADER_ENABLED) {
|
||||||
|
m_autodownloadCheckBox = new QCheckBox(m_autoJavaGroupBox);
|
||||||
|
m_autodownloadCheckBox->setObjectName("autodownloadCheckBox");
|
||||||
|
m_autodownloadCheckBox->setEnabled(false);
|
||||||
|
m_veriticalJavaLayout->addWidget(m_autodownloadCheckBox);
|
||||||
|
connect(m_autodetectJavaCheckBox, &QCheckBox::stateChanged, this, [this] {
|
||||||
|
m_autodownloadCheckBox->setEnabled(m_autodetectJavaCheckBox->isChecked());
|
||||||
|
if (!m_autodetectJavaCheckBox->isChecked())
|
||||||
|
m_autodownloadCheckBox->setChecked(false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
m_verticalLayout->addWidget(m_autoJavaGroupBox);
|
||||||
|
|
||||||
retranslate();
|
retranslate();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -137,6 +177,19 @@ void JavaSettingsWidget::initialize()
|
|||||||
m_maxMemSpinBox->setValue(observedMaxMemory);
|
m_maxMemSpinBox->setValue(observedMaxMemory);
|
||||||
m_permGenSpinBox->setValue(observedPermGenMemory);
|
m_permGenSpinBox->setValue(observedPermGenMemory);
|
||||||
updateThresholds();
|
updateThresholds();
|
||||||
|
|
||||||
|
if (BuildConfig.JAVA_DOWNLOADER_ENABLED) {
|
||||||
|
auto button =
|
||||||
|
CustomMessageBox::selectable(this, tr("Automatic Java Download"),
|
||||||
|
tr("%1 can automatically download the correct Java version for each version of Minecraft..\n"
|
||||||
|
"Do you want to enable Java auto-download?\n")
|
||||||
|
.arg(BuildConfig.LAUNCHER_DISPLAYNAME),
|
||||||
|
QMessageBox::Question, QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes)
|
||||||
|
->exec();
|
||||||
|
auto checked = button == QMessageBox::Yes;
|
||||||
|
m_autodetectJavaCheckBox->setChecked(checked);
|
||||||
|
m_autodownloadCheckBox->setChecked(checked);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void JavaSettingsWidget::refresh()
|
void JavaSettingsWidget::refresh()
|
||||||
@ -153,20 +206,52 @@ JavaSettingsWidget::ValidationStatus JavaSettingsWidget::validate()
|
|||||||
switch (javaStatus) {
|
switch (javaStatus) {
|
||||||
default:
|
default:
|
||||||
case JavaStatus::NotSet:
|
case JavaStatus::NotSet:
|
||||||
|
/* fallthrough */
|
||||||
case JavaStatus::DoesNotExist:
|
case JavaStatus::DoesNotExist:
|
||||||
|
/* fallthrough */
|
||||||
case JavaStatus::DoesNotStart:
|
case JavaStatus::DoesNotStart:
|
||||||
|
/* fallthrough */
|
||||||
case JavaStatus::ReturnedInvalidData: {
|
case JavaStatus::ReturnedInvalidData: {
|
||||||
int button = CustomMessageBox::selectable(this, tr("No Java version selected"),
|
if (!(BuildConfig.JAVA_DOWNLOADER_ENABLED && m_autodownloadCheckBox->isChecked())) { // the java will not be autodownloaded
|
||||||
tr("You didn't select a Java version or selected something that doesn't work.\n"
|
int button = QMessageBox::No;
|
||||||
"%1 will not be able to start Minecraft.\n"
|
if (m_result.mojangPlatform == "32" && maxHeapSize() > 2048) {
|
||||||
"Do you wish to proceed without any Java?"
|
button = CustomMessageBox::selectable(
|
||||||
"\n\n"
|
this, tr("32-bit Java detected"),
|
||||||
"You can change the Java version in the settings later.\n")
|
tr("You selected a 32-bit installation of Java, but allocated more than 2048MiB as maximum memory.\n"
|
||||||
.arg(BuildConfig.LAUNCHER_DISPLAYNAME),
|
"%1 will not be able to start Minecraft.\n"
|
||||||
QMessageBox::Warning, QMessageBox::Yes | QMessageBox::No, QMessageBox::NoButton)
|
"Do you wish to proceed?"
|
||||||
->exec();
|
"\n\n"
|
||||||
if (button == QMessageBox::No) {
|
"You can change the Java version in the settings later.\n")
|
||||||
return ValidationStatus::Bad;
|
.arg(BuildConfig.LAUNCHER_DISPLAYNAME),
|
||||||
|
QMessageBox::Warning, QMessageBox::Yes | QMessageBox::No | QMessageBox::Help, QMessageBox::NoButton)
|
||||||
|
->exec();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
button = CustomMessageBox::selectable(this, tr("No Java version selected"),
|
||||||
|
tr("You either didn't select a Java version or selected one that does not work.\n"
|
||||||
|
"%1 will not be able to start Minecraft.\n"
|
||||||
|
"Do you wish to proceed without a functional version of Java?"
|
||||||
|
"\n\n"
|
||||||
|
"You can change the Java version in the settings later.\n")
|
||||||
|
.arg(BuildConfig.LAUNCHER_DISPLAYNAME),
|
||||||
|
QMessageBox::Warning, QMessageBox::Yes | QMessageBox::No | QMessageBox::Help,
|
||||||
|
QMessageBox::NoButton)
|
||||||
|
->exec();
|
||||||
|
}
|
||||||
|
switch (button) {
|
||||||
|
case QMessageBox::Yes:
|
||||||
|
return ValidationStatus::JavaBad;
|
||||||
|
case QMessageBox::Help:
|
||||||
|
DesktopServices::openUrl(QUrl(BuildConfig.HELP_URL.arg("java-wizard")));
|
||||||
|
/* fallthrough */
|
||||||
|
case QMessageBox::No:
|
||||||
|
/* fallthrough */
|
||||||
|
default:
|
||||||
|
return ValidationStatus::Bad;
|
||||||
|
}
|
||||||
|
if (button == QMessageBox::No) {
|
||||||
|
return ValidationStatus::Bad;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return ValidationStatus::JavaBad;
|
return ValidationStatus::JavaBad;
|
||||||
} break;
|
} break;
|
||||||
@ -250,21 +335,22 @@ void JavaSettingsWidget::javaVersionSelected(BaseVersion::Ptr version)
|
|||||||
|
|
||||||
void JavaSettingsWidget::on_javaBrowseBtn_clicked()
|
void JavaSettingsWidget::on_javaBrowseBtn_clicked()
|
||||||
{
|
{
|
||||||
QString filter;
|
auto filter = QString("Java (%1)").arg(JavaUtils::javaExecutable);
|
||||||
#if defined Q_OS_WIN32
|
auto raw_path = QFileDialog::getOpenFileName(this, tr("Find Java executable"), QString(), filter);
|
||||||
filter = "Java (javaw.exe)";
|
|
||||||
#else
|
|
||||||
filter = "Java (java)";
|
|
||||||
#endif
|
|
||||||
QString raw_path = QFileDialog::getOpenFileName(this, tr("Find Java executable"), QString(), filter);
|
|
||||||
if (raw_path.isEmpty()) {
|
if (raw_path.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
QString cooked_path = FS::NormalizePath(raw_path);
|
auto cooked_path = FS::NormalizePath(raw_path);
|
||||||
m_javaPathTextBox->setText(cooked_path);
|
m_javaPathTextBox->setText(cooked_path);
|
||||||
checkJavaPath(cooked_path);
|
checkJavaPath(cooked_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void JavaSettingsWidget::javaDownloadBtn_clicked()
|
||||||
|
{
|
||||||
|
auto jdialog = new Java::InstallDialog({}, nullptr, this);
|
||||||
|
jdialog->exec();
|
||||||
|
}
|
||||||
|
|
||||||
void JavaSettingsWidget::on_javaStatusBtn_clicked()
|
void JavaSettingsWidget::on_javaStatusBtn_clicked()
|
||||||
{
|
{
|
||||||
QString text;
|
QString text;
|
||||||
@ -359,30 +445,25 @@ void JavaSettingsWidget::checkJavaPath(const QString& path)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setJavaStatus(JavaStatus::Pending);
|
setJavaStatus(JavaStatus::Pending);
|
||||||
m_checker.reset(new JavaChecker());
|
m_checker.reset(
|
||||||
m_checker->m_path = path;
|
new JavaChecker(path, "", minHeapSize(), maxHeapSize(), m_permGenSpinBox->isVisible() ? m_permGenSpinBox->value() : 0, 0, this));
|
||||||
m_checker->m_minMem = minHeapSize();
|
|
||||||
m_checker->m_maxMem = maxHeapSize();
|
|
||||||
if (m_permGenSpinBox->isVisible()) {
|
|
||||||
m_checker->m_permGen = m_permGenSpinBox->value();
|
|
||||||
}
|
|
||||||
connect(m_checker.get(), &JavaChecker::checkFinished, this, &JavaSettingsWidget::checkFinished);
|
connect(m_checker.get(), &JavaChecker::checkFinished, this, &JavaSettingsWidget::checkFinished);
|
||||||
m_checker->performCheck();
|
m_checker->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
void JavaSettingsWidget::checkFinished(JavaCheckResult result)
|
void JavaSettingsWidget::checkFinished(const JavaChecker::Result& result)
|
||||||
{
|
{
|
||||||
m_result = result;
|
m_result = result;
|
||||||
switch (result.validity) {
|
switch (result.validity) {
|
||||||
case JavaCheckResult::Validity::Valid: {
|
case JavaChecker::Result::Validity::Valid: {
|
||||||
setJavaStatus(JavaStatus::Good);
|
setJavaStatus(JavaStatus::Good);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case JavaCheckResult::Validity::ReturnedInvalidData: {
|
case JavaChecker::Result::Validity::ReturnedInvalidData: {
|
||||||
setJavaStatus(JavaStatus::ReturnedInvalidData);
|
setJavaStatus(JavaStatus::ReturnedInvalidData);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case JavaCheckResult::Validity::Errored: {
|
case JavaChecker::Result::Validity::Errored: {
|
||||||
setJavaStatus(JavaStatus::DoesNotStart);
|
setJavaStatus(JavaStatus::DoesNotStart);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -403,6 +484,11 @@ void JavaSettingsWidget::retranslate()
|
|||||||
m_minMemSpinBox->setToolTip(tr("The amount of memory Minecraft is started with."));
|
m_minMemSpinBox->setToolTip(tr("The amount of memory Minecraft is started with."));
|
||||||
m_permGenSpinBox->setToolTip(tr("The amount of memory available to store loaded Java classes."));
|
m_permGenSpinBox->setToolTip(tr("The amount of memory available to store loaded Java classes."));
|
||||||
m_javaBrowseBtn->setText(tr("Browse"));
|
m_javaBrowseBtn->setText(tr("Browse"));
|
||||||
|
if (BuildConfig.JAVA_DOWNLOADER_ENABLED) {
|
||||||
|
m_autodownloadCheckBox->setText(tr("Auto-download Mojang Java"));
|
||||||
|
}
|
||||||
|
m_autodetectJavaCheckBox->setText(tr("Autodetect Java version"));
|
||||||
|
m_autoJavaGroupBox->setTitle(tr("Autodetect Java"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void JavaSettingsWidget::updateThresholds()
|
void JavaSettingsWidget::updateThresholds()
|
||||||
@ -418,6 +504,9 @@ void JavaSettingsWidget::updateThresholds()
|
|||||||
} else if (observedMaxMemory < observedMinMemory) {
|
} else if (observedMaxMemory < observedMinMemory) {
|
||||||
iconName = "status-yellow";
|
iconName = "status-yellow";
|
||||||
m_labelMaxMemIcon->setToolTip(tr("Your maximum memory allocation is smaller than the minimum value"));
|
m_labelMaxMemIcon->setToolTip(tr("Your maximum memory allocation is smaller than the minimum value"));
|
||||||
|
} else if (observedMaxMemory > 2048 && m_result.is_64bit) {
|
||||||
|
iconName = "status-bad";
|
||||||
|
m_labelMaxMemIcon->setToolTip(tr("You are exceeding the maximum allocation supported by 32-bit installations of Java."));
|
||||||
} else {
|
} else {
|
||||||
iconName = "status-good";
|
iconName = "status-good";
|
||||||
m_labelMaxMemIcon->setToolTip("");
|
m_labelMaxMemIcon->setToolTip("");
|
||||||
@ -430,3 +519,13 @@ void JavaSettingsWidget::updateThresholds()
|
|||||||
m_labelMaxMemIcon->setPixmap(pix);
|
m_labelMaxMemIcon->setPixmap(pix);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool JavaSettingsWidget::autoDownloadJava() const
|
||||||
|
{
|
||||||
|
return m_autodownloadCheckBox && m_autodownloadCheckBox->isChecked();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool JavaSettingsWidget::autoDetectJava() const
|
||||||
|
{
|
||||||
|
return m_autodetectJavaCheckBox->isChecked();
|
||||||
|
}
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include <BaseVersion.h>
|
#include <BaseVersion.h>
|
||||||
#include <QObjectPtr.h>
|
#include <QObjectPtr.h>
|
||||||
#include <java/JavaChecker.h>
|
#include <java/JavaChecker.h>
|
||||||
|
#include <qcheckbox.h>
|
||||||
#include <QIcon>
|
#include <QIcon>
|
||||||
|
|
||||||
class QLineEdit;
|
class QLineEdit;
|
||||||
@ -25,7 +26,7 @@ class JavaSettingsWidget : public QWidget {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
explicit JavaSettingsWidget(QWidget* parent);
|
explicit JavaSettingsWidget(QWidget* parent);
|
||||||
virtual ~JavaSettingsWidget() {};
|
virtual ~JavaSettingsWidget() = default;
|
||||||
|
|
||||||
enum class JavaStatus { NotSet, Pending, Good, DoesNotExist, DoesNotStart, ReturnedInvalidData } javaStatus = JavaStatus::NotSet;
|
enum class JavaStatus { NotSet, Pending, Good, DoesNotExist, DoesNotStart, ReturnedInvalidData } javaStatus = JavaStatus::NotSet;
|
||||||
|
|
||||||
@ -41,6 +42,8 @@ class JavaSettingsWidget : public QWidget {
|
|||||||
int minHeapSize() const;
|
int minHeapSize() const;
|
||||||
int maxHeapSize() const;
|
int maxHeapSize() const;
|
||||||
QString javaPath() const;
|
QString javaPath() const;
|
||||||
|
bool autoDetectJava() const;
|
||||||
|
bool autoDownloadJava() const;
|
||||||
|
|
||||||
void updateThresholds();
|
void updateThresholds();
|
||||||
|
|
||||||
@ -50,7 +53,8 @@ class JavaSettingsWidget : public QWidget {
|
|||||||
void javaVersionSelected(BaseVersion::Ptr version);
|
void javaVersionSelected(BaseVersion::Ptr version);
|
||||||
void on_javaBrowseBtn_clicked();
|
void on_javaBrowseBtn_clicked();
|
||||||
void on_javaStatusBtn_clicked();
|
void on_javaStatusBtn_clicked();
|
||||||
void checkFinished(JavaCheckResult result);
|
void javaDownloadBtn_clicked();
|
||||||
|
void checkFinished(const JavaChecker::Result& result);
|
||||||
|
|
||||||
protected: /* methods */
|
protected: /* methods */
|
||||||
void checkJavaPathOnEdit(const QString& path);
|
void checkJavaPathOnEdit(const QString& path);
|
||||||
@ -76,15 +80,23 @@ class JavaSettingsWidget : public QWidget {
|
|||||||
QSpinBox* m_minMemSpinBox = nullptr;
|
QSpinBox* m_minMemSpinBox = nullptr;
|
||||||
QLabel* m_labelPermGen = nullptr;
|
QLabel* m_labelPermGen = nullptr;
|
||||||
QSpinBox* m_permGenSpinBox = nullptr;
|
QSpinBox* m_permGenSpinBox = nullptr;
|
||||||
|
|
||||||
|
QHBoxLayout* m_horizontalBtnLayout = nullptr;
|
||||||
|
QPushButton* m_javaDownloadBtn = nullptr;
|
||||||
QIcon goodIcon;
|
QIcon goodIcon;
|
||||||
QIcon yellowIcon;
|
QIcon yellowIcon;
|
||||||
QIcon badIcon;
|
QIcon badIcon;
|
||||||
|
|
||||||
|
QGroupBox* m_autoJavaGroupBox = nullptr;
|
||||||
|
QVBoxLayout* m_veriticalJavaLayout = nullptr;
|
||||||
|
QCheckBox* m_autodetectJavaCheckBox = nullptr;
|
||||||
|
QCheckBox* m_autodownloadCheckBox = nullptr;
|
||||||
|
|
||||||
unsigned int observedMinMemory = 0;
|
unsigned int observedMinMemory = 0;
|
||||||
unsigned int observedMaxMemory = 0;
|
unsigned int observedMaxMemory = 0;
|
||||||
unsigned int observedPermGenMemory = 0;
|
unsigned int observedPermGenMemory = 0;
|
||||||
QString queuedCheck;
|
QString queuedCheck;
|
||||||
uint64_t m_availableMemory = 0ull;
|
uint64_t m_availableMemory = 0ull;
|
||||||
shared_qobject_ptr<JavaChecker> m_checker;
|
shared_qobject_ptr<JavaChecker> m_checker;
|
||||||
JavaCheckResult m_result;
|
JavaChecker::Result m_result;
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user