Merge branch 'develop' into icon-indexing
Signed-off-by: Tayou <31988415+TayouVR@users.noreply.github.com>
This commit is contained in:
		| @@ -1,10 +1,12 @@ | |||||||
| --- | --- | ||||||
| Language:        Cpp |  | ||||||
| BasedOnStyle: Chromium | BasedOnStyle: Chromium | ||||||
| IndentWidth: 4 | IndentWidth: 4 | ||||||
| AlignConsecutiveMacros: false |  | ||||||
| AlignConsecutiveAssignments: false |  | ||||||
| AllowShortIfStatementsOnASingleLine: false | AllowShortIfStatementsOnASingleLine: false | ||||||
|  | ColumnLimit: 140 | ||||||
|  | --- | ||||||
|  | Language: Cpp | ||||||
|  | AlignConsecutiveMacros: None | ||||||
|  | AlignConsecutiveAssignments: None | ||||||
| BraceWrapping: | BraceWrapping: | ||||||
|   AfterFunction: true |   AfterFunction: true | ||||||
|   SplitEmptyFunction: false |   SplitEmptyFunction: false | ||||||
| @@ -12,5 +14,4 @@ BraceWrapping: | |||||||
|   SplitEmptyNamespace: false |   SplitEmptyNamespace: false | ||||||
| BreakBeforeBraces: Custom | BreakBeforeBraces: Custom | ||||||
| BreakConstructorInitializers: BeforeComma | BreakConstructorInitializers: BeforeComma | ||||||
| ColumnLimit:     140 |  | ||||||
| Cpp11BracedListStyle: false | Cpp11BracedListStyle: false | ||||||
|   | |||||||
							
								
								
									
										6
									
								
								.github/workflows/build.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								.github/workflows/build.yml
									
									
									
									
										vendored
									
									
								
							| @@ -68,7 +68,7 @@ jobs: | |||||||
|             qt_ver: 6 |             qt_ver: 6 | ||||||
|             qt_host: windows |             qt_host: windows | ||||||
|             qt_arch: '' |             qt_arch: '' | ||||||
|             qt_version: '6.5.1' |             qt_version: '6.5.2' | ||||||
|             qt_modules: 'qt5compat qtimageformats' |             qt_modules: 'qt5compat qtimageformats' | ||||||
|             qt_tools: '' |             qt_tools: '' | ||||||
|  |  | ||||||
| @@ -80,7 +80,7 @@ jobs: | |||||||
|             qt_ver: 6 |             qt_ver: 6 | ||||||
|             qt_host: windows |             qt_host: windows | ||||||
|             qt_arch: 'win64_msvc2019_arm64' |             qt_arch: 'win64_msvc2019_arm64' | ||||||
|             qt_version: '6.5.1' |             qt_version: '6.5.2' | ||||||
|             qt_modules: 'qt5compat qtimageformats' |             qt_modules: 'qt5compat qtimageformats' | ||||||
|             qt_tools: '' |             qt_tools: '' | ||||||
|  |  | ||||||
| @@ -90,7 +90,7 @@ jobs: | |||||||
|             qt_ver: 6 |             qt_ver: 6 | ||||||
|             qt_host: mac |             qt_host: mac | ||||||
|             qt_arch: '' |             qt_arch: '' | ||||||
|             qt_version: '6.5.0' |             qt_version: '6.5.2' | ||||||
|             qt_modules: 'qt5compat qtimageformats' |             qt_modules: 'qt5compat qtimageformats' | ||||||
|             qt_tools: '' |             qt_tools: '' | ||||||
|  |  | ||||||
|   | |||||||
| @@ -318,6 +318,8 @@ add_subdirectory(program_info) | |||||||
|  |  | ||||||
| ####################################### Install layout ####################################### | ####################################### Install layout ####################################### | ||||||
|  |  | ||||||
|  | set(Launcher_ENABLE_UPDATER NO) | ||||||
|  |  | ||||||
| if(NOT (UNIX AND APPLE)) | if(NOT (UNIX AND APPLE)) | ||||||
|     # Install "portable.txt" if selected component is "portable" |     # Install "portable.txt" if selected component is "portable" | ||||||
|     install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/${Launcher_Portable_File}" DESTINATION "." COMPONENT portable EXCLUDE_FROM_ALL) |     install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/${Launcher_Portable_File}" DESTINATION "." COMPONENT portable EXCLUDE_FROM_ALL) | ||||||
| @@ -342,9 +344,9 @@ if(UNIX AND APPLE) | |||||||
|     set(MACOSX_BUNDLE_SHORT_VERSION_STRING "${Launcher_VERSION_NAME}") |     set(MACOSX_BUNDLE_SHORT_VERSION_STRING "${Launcher_VERSION_NAME}") | ||||||
|     set(MACOSX_BUNDLE_LONG_VERSION_STRING "${Launcher_VERSION_NAME}") |     set(MACOSX_BUNDLE_LONG_VERSION_STRING "${Launcher_VERSION_NAME}") | ||||||
|     set(MACOSX_BUNDLE_ICON_FILE ${Launcher_Name}.icns) |     set(MACOSX_BUNDLE_ICON_FILE ${Launcher_Name}.icns) | ||||||
|     set(MACOSX_BUNDLE_COPYRIGHT "© 2022 ${Launcher_Copyright_Mac}") |     set(MACOSX_BUNDLE_COPYRIGHT "© 2022-2023 ${Launcher_Copyright_Mac}") | ||||||
|     set(MACOSX_SPARKLE_UPDATE_PUBLIC_KEY "v55ZWWD6QlPoXGV6VLzOTZxZUggWeE51X8cRQyQh6vA=") |     set(MACOSX_SPARKLE_UPDATE_PUBLIC_KEY "v55ZWWD6QlPoXGV6VLzOTZxZUggWeE51X8cRQyQh6vA=" CACHE STRING "Public key for Sparkle update feed") | ||||||
|     set(MACOSX_SPARKLE_UPDATE_FEED_URL "https://prismlauncher.org/feed/appcast.xml") |     set(MACOSX_SPARKLE_UPDATE_FEED_URL "https://prismlauncher.org/feed/appcast.xml" CACHE STRING "URL for Sparkle update feed") | ||||||
|  |  | ||||||
|     set(MACOSX_SPARKLE_DOWNLOAD_URL "https://github.com/sparkle-project/Sparkle/releases/download/2.1.0/Sparkle-2.1.0.tar.xz" CACHE STRING "URL to Sparkle release archive") |     set(MACOSX_SPARKLE_DOWNLOAD_URL "https://github.com/sparkle-project/Sparkle/releases/download/2.1.0/Sparkle-2.1.0.tar.xz" CACHE STRING "URL to Sparkle release archive") | ||||||
|     set(MACOSX_SPARKLE_SHA256 "bf6ac1caa9f8d321d5784859c88da874f28412f37fb327bc21b7b14c5d61ef94" CACHE STRING "SHA256 checksum for Sparkle release archive") |     set(MACOSX_SPARKLE_SHA256 "bf6ac1caa9f8d321d5784859c88da874f28412f37fb327bc21b7b14c5d61ef94" CACHE STRING "SHA256 checksum for Sparkle release archive") | ||||||
| @@ -353,8 +355,12 @@ if(UNIX AND APPLE) | |||||||
|     # directories to look for dependencies |     # directories to look for dependencies | ||||||
|     set(DIRS ${QT_LIBS_DIR} ${QT_LIBEXECS_DIR} ${CMAKE_LIBRARY_OUTPUT_DIRECTORY} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${MACOSX_SPARKLE_DIR}) |     set(DIRS ${QT_LIBS_DIR} ${QT_LIBEXECS_DIR} ${CMAKE_LIBRARY_OUTPUT_DIRECTORY} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${MACOSX_SPARKLE_DIR}) | ||||||
|  |  | ||||||
|  |     if(NOT MACOSX_SPARKLE_UPDATE_PUBLIC_KEY STREQUAL "" AND NOT MACOSX_SPARKLE_UPDATE_FEED_URL STREQUAL "") | ||||||
|  |         set(Launcher_ENABLE_UPDATER YES) | ||||||
|  |     endif() | ||||||
|  |  | ||||||
|     # install as bundle |     # install as bundle | ||||||
|     set(INSTALL_BUNDLE "full") |     set(INSTALL_BUNDLE "full" CACHE STRING "Use fixup_bundle to bundle dependencies") | ||||||
|  |  | ||||||
|     # Add the icon |     # Add the icon | ||||||
|     install(FILES ${Launcher_Branding_ICNS} DESTINATION ${RESOURCES_DEST_DIR} RENAME ${Launcher_Name}.icns) |     install(FILES ${Launcher_Branding_ICNS} DESTINATION ${RESOURCES_DEST_DIR} RENAME ${Launcher_Name}.icns) | ||||||
| @@ -367,7 +373,7 @@ elseif(UNIX) | |||||||
|     set(JARS_DEST_DIR "share/${Launcher_Name}") |     set(JARS_DEST_DIR "share/${Launcher_Name}") | ||||||
|  |  | ||||||
|     # install as bundle with no dependencies included |     # install as bundle with no dependencies included | ||||||
|     set(INSTALL_BUNDLE "nodeps") |     set(INSTALL_BUNDLE "nodeps" CACHE STRING "Use fixup_bundle to bundle dependencies") | ||||||
|  |  | ||||||
|     # Set RPATH |     # Set RPATH | ||||||
|     SET(Launcher_BINARY_RPATH "$ORIGIN/") |     SET(Launcher_BINARY_RPATH "$ORIGIN/") | ||||||
| @@ -401,7 +407,7 @@ elseif(WIN32) | |||||||
|     set(DIRS ${QT_LIBS_DIR} ${QT_LIBEXECS_DIR} ${CMAKE_LIBRARY_OUTPUT_DIRECTORY} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) |     set(DIRS ${QT_LIBS_DIR} ${QT_LIBEXECS_DIR} ${CMAKE_LIBRARY_OUTPUT_DIRECTORY} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) | ||||||
|  |  | ||||||
|     # install as bundle |     # install as bundle | ||||||
|     set(INSTALL_BUNDLE "full") |     set(INSTALL_BUNDLE "full" CACHE STRING "Use fixup_bundle to bundle dependencies") | ||||||
| else() | else() | ||||||
|     message(FATAL_ERROR "Platform not supported") |     message(FATAL_ERROR "Platform not supported") | ||||||
| endif() | endif() | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| // SPDX-License-Identifier: GPL-3.0-only | // SPDX-License-Identifier: GPL-3.0-only | ||||||
| /* | /* | ||||||
|  *  PolyMC - Minecraft Launcher |  *  Prism Launcher - Minecraft Launcher | ||||||
|  *  Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net> |  *  Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net> | ||||||
|  * |  * | ||||||
|  *  This program is free software: you can redistribute it and/or modify |  *  This program is free software: you can redistribute it and/or modify | ||||||
|   | |||||||
| @@ -36,8 +36,8 @@ | |||||||
|  */ |  */ | ||||||
|  |  | ||||||
| #pragma once | #pragma once | ||||||
| #include <QString> |  | ||||||
| #include <QList> | #include <QList> | ||||||
|  | #include <QString> | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * \brief The Config class holds all the build-time information passed from the build system. |  * \brief The Config class holds all the build-time information passed from the build system. | ||||||
|   | |||||||
							
								
								
									
										24
									
								
								flake.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										24
									
								
								flake.lock
									
									
									
										generated
									
									
									
								
							| @@ -21,11 +21,11 @@ | |||||||
|         "nixpkgs-lib": "nixpkgs-lib" |         "nixpkgs-lib": "nixpkgs-lib" | ||||||
|       }, |       }, | ||||||
|       "locked": { |       "locked": { | ||||||
|         "lastModified": 1688466019, |         "lastModified": 1690933134, | ||||||
|         "narHash": "sha256-VeM2akYrBYMsb4W/MmBo1zmaMfgbL4cH3Pu8PGyIwJ0=", |         "narHash": "sha256-ab989mN63fQZBFrkk4Q8bYxQCktuHmBIBqUG1jl6/FQ=", | ||||||
|         "owner": "hercules-ci", |         "owner": "hercules-ci", | ||||||
|         "repo": "flake-parts", |         "repo": "flake-parts", | ||||||
|         "rev": "8e8d955c22df93dbe24f19ea04f47a74adbdc5ec", |         "rev": "59cf3f1447cfc75087e7273b04b31e689a8599fb", | ||||||
|         "type": "github" |         "type": "github" | ||||||
|       }, |       }, | ||||||
|       "original": { |       "original": { | ||||||
| @@ -91,11 +91,11 @@ | |||||||
|     }, |     }, | ||||||
|     "nixpkgs": { |     "nixpkgs": { | ||||||
|       "locked": { |       "locked": { | ||||||
|         "lastModified": 1690630721, |         "lastModified": 1691218994, | ||||||
|         "narHash": "sha256-Y04onHyBQT4Erfr2fc82dbJTfXGYrf4V0ysLUYnPOP8=", |         "narHash": "sha256-46GJ5vLf9H+Oh7Jii2gJI9GATJHGbx2iQpon5nUSFPI=", | ||||||
|         "owner": "nixos", |         "owner": "nixos", | ||||||
|         "repo": "nixpkgs", |         "repo": "nixpkgs", | ||||||
|         "rev": "d2b52322f35597c62abf56de91b0236746b2a03d", |         "rev": "0d2fb29f5071a12d7983319c2c2576be6a130582", | ||||||
|         "type": "github" |         "type": "github" | ||||||
|       }, |       }, | ||||||
|       "original": { |       "original": { | ||||||
| @@ -108,11 +108,11 @@ | |||||||
|     "nixpkgs-lib": { |     "nixpkgs-lib": { | ||||||
|       "locked": { |       "locked": { | ||||||
|         "dir": "lib", |         "dir": "lib", | ||||||
|         "lastModified": 1688049487, |         "lastModified": 1690881714, | ||||||
|         "narHash": "sha256-100g4iaKC9MalDjUW9iN6Jl/OocTDtXdeAj7pEGIRh4=", |         "narHash": "sha256-h/nXluEqdiQHs1oSgkOOWF+j8gcJMWhwnZ9PFabN6q0=", | ||||||
|         "owner": "NixOS", |         "owner": "NixOS", | ||||||
|         "repo": "nixpkgs", |         "repo": "nixpkgs", | ||||||
|         "rev": "4bc72cae107788bf3f24f30db2e2f685c9298dc9", |         "rev": "9e1960bc196baf6881340d53dccb203a951745a2", | ||||||
|         "type": "github" |         "type": "github" | ||||||
|       }, |       }, | ||||||
|       "original": { |       "original": { | ||||||
| @@ -138,11 +138,11 @@ | |||||||
|         ] |         ] | ||||||
|       }, |       }, | ||||||
|       "locked": { |       "locked": { | ||||||
|         "lastModified": 1690628027, |         "lastModified": 1691256628, | ||||||
|         "narHash": "sha256-OTSbA2hM6VmxyZ/4siYPANffMBzIsKu04GLjXcv8ST0=", |         "narHash": "sha256-M0YXHemR3zbyhM7PvJa5lzGhWVf6kM/fpZ4cWe/VIhI=", | ||||||
|         "owner": "cachix", |         "owner": "cachix", | ||||||
|         "repo": "pre-commit-hooks.nix", |         "repo": "pre-commit-hooks.nix", | ||||||
|         "rev": "1e2443dd3f669eb65433b2fc26a3065e05a7dc9c", |         "rev": "3139c4d1f7732cab89f06492bdd4677b877e3785", | ||||||
|         "type": "github" |         "type": "github" | ||||||
|       }, |       }, | ||||||
|       "original": { |       "original": { | ||||||
|   | |||||||
| @@ -18,6 +18,8 @@ finish-args: | |||||||
|   - --filesystem=xdg-run/app/com.discordapp.Discord:create |   - --filesystem=xdg-run/app/com.discordapp.Discord:create | ||||||
|     # Mod drag&drop |     # Mod drag&drop | ||||||
|   - --filesystem=xdg-download:ro |   - --filesystem=xdg-download:ro | ||||||
|  |     # FTBApp import | ||||||
|  |   - --filesystem=~/.ftba:ro | ||||||
|  |  | ||||||
| cleanup: | cleanup: | ||||||
|   - /lib/libGLU* |   - /lib/libGLU* | ||||||
|   | |||||||
| @@ -49,27 +49,27 @@ | |||||||
| #include "pathmatcher/MultiMatcher.h" | #include "pathmatcher/MultiMatcher.h" | ||||||
| #include "pathmatcher/SimplePrefixMatcher.h" | #include "pathmatcher/SimplePrefixMatcher.h" | ||||||
| #include "settings/INIFile.h" | #include "settings/INIFile.h" | ||||||
| #include "ui/MainWindow.h" |  | ||||||
| #include "ui/InstanceWindow.h" | #include "ui/InstanceWindow.h" | ||||||
|  | #include "ui/MainWindow.h" | ||||||
|  |  | ||||||
| #include "ui/dialogs/ProgressDialog.h" | #include "ui/dialogs/ProgressDialog.h" | ||||||
| #include "ui/instanceview/AccessibleInstanceView.h" | #include "ui/instanceview/AccessibleInstanceView.h" | ||||||
|  |  | ||||||
| #include "ui/pages/BasePageProvider.h" | #include "ui/pages/BasePageProvider.h" | ||||||
| #include "ui/pages/global/LauncherPage.h" | #include "ui/pages/global/APIPage.h" | ||||||
| #include "ui/pages/global/MinecraftPage.h" | #include "ui/pages/global/AccountListPage.h" | ||||||
|  | #include "ui/pages/global/CustomCommandsPage.h" | ||||||
|  | #include "ui/pages/global/ExternalToolsPage.h" | ||||||
| #include "ui/pages/global/JavaPage.h" | #include "ui/pages/global/JavaPage.h" | ||||||
| #include "ui/pages/global/LanguagePage.h" | #include "ui/pages/global/LanguagePage.h" | ||||||
|  | #include "ui/pages/global/LauncherPage.h" | ||||||
|  | #include "ui/pages/global/MinecraftPage.h" | ||||||
| #include "ui/pages/global/ProxyPage.h" | #include "ui/pages/global/ProxyPage.h" | ||||||
| #include "ui/pages/global/ExternalToolsPage.h" |  | ||||||
| #include "ui/pages/global/AccountListPage.h" |  | ||||||
| #include "ui/pages/global/APIPage.h" |  | ||||||
| #include "ui/pages/global/CustomCommandsPage.h" |  | ||||||
|  |  | ||||||
| #include "ui/setupwizard/SetupWizard.h" |  | ||||||
| #include "ui/setupwizard/LanguageWizardPage.h" |  | ||||||
| #include "ui/setupwizard/JavaWizardPage.h" | #include "ui/setupwizard/JavaWizardPage.h" | ||||||
|  | #include "ui/setupwizard/LanguageWizardPage.h" | ||||||
| #include "ui/setupwizard/PasteWizardPage.h" | #include "ui/setupwizard/PasteWizardPage.h" | ||||||
|  | #include "ui/setupwizard/SetupWizard.h" | ||||||
| #include "ui/setupwizard/ThemeWizardPage.h" | #include "ui/setupwizard/ThemeWizardPage.h" | ||||||
|  |  | ||||||
| #include "ui/dialogs/CustomMessageBox.h" | #include "ui/dialogs/CustomMessageBox.h" | ||||||
| @@ -83,20 +83,20 @@ | |||||||
| #include <iostream> | #include <iostream> | ||||||
| #include <mutex> | #include <mutex> | ||||||
|  |  | ||||||
| #include <QFileOpenEvent> |  | ||||||
| #include <QAccessible> | #include <QAccessible> | ||||||
| #include <QCommandLineParser> | #include <QCommandLineParser> | ||||||
|  | #include <QDebug> | ||||||
| #include <QDir> | #include <QDir> | ||||||
| #include <QFileInfo> | #include <QFileInfo> | ||||||
| #include <QNetworkAccessManager> | #include <QFileOpenEvent> | ||||||
| #include <QTranslator> | #include <QIcon> | ||||||
| #include <QLibraryInfo> | #include <QLibraryInfo> | ||||||
| #include <QList> | #include <QList> | ||||||
|  | #include <QNetworkAccessManager> | ||||||
| #include <QStringList> | #include <QStringList> | ||||||
| #include <QDebug> |  | ||||||
| #include <QStyleFactory> | #include <QStyleFactory> | ||||||
|  | #include <QTranslator> | ||||||
| #include <QWindow> | #include <QWindow> | ||||||
| #include <QIcon> |  | ||||||
|  |  | ||||||
| #include "InstanceList.h" | #include "InstanceList.h" | ||||||
| #include "MTPixmapCache.h" | #include "MTPixmapCache.h" | ||||||
| @@ -116,32 +116,31 @@ | |||||||
| #include "settings/INISettingsObject.h" | #include "settings/INISettingsObject.h" | ||||||
| #include "settings/Setting.h" | #include "settings/Setting.h" | ||||||
|  |  | ||||||
| #include "translations/TranslationsModel.h" |  | ||||||
| #include "meta/Index.h" | #include "meta/Index.h" | ||||||
|  | #include "translations/TranslationsModel.h" | ||||||
|  |  | ||||||
| #include <FileSystem.h> |  | ||||||
| #include <DesktopServices.h> | #include <DesktopServices.h> | ||||||
|  | #include <FileSystem.h> | ||||||
| #include <LocalPeer.h> | #include <LocalPeer.h> | ||||||
|  |  | ||||||
| #include <sys.h> | #include <sys.h> | ||||||
|  |  | ||||||
| #ifdef Q_OS_LINUX | #ifdef Q_OS_LINUX | ||||||
| #include <dlfcn.h> | #include <dlfcn.h> | ||||||
| #include "gamemode_client.h" |  | ||||||
| #include "MangoHud.h" | #include "MangoHud.h" | ||||||
|  | #include "gamemode_client.h" | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #ifdef Q_OS_MAC | #if defined(Q_OS_MAC) && defined(SPARKLE_ENABLED) | ||||||
| #include "updater/MacSparkleUpdater.h" | #include "updater/MacSparkleUpdater.h" | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  |  | ||||||
| #if defined Q_OS_WIN32 | #if defined Q_OS_WIN32 | ||||||
| #ifndef WIN32_LEAN_AND_MEAN | #ifndef WIN32_LEAN_AND_MEAN | ||||||
| #define WIN32_LEAN_AND_MEAN | #define WIN32_LEAN_AND_MEAN | ||||||
| #endif | #endif | ||||||
| #include <windows.h> |  | ||||||
| #include <stdio.h> | #include <stdio.h> | ||||||
|  | #include <windows.h> | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #define STRINGIFY(x) #x | #define STRINGIFY(x) #x | ||||||
| @@ -168,25 +167,21 @@ void appDebugOutput(QtMsgType type, const QMessageLogContext &context, const QSt | |||||||
|     fflush(stderr); |     fflush(stderr); | ||||||
| } | } | ||||||
|  |  | ||||||
| } | }  // namespace | ||||||
|  |  | ||||||
| Application::Application(int& argc, char** argv) : QApplication(argc, argv) | Application::Application(int& argc, char** argv) : QApplication(argc, argv) | ||||||
| { | { | ||||||
| #if defined Q_OS_WIN32 | #if defined Q_OS_WIN32 | ||||||
|     // attach the parent console |     // attach the parent console | ||||||
|     if(AttachConsole(ATTACH_PARENT_PROCESS)) |     if (AttachConsole(ATTACH_PARENT_PROCESS)) { | ||||||
|     { |  | ||||||
|         // if attach succeeds, reopen and sync all the i/o |         // if attach succeeds, reopen and sync all the i/o | ||||||
|         if(freopen("CON", "w", stdout)) |         if (freopen("CON", "w", stdout)) { | ||||||
|         { |  | ||||||
|             std::cout.sync_with_stdio(); |             std::cout.sync_with_stdio(); | ||||||
|         } |         } | ||||||
|         if(freopen("CON", "w", stderr)) |         if (freopen("CON", "w", stderr)) { | ||||||
|         { |  | ||||||
|             std::cerr.sync_with_stdio(); |             std::cerr.sync_with_stdio(); | ||||||
|         } |         } | ||||||
|         if(freopen("CON", "r", stdin)) |         if (freopen("CON", "r", stdin)) { | ||||||
|         { |  | ||||||
|             std::cin.sync_with_stdio(); |             std::cin.sync_with_stdio(); | ||||||
|         } |         } | ||||||
|         auto out = GetStdHandle(STD_OUTPUT_HANDLE); |         auto out = GetStdHandle(STD_OUTPUT_HANDLE); | ||||||
| @@ -211,15 +206,14 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) | |||||||
|     QCommandLineParser parser; |     QCommandLineParser parser; | ||||||
|     parser.setApplicationDescription(BuildConfig.LAUNCHER_DISPLAYNAME); |     parser.setApplicationDescription(BuildConfig.LAUNCHER_DISPLAYNAME); | ||||||
|  |  | ||||||
|     parser.addOptions({ |     parser.addOptions( | ||||||
|         {{"d", "dir"}, "Use a custom path as application root (use '.' for current directory)", "directory"}, |         { { { "d", "dir" }, "Use a custom path as application root (use '.' for current directory)", "directory" }, | ||||||
|           { { "l", "launch" }, "Launch the specified instance (by instance ID)", "instance" }, |           { { "l", "launch" }, "Launch the specified instance (by instance ID)", "instance" }, | ||||||
|           { { "s", "server" }, "Join the specified server on launch (only valid in combination with --launch)", "address" }, |           { { "s", "server" }, "Join the specified server on launch (only valid in combination with --launch)", "address" }, | ||||||
|           { { "a", "profile" }, "Use the account specified by its profile name (only valid in combination with --launch)", "profile" }, |           { { "a", "profile" }, "Use the account specified by its profile name (only valid in combination with --launch)", "profile" }, | ||||||
|           { "alive", "Write a small '" + liveCheckFile + "' file after the launcher starts" }, |           { "alive", "Write a small '" + liveCheckFile + "' file after the launcher starts" }, | ||||||
|           { { "I", "import" }, "Import instance from specified zip (local path or URL)", "file" }, |           { { "I", "import" }, "Import instance from specified zip (local path or URL)", "file" }, | ||||||
|         {"show", "Opens the window for the specified instance (by instance ID)", "show"} |           { "show", "Opens the window for the specified instance (by instance ID)", "show" } }); | ||||||
|     }); |  | ||||||
|     parser.addHelpOption(); |     parser.addHelpOption(); | ||||||
|     parser.addVersionOption(); |     parser.addVersionOption(); | ||||||
|  |  | ||||||
| @@ -241,10 +235,8 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) | |||||||
|         m_zipsToImport.append(QUrl::fromLocalFile(QFileInfo(zip_path).absoluteFilePath())); |         m_zipsToImport.append(QUrl::fromLocalFile(QFileInfo(zip_path).absoluteFilePath())); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|     // error if --launch is missing with --server or --profile |     // error if --launch is missing with --server or --profile | ||||||
|     if((!m_serverToJoin.isEmpty() || !m_profileToUse.isEmpty()) && m_instanceIdToLaunch.isEmpty()) |     if ((!m_serverToJoin.isEmpty() || !m_profileToUse.isEmpty()) && m_instanceIdToLaunch.isEmpty()) { | ||||||
|     { |  | ||||||
|         std::cerr << "--server and --profile can only be used in combination with --launch!" << std::endl; |         std::cerr << "--server and --profile can only be used in combination with --launch!" << std::endl; | ||||||
|         m_status = Application::Failed; |         m_status = Application::Failed; | ||||||
|         return; |         return; | ||||||
| @@ -272,16 +264,19 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) | |||||||
|     QString dataPath; |     QString dataPath; | ||||||
|     // change folder |     // change folder | ||||||
|     QString dirParam = parser.value("dir"); |     QString dirParam = parser.value("dir"); | ||||||
|     if (!dirParam.isEmpty()) |     if (!dirParam.isEmpty()) { | ||||||
|     { |  | ||||||
|         // the dir param. it makes multimc data path point to whatever the user specified |         // the dir param. it makes multimc data path point to whatever the user specified | ||||||
|         // on command line |         // on command line | ||||||
|         adjustedBy = "Command line"; |         adjustedBy = "Command line"; | ||||||
|         dataPath = dirParam; |         dataPath = dirParam; | ||||||
|  |     } else { | ||||||
|  |         QDir foo; | ||||||
|  |         if (DesktopServices::isSnap()) { | ||||||
|  |             foo = QDir(getenv("SNAP_USER_COMMON")); | ||||||
|  |         } else { | ||||||
|  |             foo = QDir(FS::PathCombine(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation), "..")); | ||||||
|         } |         } | ||||||
|     else |  | ||||||
|     { |  | ||||||
|         QDir foo(FS::PathCombine(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation), "..")); |  | ||||||
|         dataPath = foo.absolutePath(); |         dataPath = foo.absolutePath(); | ||||||
|         adjustedBy = "Persistent data path"; |         adjustedBy = "Persistent data path"; | ||||||
|  |  | ||||||
| @@ -294,34 +289,27 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) | |||||||
| #endif | #endif | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (!FS::ensureFolderPathExists(dataPath)) |     if (!FS::ensureFolderPathExists(dataPath)) { | ||||||
|     { |  | ||||||
|         showFatalErrorMessage( |         showFatalErrorMessage( | ||||||
|             "The launcher data folder could not be created.", |             "The launcher data folder could not be created.", | ||||||
|             QString( |             QString("The launcher data folder could not be created.\n" | ||||||
|                 "The launcher data folder could not be created.\n" |  | ||||||
|                     "\n" |                     "\n" | ||||||
|                     "Make sure you have the right permissions to the launcher data folder and any folder needed to access it.\n" |                     "Make sure you have the right permissions to the launcher data folder and any folder needed to access it.\n" | ||||||
|                     "(%1)\n" |                     "(%1)\n" | ||||||
|                     "\n" |                     "\n" | ||||||
|                 "The launcher cannot continue until you fix this problem." |                     "The launcher cannot continue until you fix this problem.") | ||||||
|             ).arg(dataPath) |                 .arg(dataPath)); | ||||||
|         ); |  | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|     if (!QDir::setCurrent(dataPath)) |     if (!QDir::setCurrent(dataPath)) { | ||||||
|     { |         showFatalErrorMessage("The launcher data folder could not be opened.", | ||||||
|         showFatalErrorMessage( |                               QString("The launcher data folder could not be opened.\n" | ||||||
|             "The launcher data folder could not be opened.", |  | ||||||
|             QString( |  | ||||||
|                 "The launcher data folder could not be opened.\n" |  | ||||||
|                                       "\n" |                                       "\n" | ||||||
|                                       "Make sure you have the right permissions to the launcher data folder.\n" |                                       "Make sure you have the right permissions to the launcher data folder.\n" | ||||||
|                                       "(%1)\n" |                                       "(%1)\n" | ||||||
|                                       "\n" |                                       "\n" | ||||||
|                 "The launcher cannot continue until you fix this problem." |                                       "The launcher cannot continue until you fix this problem.") | ||||||
|             ).arg(dataPath) |                                   .arg(dataPath)); | ||||||
|         ); |  | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -338,14 +326,12 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) | |||||||
|         if (m_peerInstance->isClient()) { |         if (m_peerInstance->isClient()) { | ||||||
|             int timeout = 2000; |             int timeout = 2000; | ||||||
|  |  | ||||||
|             if(m_instanceIdToLaunch.isEmpty()) |             if (m_instanceIdToLaunch.isEmpty()) { | ||||||
|             { |  | ||||||
|                 ApplicationMessage activate; |                 ApplicationMessage activate; | ||||||
|                 activate.command = "activate"; |                 activate.command = "activate"; | ||||||
|                 m_peerInstance->sendMessage(activate.serialize(), timeout); |                 m_peerInstance->sendMessage(activate.serialize(), timeout); | ||||||
|  |  | ||||||
|                 if(!m_zipsToImport.isEmpty()) |                 if (!m_zipsToImport.isEmpty()) { | ||||||
|                 { |  | ||||||
|                     for (auto zip_url : m_zipsToImport) { |                     for (auto zip_url : m_zipsToImport) { | ||||||
|                         ApplicationMessage import; |                         ApplicationMessage import; | ||||||
|                         import.command = "import"; |                         import.command = "import"; | ||||||
| @@ -353,19 +339,15 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) | |||||||
|                         m_peerInstance->sendMessage(import.serialize(), timeout); |                         m_peerInstance->sendMessage(import.serialize(), timeout); | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|             } |             } else { | ||||||
|             else |  | ||||||
|             { |  | ||||||
|                 ApplicationMessage launch; |                 ApplicationMessage launch; | ||||||
|                 launch.command = "launch"; |                 launch.command = "launch"; | ||||||
|                 launch.args["id"] = m_instanceIdToLaunch; |                 launch.args["id"] = m_instanceIdToLaunch; | ||||||
|  |  | ||||||
|                 if(!m_serverToJoin.isEmpty()) |                 if (!m_serverToJoin.isEmpty()) { | ||||||
|                 { |  | ||||||
|                     launch.args["server"] = m_serverToJoin; |                     launch.args["server"] = m_serverToJoin; | ||||||
|                 } |                 } | ||||||
|                 if(!m_profileToUse.isEmpty()) |                 if (!m_profileToUse.isEmpty()) { | ||||||
|                 { |  | ||||||
|                     launch.args["profile"] = m_profileToUse; |                     launch.args["profile"] = m_profileToUse; | ||||||
|                 } |                 } | ||||||
|                 m_peerInstance->sendMessage(launch.serialize(), timeout); |                 m_peerInstance->sendMessage(launch.serialize(), timeout); | ||||||
| @@ -409,9 +391,16 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) | |||||||
|         qInstallMessageHandler(appDebugOutput); |         qInstallMessageHandler(appDebugOutput); | ||||||
|  |  | ||||||
|         qSetMessagePattern( |         qSetMessagePattern( | ||||||
|                 "%{time process}" " " |             "%{time process}" | ||||||
|                 "%{if-debug}D%{endif}" "%{if-info}I%{endif}" "%{if-warning}W%{endif}" "%{if-critical}C%{endif}" "%{if-fatal}F%{endif}" |             " " | ||||||
|                 " " "|" " " |             "%{if-debug}D%{endif}" | ||||||
|  |             "%{if-info}I%{endif}" | ||||||
|  |             "%{if-warning}W%{endif}" | ||||||
|  |             "%{if-critical}C%{endif}" | ||||||
|  |             "%{if-fatal}F%{endif}" | ||||||
|  |             " " | ||||||
|  |             "|" | ||||||
|  |             " " | ||||||
|             "%{if-category}[%{category}]: %{endif}" |             "%{if-category}[%{category}]: %{endif}" | ||||||
|             "%{message}"); |             "%{message}"); | ||||||
|  |  | ||||||
| @@ -467,49 +456,44 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) | |||||||
|         bool migrated = false; |         bool migrated = false; | ||||||
|  |  | ||||||
|         if (!migrated) |         if (!migrated) | ||||||
|             migrated = handleDataMigration(dataPath, FS::PathCombine(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation), "../../PolyMC"), "PolyMC", "polymc.cfg"); |             migrated = handleDataMigration( | ||||||
|  |                 dataPath, FS::PathCombine(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation), "../../PolyMC"), "PolyMC", | ||||||
|  |                 "polymc.cfg"); | ||||||
|         if (!migrated) |         if (!migrated) | ||||||
|             migrated = handleDataMigration(dataPath, FS::PathCombine(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation), "../../multimc"), "MultiMC", "multimc.cfg"); |             migrated = handleDataMigration( | ||||||
|  |                 dataPath, FS::PathCombine(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation), "../../multimc"), "MultiMC", | ||||||
|  |                 "multimc.cfg"); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     { |     { | ||||||
|  |  | ||||||
|         qDebug() << BuildConfig.LAUNCHER_DISPLAYNAME << ", (c) 2013-2021 " << BuildConfig.LAUNCHER_COPYRIGHT; |         qDebug() << BuildConfig.LAUNCHER_DISPLAYNAME << ", (c) 2013-2021 " << BuildConfig.LAUNCHER_COPYRIGHT; | ||||||
|         qDebug() << "Version                    : " << BuildConfig.printableVersionString(); |         qDebug() << "Version                    : " << BuildConfig.printableVersionString(); | ||||||
|         qDebug() << "Platform                   : " << BuildConfig.BUILD_PLATFORM; |         qDebug() << "Platform                   : " << BuildConfig.BUILD_PLATFORM; | ||||||
|         qDebug() << "Git commit                 : " << BuildConfig.GIT_COMMIT; |         qDebug() << "Git commit                 : " << BuildConfig.GIT_COMMIT; | ||||||
|         qDebug() << "Git refspec                : " << BuildConfig.GIT_REFSPEC; |         qDebug() << "Git refspec                : " << BuildConfig.GIT_REFSPEC; | ||||||
|         if (adjustedBy.size()) |         if (adjustedBy.size()) { | ||||||
|         { |  | ||||||
|             qDebug() << "Work dir before adjustment : " << origcwdPath; |             qDebug() << "Work dir before adjustment : " << origcwdPath; | ||||||
|             qDebug() << "Work dir after adjustment  : " << QDir::currentPath(); |             qDebug() << "Work dir after adjustment  : " << QDir::currentPath(); | ||||||
|             qDebug() << "Adjusted by                : " << adjustedBy; |             qDebug() << "Adjusted by                : " << adjustedBy; | ||||||
|         } |         } else { | ||||||
|         else |  | ||||||
|         { |  | ||||||
|             qDebug() << "Work dir                   : " << QDir::currentPath(); |             qDebug() << "Work dir                   : " << QDir::currentPath(); | ||||||
|         } |         } | ||||||
|         qDebug() << "Binary path                : " << binPath; |         qDebug() << "Binary path                : " << binPath; | ||||||
|         qDebug() << "Application root path      : " << m_rootPath; |         qDebug() << "Application root path      : " << m_rootPath; | ||||||
|         if(!m_instanceIdToLaunch.isEmpty()) |         if (!m_instanceIdToLaunch.isEmpty()) { | ||||||
|         { |  | ||||||
|             qDebug() << "ID of instance to launch   : " << m_instanceIdToLaunch; |             qDebug() << "ID of instance to launch   : " << m_instanceIdToLaunch; | ||||||
|         } |         } | ||||||
|         if(!m_serverToJoin.isEmpty()) |         if (!m_serverToJoin.isEmpty()) { | ||||||
|         { |  | ||||||
|             qDebug() << "Address of server to join  :" << m_serverToJoin; |             qDebug() << "Address of server to join  :" << m_serverToJoin; | ||||||
|         } |         } | ||||||
|         qDebug() << "<> Paths set."; |         qDebug() << "<> Paths set."; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if(m_liveCheck) |     if (m_liveCheck) { | ||||||
|     { |  | ||||||
|         QFile check(liveCheckFile); |         QFile check(liveCheckFile); | ||||||
|         if(check.open(QIODevice::WriteOnly | QIODevice::Truncate)) |         if (check.open(QIODevice::WriteOnly | QIODevice::Truncate)) { | ||||||
|         { |  | ||||||
|             auto payload = appID.toString().toUtf8(); |             auto payload = appID.toString().toUtf8(); | ||||||
|             if(check.write(payload) == payload.size()) |             if (check.write(payload) == payload.size()) { | ||||||
|             { |  | ||||||
|                 check.close(); |                 check.close(); | ||||||
|             } else { |             } else { | ||||||
|                 qWarning() << "Could not write into" << liveCheckFile << "!"; |                 qWarning() << "Could not write into" << liveCheckFile << "!"; | ||||||
| @@ -628,9 +612,6 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) | |||||||
|         m_settings->registerSetting("ShowGlobalGameTime", true); |         m_settings->registerSetting("ShowGlobalGameTime", true); | ||||||
|         m_settings->registerSetting("RecordGameTime", true); |         m_settings->registerSetting("RecordGameTime", true); | ||||||
|  |  | ||||||
|         // Minecraft launch method |  | ||||||
|         m_settings->registerSetting("MCLaunchMethod", "LauncherPart"); |  | ||||||
|  |  | ||||||
|         // Minecraft mods |         // Minecraft mods | ||||||
|         m_settings->registerSetting("ModMetadataDisabled", false); |         m_settings->registerSetting("ModMetadataDisabled", false); | ||||||
|  |  | ||||||
| @@ -681,8 +662,7 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) | |||||||
|             QString pastebinURL = m_settings->get("PastebinURL").toString(); |             QString pastebinURL = m_settings->get("PastebinURL").toString(); | ||||||
|  |  | ||||||
|             bool userHadDefaultPastebin = pastebinURL == "https://0x0.st"; |             bool userHadDefaultPastebin = pastebinURL == "https://0x0.st"; | ||||||
|             if (!pastebinURL.isEmpty() && !userHadDefaultPastebin) |             if (!pastebinURL.isEmpty() && !userHadDefaultPastebin) { | ||||||
|             { |  | ||||||
|                 m_settings->set("PastebinType", PasteUpload::PasteType::NullPointer); |                 m_settings->set("PastebinType", PasteUpload::PasteType::NullPointer); | ||||||
|                 m_settings->set("PastebinCustomAPIBase", pastebinURL); |                 m_settings->set("PastebinCustomAPIBase", pastebinURL); | ||||||
|                 m_settings->reset("PastebinURL"); |                 m_settings->reset("PastebinURL"); | ||||||
| @@ -691,8 +671,7 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) | |||||||
|             bool ok; |             bool ok; | ||||||
|             int pasteType = m_settings->get("PastebinType").toInt(&ok); |             int pasteType = m_settings->get("PastebinType").toInt(&ok); | ||||||
|             // If PastebinType is invalid then reset the related settings. |             // If PastebinType is invalid then reset the related settings. | ||||||
|             if (!ok || !(PasteUpload::PasteType::First <= pasteType && pasteType <= PasteUpload::PasteType::Last)) |             if (!ok || !(PasteUpload::PasteType::First <= pasteType && pasteType <= PasteUpload::PasteType::Last)) { | ||||||
|             { |  | ||||||
|                 m_settings->reset("PastebinType"); |                 m_settings->reset("PastebinType"); | ||||||
|                 m_settings->reset("PastebinCustomAPIBase"); |                 m_settings->reset("PastebinCustomAPIBase"); | ||||||
|             } |             } | ||||||
| @@ -704,7 +683,7 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) | |||||||
|             QUrl metaUrl(m_settings->get("MetaURLOverride").toString()); |             QUrl metaUrl(m_settings->get("MetaURLOverride").toString()); | ||||||
|  |  | ||||||
|             // get rid of invalid meta urls |             // get rid of invalid meta urls | ||||||
|             if (!metaUrl.isValid() || metaUrl.scheme() != "http" || metaUrl.scheme() != "https") |             if (!metaUrl.isValid() || (metaUrl.scheme() != "http" && metaUrl.scheme() != "https")) | ||||||
|                 m_settings->reset("MetaURLOverride"); |                 m_settings->reset("MetaURLOverride"); | ||||||
|         } |         } | ||||||
|  |  | ||||||
| @@ -773,10 +752,9 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     // initialize the updater |     // initialize the updater | ||||||
|     if(BuildConfig.UPDATER_ENABLED) |     if (BuildConfig.UPDATER_ENABLED) { | ||||||
|     { |  | ||||||
|         qDebug() << "Initializing updater"; |         qDebug() << "Initializing updater"; | ||||||
| #ifdef Q_OS_MAC | #if defined(Q_OS_MAC) && defined(SPARKLE_ENABLED) | ||||||
|         m_updater.reset(new MacSparkleUpdater()); |         m_updater.reset(new MacSparkleUpdater()); | ||||||
| #endif | #endif | ||||||
|         qDebug() << "<> Updater started."; |         qDebug() << "<> Updater started."; | ||||||
| @@ -785,18 +763,11 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) | |||||||
|     // Instance icons |     // Instance icons | ||||||
|     { |     { | ||||||
|         auto setting = APPLICATION->settings()->getSetting("IconsDir"); |         auto setting = APPLICATION->settings()->getSetting("IconsDir"); | ||||||
|         QStringList instFolders = |         QStringList instFolders = { ":/icons/multimc/32x32/instances/", ":/icons/multimc/50x50/instances/", | ||||||
|         { |                                     ":/icons/multimc/128x128/instances/", ":/icons/multimc/scalable/instances/" }; | ||||||
|             ":/icons/multimc/32x32/instances/", |  | ||||||
|             ":/icons/multimc/50x50/instances/", |  | ||||||
|             ":/icons/multimc/128x128/instances/", |  | ||||||
|             ":/icons/multimc/scalable/instances/" |  | ||||||
|         }; |  | ||||||
|         m_icons.reset(new IconList(instFolders, setting->get().toString())); |         m_icons.reset(new IconList(instFolders, setting->get().toString())); | ||||||
|         connect(setting.get(), &Setting::SettingChanged,[&](const Setting &, QVariant value) |         connect(setting.get(), &Setting::SettingChanged, | ||||||
|         { |                 [&](const Setting&, QVariant value) { m_icons->directoryChanged(value.toString()); }); | ||||||
|             m_icons->directoryChanged(value.toString()); |  | ||||||
|         }); |  | ||||||
|         qDebug() << "<> Instance icons intialized."; |         qDebug() << "<> Instance icons intialized."; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -810,8 +781,7 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) | |||||||
|         // and remember that we have to show him a dialog when the gui starts (if it does so) |         // and remember that we have to show him a dialog when the gui starts (if it does so) | ||||||
|         QString instDir = InstDirSetting->get().toString(); |         QString instDir = InstDirSetting->get().toString(); | ||||||
|         qDebug() << "Instance path              : " << instDir; |         qDebug() << "Instance path              : " << instDir; | ||||||
|         if (FS::checkProblemticPathJava(QDir(instDir))) |         if (FS::checkProblemticPathJava(QDir(instDir))) { | ||||||
|         { |  | ||||||
|             qWarning() << "Your instance path contains \'!\' and this is known to cause java problems!"; |             qWarning() << "Your instance path contains \'!\' and this is known to cause java problems!"; | ||||||
|         } |         } | ||||||
|         m_instances.reset(new InstanceList(m_settings, instDir, this)); |         m_instances.reset(new InstanceList(m_settings, instDir, this)); | ||||||
| @@ -864,8 +834,7 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) | |||||||
|     // FIXME: what to do with these? |     // FIXME: what to do with these? | ||||||
|     m_profilers.insert("jprofiler", std::shared_ptr<BaseProfilerFactory>(new JProfilerFactory())); |     m_profilers.insert("jprofiler", std::shared_ptr<BaseProfilerFactory>(new JProfilerFactory())); | ||||||
|     m_profilers.insert("jvisualvm", std::shared_ptr<BaseProfilerFactory>(new JVisualVMFactory())); |     m_profilers.insert("jvisualvm", std::shared_ptr<BaseProfilerFactory>(new JVisualVMFactory())); | ||||||
|     for (auto profiler : m_profilers.values()) |     for (auto profiler : m_profilers.values()) { | ||||||
|     { |  | ||||||
|         profiler->registerSettings(m_settings); |         profiler->registerSettings(m_settings); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -875,19 +844,15 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) | |||||||
|     } |     } | ||||||
|  |  | ||||||
| #ifdef Q_OS_MACOS | #ifdef Q_OS_MACOS | ||||||
|     connect(this, &Application::clickedOnDock, [this]() { |     connect(this, &Application::clickedOnDock, [this]() { this->showMainWindow(); }); | ||||||
|         this->showMainWindow(); |  | ||||||
|     }); |  | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|     connect(this, &Application::aboutToQuit, [this]() { |     connect(this, &Application::aboutToQuit, [this]() { | ||||||
|         if(m_instances) |         if (m_instances) { | ||||||
|         { |  | ||||||
|             // save any remaining instance state |             // save any remaining instance state | ||||||
|             m_instances->saveNow(); |             m_instances->saveNow(); | ||||||
|         } |         } | ||||||
|         if(logFile) |         if (logFile) { | ||||||
|         { |  | ||||||
|             logFile->flush(); |             logFile->flush(); | ||||||
|             logFile->close(); |             logFile->close(); | ||||||
|         } |         } | ||||||
| @@ -895,8 +860,7 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) | |||||||
|  |  | ||||||
|     updateCapabilities(); |     updateCapabilities(); | ||||||
|  |  | ||||||
|     if(createSetupWizard()) |     if (createSetupWizard()) { | ||||||
|     { |  | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -906,23 +870,20 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) | |||||||
|  |  | ||||||
| bool Application::createSetupWizard() | bool Application::createSetupWizard() | ||||||
| { | { | ||||||
|     bool javaRequired = [&]() |     bool javaRequired = [&]() { | ||||||
|     { |  | ||||||
|         bool ignoreJavaWizard = m_settings->get("IgnoreJavaWizard").toBool(); |         bool ignoreJavaWizard = m_settings->get("IgnoreJavaWizard").toBool(); | ||||||
|         if (ignoreJavaWizard) { |         if (ignoreJavaWizard) { | ||||||
|             return false; |             return false; | ||||||
|         } |         } | ||||||
|         QString currentHostName = QHostInfo::localHostName(); |         QString currentHostName = QHostInfo::localHostName(); | ||||||
|         QString oldHostName = settings()->get("LastHostname").toString(); |         QString oldHostName = settings()->get("LastHostname").toString(); | ||||||
|         if (currentHostName != oldHostName) |         if (currentHostName != oldHostName) { | ||||||
|         { |  | ||||||
|             settings()->set("LastHostname", currentHostName); |             settings()->set("LastHostname", currentHostName); | ||||||
|             return true; |             return true; | ||||||
|         } |         } | ||||||
|         QString currentJavaPath = settings()->get("JavaPath").toString(); |         QString currentJavaPath = settings()->get("JavaPath").toString(); | ||||||
|         QString actualPath = FS::ResolveExecutable(currentJavaPath); |         QString actualPath = FS::ResolveExecutable(currentJavaPath); | ||||||
|         if (actualPath.isNull()) |         if (actualPath.isNull()) { | ||||||
|         { |  | ||||||
|             return true; |             return true; | ||||||
|         } |         } | ||||||
|         return false; |         return false; | ||||||
| @@ -945,23 +906,19 @@ bool Application::createSetupWizard() | |||||||
|         m_themeManager->applyCurrentlySelectedTheme(true); |         m_themeManager->applyCurrentlySelectedTheme(true); | ||||||
|  |  | ||||||
|         m_setupWizard = new SetupWizard(nullptr); |         m_setupWizard = new SetupWizard(nullptr); | ||||||
|         if (languageRequired) |         if (languageRequired) { | ||||||
|         { |  | ||||||
|             m_setupWizard->addPage(new LanguageWizardPage(m_setupWizard)); |             m_setupWizard->addPage(new LanguageWizardPage(m_setupWizard)); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if (javaRequired) |         if (javaRequired) { | ||||||
|         { |  | ||||||
|             m_setupWizard->addPage(new JavaWizardPage(m_setupWizard)); |             m_setupWizard->addPage(new JavaWizardPage(m_setupWizard)); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if (pasteInterventionRequired) |         if (pasteInterventionRequired) { | ||||||
|         { |  | ||||||
|             m_setupWizard->addPage(new PasteWizardPage(m_setupWizard)); |             m_setupWizard->addPage(new PasteWizardPage(m_setupWizard)); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if (themeInterventionRequired) |         if (themeInterventionRequired) { | ||||||
|         { |  | ||||||
|             m_setupWizard->addPage(new ThemeWizardPage(m_setupWizard)); |             m_setupWizard->addPage(new ThemeWizardPage(m_setupWizard)); | ||||||
|         } |         } | ||||||
|  |  | ||||||
| @@ -1002,24 +959,20 @@ void Application::setupWizardFinished(int status) | |||||||
| void Application::performMainStartupAction() | void Application::performMainStartupAction() | ||||||
| { | { | ||||||
|     m_status = Application::Initialized; |     m_status = Application::Initialized; | ||||||
|     if(!m_instanceIdToLaunch.isEmpty()) |     if (!m_instanceIdToLaunch.isEmpty()) { | ||||||
|     { |  | ||||||
|         auto inst = instances()->getInstanceById(m_instanceIdToLaunch); |         auto inst = instances()->getInstanceById(m_instanceIdToLaunch); | ||||||
|         if(inst) |         if (inst) { | ||||||
|         { |  | ||||||
|             MinecraftServerTargetPtr serverToJoin = nullptr; |             MinecraftServerTargetPtr serverToJoin = nullptr; | ||||||
|             MinecraftAccountPtr accountToUse = nullptr; |             MinecraftAccountPtr accountToUse = nullptr; | ||||||
|  |  | ||||||
|             qDebug() << "<> Instance" << m_instanceIdToLaunch << "launching"; |             qDebug() << "<> Instance" << m_instanceIdToLaunch << "launching"; | ||||||
|             if(!m_serverToJoin.isEmpty()) |             if (!m_serverToJoin.isEmpty()) { | ||||||
|             { |  | ||||||
|                 // FIXME: validate the server string |                 // FIXME: validate the server string | ||||||
|                 serverToJoin.reset(new MinecraftServerTarget(MinecraftServerTarget::parse(m_serverToJoin))); |                 serverToJoin.reset(new MinecraftServerTarget(MinecraftServerTarget::parse(m_serverToJoin))); | ||||||
|                 qDebug() << "   Launching with server" << m_serverToJoin; |                 qDebug() << "   Launching with server" << m_serverToJoin; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             if(!m_profileToUse.isEmpty()) |             if (!m_profileToUse.isEmpty()) { | ||||||
|             { |  | ||||||
|                 accountToUse = accounts()->getAccountByProfileName(m_profileToUse); |                 accountToUse = accounts()->getAccountByProfileName(m_profileToUse); | ||||||
|                 if (!accountToUse) { |                 if (!accountToUse) { | ||||||
|                     return; |                     return; | ||||||
| @@ -1031,24 +984,20 @@ void Application::performMainStartupAction() | |||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     if(!m_instanceIdToShowWindowOf.isEmpty()) |     if (!m_instanceIdToShowWindowOf.isEmpty()) { | ||||||
|     { |  | ||||||
|         auto inst = instances()->getInstanceById(m_instanceIdToShowWindowOf); |         auto inst = instances()->getInstanceById(m_instanceIdToShowWindowOf); | ||||||
|         if(inst) |         if (inst) { | ||||||
|         { |  | ||||||
|             qDebug() << "<> Showing window of instance " << m_instanceIdToShowWindowOf; |             qDebug() << "<> Showing window of instance " << m_instanceIdToShowWindowOf; | ||||||
|             showInstanceWindow(inst); |             showInstanceWindow(inst); | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     if(!m_mainWindow) |     if (!m_mainWindow) { | ||||||
|     { |  | ||||||
|         // normal main window |         // normal main window | ||||||
|         showMainWindow(false); |         showMainWindow(false); | ||||||
|         qDebug() << "<> Main window shown."; |         qDebug() << "<> Main window shown."; | ||||||
|     } |     } | ||||||
|     if(!m_zipsToImport.isEmpty()) |     if (!m_zipsToImport.isEmpty()) { | ||||||
|     { |  | ||||||
|         qDebug() << "<> Importing from zip:" << m_zipsToImport; |         qDebug() << "<> Importing from zip:" << m_zipsToImport; | ||||||
|         m_mainWindow->processURLs(m_zipsToImport); |         m_mainWindow->processURLs(m_zipsToImport); | ||||||
|     } |     } | ||||||
| @@ -1068,8 +1017,7 @@ Application::~Application() | |||||||
|  |  | ||||||
| #if defined Q_OS_WIN32 | #if defined Q_OS_WIN32 | ||||||
|     // Detach from Windows console |     // Detach from Windows console | ||||||
|     if(consoleAttached) |     if (consoleAttached) { | ||||||
|     { |  | ||||||
|         fclose(stdout); |         fclose(stdout); | ||||||
|         fclose(stdin); |         fclose(stdin); | ||||||
|         fclose(stderr); |         fclose(stderr); | ||||||
| @@ -1080,8 +1028,7 @@ Application::~Application() | |||||||
|  |  | ||||||
| void Application::messageReceived(const QByteArray& message) | void Application::messageReceived(const QByteArray& message) | ||||||
| { | { | ||||||
|     if(status() != Initialized) |     if (status() != Initialized) { | ||||||
|     { |  | ||||||
|         qDebug() << "Received message" << message << "while still initializing. It will be ignored."; |         qDebug() << "Received message" << message << "while still initializing. It will be ignored."; | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
| @@ -1091,22 +1038,16 @@ void Application::messageReceived(const QByteArray& message) | |||||||
|  |  | ||||||
|     auto& command = received.command; |     auto& command = received.command; | ||||||
|  |  | ||||||
|     if(command == "activate") |     if (command == "activate") { | ||||||
|     { |  | ||||||
|         showMainWindow(); |         showMainWindow(); | ||||||
|     } |     } else if (command == "import") { | ||||||
|     else if(command == "import") |  | ||||||
|     { |  | ||||||
|         QString path = received.args["path"]; |         QString path = received.args["path"]; | ||||||
|         if(path.isEmpty()) |         if (path.isEmpty()) { | ||||||
|         { |  | ||||||
|             qWarning() << "Received" << command << "message without a zip path/URL."; |             qWarning() << "Received" << command << "message without a zip path/URL."; | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|         m_mainWindow->processURLs({ QUrl::fromLocalFile(QFileInfo(path).absoluteFilePath()) }); |         m_mainWindow->processURLs({ QUrl::fromLocalFile(QFileInfo(path).absoluteFilePath()) }); | ||||||
|     } |     } else if (command == "launch") { | ||||||
|     else if(command == "launch") |  | ||||||
|     { |  | ||||||
|         QString id = received.args["id"]; |         QString id = received.args["id"]; | ||||||
|         QString server = received.args["server"]; |         QString server = received.args["server"]; | ||||||
|         QString profile = received.args["profile"]; |         QString profile = received.args["profile"]; | ||||||
| @@ -1118,8 +1059,7 @@ void Application::messageReceived(const QByteArray& message) | |||||||
|                 qWarning() << "Launch command requires an valid instance ID. " << id << "resolves to nothing."; |                 qWarning() << "Launch command requires an valid instance ID. " << id << "resolves to nothing."; | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
|         } |         } else { | ||||||
|         else { |  | ||||||
|             qWarning() << "Launch command called without an instance ID..."; |             qWarning() << "Launch command called without an instance ID..."; | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
| @@ -1133,22 +1073,14 @@ void Application::messageReceived(const QByteArray& message) | |||||||
|         if (!profile.isEmpty()) { |         if (!profile.isEmpty()) { | ||||||
|             accountObject = accounts()->getAccountByProfileName(profile); |             accountObject = accounts()->getAccountByProfileName(profile); | ||||||
|             if (!accountObject) { |             if (!accountObject) { | ||||||
|                 qWarning() << "Launch command requires the specified profile to be valid. " << profile << "does not resolve to any account."; |                 qWarning() << "Launch command requires the specified profile to be valid. " << profile | ||||||
|  |                            << "does not resolve to any account."; | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         launch( |         launch(instance, true, false, nullptr, serverObject, accountObject); | ||||||
|             instance, |     } else { | ||||||
|             true, |  | ||||||
|             false, |  | ||||||
|             nullptr, |  | ||||||
|             serverObject, |  | ||||||
|             accountObject |  | ||||||
|         ); |  | ||||||
|     } |  | ||||||
|     else |  | ||||||
|     { |  | ||||||
|         qWarning() << "Received invalid message" << message; |         qWarning() << "Received invalid message" << message; | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -1160,8 +1092,7 @@ std::shared_ptr<TranslationsModel> Application::translations() | |||||||
|  |  | ||||||
| std::shared_ptr<JavaInstallList> Application::javalist() | std::shared_ptr<JavaInstallList> Application::javalist() | ||||||
| { | { | ||||||
|     if (!m_javalist) |     if (!m_javalist) { | ||||||
|     { |  | ||||||
|         m_javalist.reset(new JavaInstallList()); |         m_javalist.reset(new JavaInstallList()); | ||||||
|     } |     } | ||||||
|     return m_javalist; |     return m_javalist; | ||||||
| @@ -1178,37 +1109,28 @@ QIcon Application::getThemedIcon(const QString& name) | |||||||
| bool Application::openJsonEditor(const QString& filename) | bool Application::openJsonEditor(const QString& filename) | ||||||
| { | { | ||||||
|     const QString file = QDir::current().absoluteFilePath(filename); |     const QString file = QDir::current().absoluteFilePath(filename); | ||||||
|     if (m_settings->get("JsonEditor").toString().isEmpty()) |     if (m_settings->get("JsonEditor").toString().isEmpty()) { | ||||||
|     { |  | ||||||
|         return DesktopServices::openUrl(QUrl::fromLocalFile(file)); |         return DesktopServices::openUrl(QUrl::fromLocalFile(file)); | ||||||
|     } |     } else { | ||||||
|     else |  | ||||||
|     { |  | ||||||
|         // return DesktopServices::openFile(m_settings->get("JsonEditor").toString(), file); |         // return DesktopServices::openFile(m_settings->get("JsonEditor").toString(), file); | ||||||
|         return DesktopServices::run(m_settings->get("JsonEditor").toString(), { file }); |         return DesktopServices::run(m_settings->get("JsonEditor").toString(), { file }); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| bool Application::launch( | bool Application::launch(InstancePtr instance, | ||||||
|         InstancePtr instance, |  | ||||||
|                          bool online, |                          bool online, | ||||||
|                          bool demo, |                          bool demo, | ||||||
|                          BaseProfilerFactory* profiler, |                          BaseProfilerFactory* profiler, | ||||||
|                          MinecraftServerTargetPtr serverToJoin, |                          MinecraftServerTargetPtr serverToJoin, | ||||||
|         MinecraftAccountPtr accountToUse |                          MinecraftAccountPtr accountToUse) | ||||||
| ) { |  | ||||||
|     if(m_updateRunning) |  | ||||||
| { | { | ||||||
|  |     if (m_updateRunning) { | ||||||
|         qDebug() << "Cannot launch instances while an update is running. Please try again when updates are completed."; |         qDebug() << "Cannot launch instances while an update is running. Please try again when updates are completed."; | ||||||
|     } |     } else if (instance->canLaunch()) { | ||||||
|     else if(instance->canLaunch()) |  | ||||||
|     { |  | ||||||
|         auto& extras = m_instanceExtras[instance->id()]; |         auto& extras = m_instanceExtras[instance->id()]; | ||||||
|         auto& window = extras.window; |         auto& window = extras.window; | ||||||
|         if(window) |         if (window) { | ||||||
|         { |             if (!window->saveAll()) { | ||||||
|             if(!window->saveAll()) |  | ||||||
|             { |  | ||||||
|                 return false; |                 return false; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| @@ -1220,30 +1142,21 @@ bool Application::launch( | |||||||
|         controller->setProfiler(profiler); |         controller->setProfiler(profiler); | ||||||
|         controller->setServerToJoin(serverToJoin); |         controller->setServerToJoin(serverToJoin); | ||||||
|         controller->setAccountToUse(accountToUse); |         controller->setAccountToUse(accountToUse); | ||||||
|         if(window) |         if (window) { | ||||||
|         { |  | ||||||
|             controller->setParentWidget(window); |             controller->setParentWidget(window); | ||||||
|         } |         } else if (m_mainWindow) { | ||||||
|         else if(m_mainWindow) |  | ||||||
|         { |  | ||||||
|             controller->setParentWidget(m_mainWindow); |             controller->setParentWidget(m_mainWindow); | ||||||
|         } |         } | ||||||
|         connect(controller.get(), &LaunchController::succeeded, this, &Application::controllerSucceeded); |         connect(controller.get(), &LaunchController::succeeded, this, &Application::controllerSucceeded); | ||||||
|         connect(controller.get(), &LaunchController::failed, this, &Application::controllerFailed); |         connect(controller.get(), &LaunchController::failed, this, &Application::controllerFailed); | ||||||
|         connect(controller.get(), &LaunchController::aborted, this, [this] { |         connect(controller.get(), &LaunchController::aborted, this, [this] { controllerFailed(tr("Aborted")); }); | ||||||
|             controllerFailed(tr("Aborted")); |  | ||||||
|         }); |  | ||||||
|         addRunningInstance(); |         addRunningInstance(); | ||||||
|         controller->start(); |         controller->start(); | ||||||
|         return true; |         return true; | ||||||
|     } |     } else if (instance->isRunning()) { | ||||||
|     else if (instance->isRunning()) |  | ||||||
|     { |  | ||||||
|         showInstanceWindow(instance, "console"); |         showInstanceWindow(instance, "console"); | ||||||
|         return true; |         return true; | ||||||
|     } |     } else if (instance->canEdit()) { | ||||||
|     else if (instance->canEdit()) |  | ||||||
|     { |  | ||||||
|         showInstanceWindow(instance); |         showInstanceWindow(instance); | ||||||
|         return true; |         return true; | ||||||
|     } |     } | ||||||
| @@ -1252,16 +1165,14 @@ bool Application::launch( | |||||||
|  |  | ||||||
| bool Application::kill(InstancePtr instance) | bool Application::kill(InstancePtr instance) | ||||||
| { | { | ||||||
|     if (!instance->isRunning()) |     if (!instance->isRunning()) { | ||||||
|     { |  | ||||||
|         qWarning() << "Attempted to kill instance" << instance->id() << ", which isn't running."; |         qWarning() << "Attempted to kill instance" << instance->id() << ", which isn't running."; | ||||||
|         return false; |         return false; | ||||||
|     } |     } | ||||||
|     auto& extras = m_instanceExtras[instance->id()]; |     auto& extras = m_instanceExtras[instance->id()]; | ||||||
|     // NOTE: copy of the shared pointer keeps it alive |     // NOTE: copy of the shared pointer keeps it alive | ||||||
|     auto controller = extras.controller; |     auto controller = extras.controller; | ||||||
|     if(controller) |     if (controller) { | ||||||
|     { |  | ||||||
|         return controller->abort(); |         return controller->abort(); | ||||||
|     } |     } | ||||||
|     return true; |     return true; | ||||||
| @@ -1276,22 +1187,19 @@ void Application::closeCurrentWindow() | |||||||
| void Application::addRunningInstance() | void Application::addRunningInstance() | ||||||
| { | { | ||||||
|     m_runningInstances++; |     m_runningInstances++; | ||||||
|     if(m_runningInstances == 1) |     if (m_runningInstances == 1) { | ||||||
|     { |  | ||||||
|         emit updateAllowedChanged(false); |         emit updateAllowedChanged(false); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| void Application::subRunningInstance() | void Application::subRunningInstance() | ||||||
| { | { | ||||||
|     if(m_runningInstances == 0) |     if (m_runningInstances == 0) { | ||||||
|     { |  | ||||||
|         qCritical() << "Something went really wrong and we now have less than 0 running instances... WTF"; |         qCritical() << "Something went really wrong and we now have less than 0 running instances... WTF"; | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|     m_runningInstances--; |     m_runningInstances--; | ||||||
|     if(m_runningInstances == 0) |     if (m_runningInstances == 0) { | ||||||
|     { |  | ||||||
|         emit updateAllowedChanged(true); |         emit updateAllowedChanged(true); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -1311,7 +1219,6 @@ void Application::updateIsRunning(bool running) | |||||||
|     m_updateRunning = running; |     m_updateRunning = running; | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| void Application::controllerSucceeded() | void Application::controllerSucceeded() | ||||||
| { | { | ||||||
|     auto controller = qobject_cast<LaunchController*>(QObject::sender()); |     auto controller = qobject_cast<LaunchController*>(QObject::sender()); | ||||||
| @@ -1321,10 +1228,8 @@ void Application::controllerSucceeded() | |||||||
|     auto& extras = m_instanceExtras[id]; |     auto& extras = m_instanceExtras[id]; | ||||||
|  |  | ||||||
|     // on success, do... |     // on success, do... | ||||||
|     if (controller->instance()->settings()->get("AutoCloseConsole").toBool()) |     if (controller->instance()->settings()->get("AutoCloseConsole").toBool()) { | ||||||
|     { |         if (extras.window) { | ||||||
|         if(extras.window) |  | ||||||
|         { |  | ||||||
|             extras.window->close(); |             extras.window->close(); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @@ -1332,8 +1237,7 @@ void Application::controllerSucceeded() | |||||||
|     subRunningInstance(); |     subRunningInstance(); | ||||||
|  |  | ||||||
|     // quit when there are no more windows. |     // quit when there are no more windows. | ||||||
|     if(shouldExitNow()) |     if (shouldExitNow()) { | ||||||
|     { |  | ||||||
|         m_status = Status::Succeeded; |         m_status = Status::Succeeded; | ||||||
|         exit(0); |         exit(0); | ||||||
|     } |     } | ||||||
| @@ -1353,8 +1257,7 @@ void Application::controllerFailed(const QString& error) | |||||||
|     subRunningInstance(); |     subRunningInstance(); | ||||||
|  |  | ||||||
|     // quit when there are no more windows. |     // quit when there are no more windows. | ||||||
|     if(shouldExitNow()) |     if (shouldExitNow()) { | ||||||
|     { |  | ||||||
|         m_status = Status::Failed; |         m_status = Status::Failed; | ||||||
|         exit(1); |         exit(1); | ||||||
|     } |     } | ||||||
| @@ -1376,24 +1279,18 @@ void Application::ShowGlobalSettings(class QWidget* parent, QString open_page) | |||||||
|  |  | ||||||
| MainWindow* Application::showMainWindow(bool minimized) | MainWindow* Application::showMainWindow(bool minimized) | ||||||
| { | { | ||||||
|     if(m_mainWindow) |     if (m_mainWindow) { | ||||||
|     { |  | ||||||
|         m_mainWindow->setWindowState(m_mainWindow->windowState() & ~Qt::WindowMinimized); |         m_mainWindow->setWindowState(m_mainWindow->windowState() & ~Qt::WindowMinimized); | ||||||
|         m_mainWindow->raise(); |         m_mainWindow->raise(); | ||||||
|         m_mainWindow->activateWindow(); |         m_mainWindow->activateWindow(); | ||||||
|     } |     } else { | ||||||
|     else |  | ||||||
|     { |  | ||||||
|         m_mainWindow = new MainWindow(); |         m_mainWindow = new MainWindow(); | ||||||
|         m_mainWindow->restoreState(QByteArray::fromBase64(APPLICATION->settings()->get("MainWindowState").toByteArray())); |         m_mainWindow->restoreState(QByteArray::fromBase64(APPLICATION->settings()->get("MainWindowState").toByteArray())); | ||||||
|         m_mainWindow->restoreGeometry(QByteArray::fromBase64(APPLICATION->settings()->get("MainWindowGeometry").toByteArray())); |         m_mainWindow->restoreGeometry(QByteArray::fromBase64(APPLICATION->settings()->get("MainWindowGeometry").toByteArray())); | ||||||
|  |  | ||||||
|         if(minimized) |         if (minimized) { | ||||||
|         { |  | ||||||
|             m_mainWindow->showMinimized(); |             m_mainWindow->showMinimized(); | ||||||
|         } |         } else { | ||||||
|         else |  | ||||||
|         { |  | ||||||
|             m_mainWindow->show(); |             m_mainWindow->show(); | ||||||
|         } |         } | ||||||
|  |  | ||||||
| @@ -1413,23 +1310,18 @@ InstanceWindow *Application::showInstanceWindow(InstancePtr instance, QString pa | |||||||
|     auto& extras = m_instanceExtras[id]; |     auto& extras = m_instanceExtras[id]; | ||||||
|     auto& window = extras.window; |     auto& window = extras.window; | ||||||
|  |  | ||||||
|     if(window) |     if (window) { | ||||||
|     { |  | ||||||
|         window->raise(); |         window->raise(); | ||||||
|         window->activateWindow(); |         window->activateWindow(); | ||||||
|     } |     } else { | ||||||
|     else |  | ||||||
|     { |  | ||||||
|         window = new InstanceWindow(instance); |         window = new InstanceWindow(instance); | ||||||
|         m_openWindows++; |         m_openWindows++; | ||||||
|         connect(window, &InstanceWindow::isClosing, this, &Application::on_windowClose); |         connect(window, &InstanceWindow::isClosing, this, &Application::on_windowClose); | ||||||
|     } |     } | ||||||
|     if(!page.isEmpty()) |     if (!page.isEmpty()) { | ||||||
|     { |  | ||||||
|         window->selectPage(page); |         window->selectPage(page); | ||||||
|     } |     } | ||||||
|     if(extras.controller) |     if (extras.controller) { | ||||||
|     { |  | ||||||
|         extras.controller->setParentWidget(window); |         extras.controller->setParentWidget(window); | ||||||
|     } |     } | ||||||
|     return window; |     return window; | ||||||
| @@ -1439,23 +1331,19 @@ void Application::on_windowClose() | |||||||
| { | { | ||||||
|     m_openWindows--; |     m_openWindows--; | ||||||
|     auto instWindow = qobject_cast<InstanceWindow*>(QObject::sender()); |     auto instWindow = qobject_cast<InstanceWindow*>(QObject::sender()); | ||||||
|     if(instWindow) |     if (instWindow) { | ||||||
|     { |  | ||||||
|         auto& extras = m_instanceExtras[instWindow->instanceId()]; |         auto& extras = m_instanceExtras[instWindow->instanceId()]; | ||||||
|         extras.window = nullptr; |         extras.window = nullptr; | ||||||
|         if(extras.controller) |         if (extras.controller) { | ||||||
|         { |  | ||||||
|             extras.controller->setParentWidget(m_mainWindow); |             extras.controller->setParentWidget(m_mainWindow); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     auto mainWindow = qobject_cast<MainWindow*>(QObject::sender()); |     auto mainWindow = qobject_cast<MainWindow*>(QObject::sender()); | ||||||
|     if(mainWindow) |     if (mainWindow) { | ||||||
|     { |  | ||||||
|         m_mainWindow = nullptr; |         m_mainWindow = nullptr; | ||||||
|     } |     } | ||||||
|     // quit when there are no more windows. |     // quit when there are no more windows. | ||||||
|     if(shouldExitNow()) |     if (shouldExitNow()) { | ||||||
|     { |  | ||||||
|         exit(0); |         exit(0); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -1463,23 +1351,14 @@ void Application::on_windowClose() | |||||||
| void Application::updateProxySettings(QString proxyTypeStr, QString addr, int port, QString user, QString password) | void Application::updateProxySettings(QString proxyTypeStr, QString addr, int port, QString user, QString password) | ||||||
| { | { | ||||||
|     // Set the application proxy settings. |     // Set the application proxy settings. | ||||||
|     if (proxyTypeStr == "SOCKS5") |     if (proxyTypeStr == "SOCKS5") { | ||||||
|     { |         QNetworkProxy::setApplicationProxy(QNetworkProxy(QNetworkProxy::Socks5Proxy, addr, port, user, password)); | ||||||
|         QNetworkProxy::setApplicationProxy( |     } else if (proxyTypeStr == "HTTP") { | ||||||
|             QNetworkProxy(QNetworkProxy::Socks5Proxy, addr, port, user, password)); |         QNetworkProxy::setApplicationProxy(QNetworkProxy(QNetworkProxy::HttpProxy, addr, port, user, password)); | ||||||
|     } |     } else if (proxyTypeStr == "None") { | ||||||
|     else if (proxyTypeStr == "HTTP") |  | ||||||
|     { |  | ||||||
|         QNetworkProxy::setApplicationProxy( |  | ||||||
|             QNetworkProxy(QNetworkProxy::HttpProxy, addr, port, user, password)); |  | ||||||
|     } |  | ||||||
|     else if (proxyTypeStr == "None") |  | ||||||
|     { |  | ||||||
|         // If we have no proxy set, set no proxy and return. |         // If we have no proxy set, set no proxy and return. | ||||||
|         QNetworkProxy::setApplicationProxy(QNetworkProxy(QNetworkProxy::NoProxy)); |         QNetworkProxy::setApplicationProxy(QNetworkProxy(QNetworkProxy::NoProxy)); | ||||||
|     } |     } else { | ||||||
|     else |  | ||||||
|     { |  | ||||||
|         // If we have "Default" selected, set Qt to use the system proxy settings. |         // If we have "Default" selected, set Qt to use the system proxy settings. | ||||||
|         QNetworkProxyFactory::setUseSystemConfiguration(true); |         QNetworkProxyFactory::setUseSystemConfiguration(true); | ||||||
|     } |     } | ||||||
| @@ -1489,13 +1368,11 @@ void Application::updateProxySettings(QString proxyTypeStr, QString addr, int po | |||||||
|     m_network->setProxy(proxy); |     m_network->setProxy(proxy); | ||||||
|  |  | ||||||
|     QString proxyDesc; |     QString proxyDesc; | ||||||
|     if (proxy.type() == QNetworkProxy::NoProxy) |     if (proxy.type() == QNetworkProxy::NoProxy) { | ||||||
|     { |  | ||||||
|         qDebug() << "Using no proxy is an option!"; |         qDebug() << "Using no proxy is an option!"; | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|     switch (proxy.type()) |     switch (proxy.type()) { | ||||||
|     { |  | ||||||
|         case QNetworkProxy::DefaultProxy: |         case QNetworkProxy::DefaultProxy: | ||||||
|             proxyDesc = "Default proxy: "; |             proxyDesc = "Default proxy: "; | ||||||
|             break; |             break; | ||||||
| @@ -1515,9 +1392,7 @@ void Application::updateProxySettings(QString proxyTypeStr, QString addr, int po | |||||||
|             proxyDesc = "DERP proxy: "; |             proxyDesc = "DERP proxy: "; | ||||||
|             break; |             break; | ||||||
|     } |     } | ||||||
|     proxyDesc += QString("%1:%2") |     proxyDesc += QString("%1:%2").arg(proxy.hostName()).arg(proxy.port()); | ||||||
|                      .arg(proxy.hostName()) |  | ||||||
|                      .arg(proxy.port()); |  | ||||||
|     qDebug() << proxyDesc; |     qDebug() << proxyDesc; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -1533,8 +1408,7 @@ shared_qobject_ptr<QNetworkAccessManager> Application::network() | |||||||
|  |  | ||||||
| shared_qobject_ptr<Meta::Index> Application::metadataIndex() | shared_qobject_ptr<Meta::Index> Application::metadataIndex() | ||||||
| { | { | ||||||
|     if (!m_metadataIndex) |     if (!m_metadataIndex) { | ||||||
|     { |  | ||||||
|         m_metadataIndex.reset(new Meta::Index()); |         m_metadataIndex.reset(new Meta::Index()); | ||||||
|     } |     } | ||||||
|     return m_metadataIndex; |     return m_metadataIndex; | ||||||
| @@ -1567,8 +1441,7 @@ QString Application::getJarPath(QString jarFile) | |||||||
|         FS::PathCombine(applicationDirPath(), "jars"), |         FS::PathCombine(applicationDirPath(), "jars"), | ||||||
|         FS::PathCombine(applicationDirPath(), "..", "jars")  // from inside build dir, for debuging |         FS::PathCombine(applicationDirPath(), "..", "jars")  // from inside build dir, for debuging | ||||||
|     }; |     }; | ||||||
|     for(QString p : potentialPaths) |     for (QString p : potentialPaths) { | ||||||
|     { |  | ||||||
|         QString jarPath = FS::PathCombine(p, jarFile); |         QString jarPath = FS::PathCombine(p, jarFile); | ||||||
|         if (QFileInfo(jarPath).isFile()) |         if (QFileInfo(jarPath).isFile()) | ||||||
|             return jarPath; |             return jarPath; | ||||||
|   | |||||||
| @@ -38,12 +38,12 @@ | |||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
| #include <QApplication> | #include <QApplication> | ||||||
| #include <memory> | #include <QDateTime> | ||||||
| #include <QDebug> | #include <QDebug> | ||||||
| #include <QFlag> | #include <QFlag> | ||||||
| #include <QIcon> | #include <QIcon> | ||||||
| #include <QDateTime> |  | ||||||
| #include <QUrl> | #include <QUrl> | ||||||
|  | #include <memory> | ||||||
|  |  | ||||||
| #include <BaseInstance.h> | #include <BaseInstance.h> | ||||||
|  |  | ||||||
| @@ -82,17 +82,11 @@ namespace Meta { | |||||||
| #endif | #endif | ||||||
| #define APPLICATION (static_cast<Application*>(QCoreApplication::instance())) | #define APPLICATION (static_cast<Application*>(QCoreApplication::instance())) | ||||||
|  |  | ||||||
| class Application : public QApplication | class Application : public QApplication { | ||||||
| { |  | ||||||
|     // friends for the purpose of limiting access to deprecated stuff |     // friends for the purpose of limiting access to deprecated stuff | ||||||
|     Q_OBJECT |     Q_OBJECT | ||||||
|    public: |    public: | ||||||
|     enum Status { |     enum Status { StartingUp, Failed, Succeeded, Initialized }; | ||||||
|         StartingUp, |  | ||||||
|         Failed, |  | ||||||
|         Succeeded, |  | ||||||
|         Initialized |  | ||||||
|     }; |  | ||||||
|  |  | ||||||
|     enum Capability { |     enum Capability { | ||||||
|         None = 0, |         None = 0, | ||||||
| @@ -110,13 +104,9 @@ public: | |||||||
|  |  | ||||||
|     bool event(QEvent* event) override; |     bool event(QEvent* event) override; | ||||||
|  |  | ||||||
|     std::shared_ptr<SettingsObject> settings() const { |     std::shared_ptr<SettingsObject> settings() const { return m_settings; } | ||||||
|         return m_settings; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     qint64 timeSinceStart() const { |     qint64 timeSinceStart() const { return startTime.msecsTo(QDateTime::currentDateTime()); } | ||||||
|         return startTime.msecsTo(QDateTime::currentDateTime()); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     QIcon getThemedIcon(const QString& name); |     QIcon getThemedIcon(const QString& name); | ||||||
|  |  | ||||||
| @@ -130,29 +120,17 @@ public: | |||||||
|  |  | ||||||
|     std::shared_ptr<JavaInstallList> javalist(); |     std::shared_ptr<JavaInstallList> javalist(); | ||||||
|  |  | ||||||
|     std::shared_ptr<InstanceList> instances() const { |     std::shared_ptr<InstanceList> instances() const { return m_instances; } | ||||||
|         return m_instances; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     std::shared_ptr<IconList> icons() const { |     std::shared_ptr<IconList> icons() const { return m_icons; } | ||||||
|         return m_icons; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     MCEditTool *mcedit() const { |     MCEditTool* mcedit() const { return m_mcedit.get(); } | ||||||
|         return m_mcedit.get(); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     shared_qobject_ptr<AccountList> accounts() const { |     shared_qobject_ptr<AccountList> accounts() const { return m_accounts; } | ||||||
|         return m_accounts; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     Status status() const { |     Status status() const { return m_status; } | ||||||
|         return m_status; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     const QMap<QString, std::shared_ptr<BaseProfilerFactory>> &profilers() const { |     const QMap<QString, std::shared_ptr<BaseProfilerFactory>>& profilers() const { return m_profilers; } | ||||||
|         return m_profilers; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     void updateProxySettings(QString proxyTypeStr, QString addr, int port, QString user, QString password); |     void updateProxySettings(QString proxyTypeStr, QString addr, int port, QString user, QString password); | ||||||
|  |  | ||||||
| @@ -177,17 +155,11 @@ public: | |||||||
|     QString getUserAgentUncached(); |     QString getUserAgentUncached(); | ||||||
|  |  | ||||||
|     /// this is the root of the 'installation'. Used for automatic updates |     /// this is the root of the 'installation'. Used for automatic updates | ||||||
|     const QString &root() { |     const QString& root() { return m_rootPath; } | ||||||
|         return m_rootPath; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     bool isPortable() { |     bool isPortable() { return m_portable; } | ||||||
|         return m_portable; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     const Capabilities capabilities() { |     const Capabilities capabilities() { return m_capabilities; } | ||||||
|         return m_capabilities; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /*! |     /*! | ||||||
|      * Opens a json file using either a system default editor, or, if not empty, the editor |      * Opens a json file using either a system default editor, or, if not empty, the editor | ||||||
| @@ -216,14 +188,12 @@ signals: | |||||||
| #endif | #endif | ||||||
|  |  | ||||||
|    public slots: |    public slots: | ||||||
|     bool launch( |     bool launch(InstancePtr instance, | ||||||
|         InstancePtr instance, |  | ||||||
|                 bool online = true, |                 bool online = true, | ||||||
|                 bool demo = false, |                 bool demo = false, | ||||||
|                 BaseProfilerFactory* profiler = nullptr, |                 BaseProfilerFactory* profiler = nullptr, | ||||||
|                 MinecraftServerTargetPtr serverToJoin = nullptr, |                 MinecraftServerTargetPtr serverToJoin = nullptr, | ||||||
|         MinecraftAccountPtr accountToUse = nullptr |                 MinecraftAccountPtr accountToUse = nullptr); | ||||||
|     ); |  | ||||||
|     bool kill(InstancePtr instance); |     bool kill(InstancePtr instance); | ||||||
|     void closeCurrentWindow(); |     void closeCurrentWindow(); | ||||||
|  |  | ||||||
| @@ -303,6 +273,7 @@ private: | |||||||
|     LocalPeer* m_peerInstance = nullptr; |     LocalPeer* m_peerInstance = nullptr; | ||||||
|  |  | ||||||
|     SetupWizard* m_setupWizard = nullptr; |     SetupWizard* m_setupWizard = nullptr; | ||||||
|  |  | ||||||
|    public: |    public: | ||||||
|     QString m_instanceIdToLaunch; |     QString m_instanceIdToLaunch; | ||||||
|     QString m_serverToJoin; |     QString m_serverToJoin; | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| // SPDX-License-Identifier: GPL-3.0-only | // SPDX-License-Identifier: GPL-3.0-only | ||||||
| /* | /* | ||||||
|  *  PolyMC - Minecraft Launcher |  *  Prism Launcher - Minecraft Launcher | ||||||
|  *  Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net> |  *  Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net> | ||||||
|  * |  * | ||||||
|  *  This program is free software: you can redistribute it and/or modify |  *  This program is free software: you can redistribute it and/or modify | ||||||
| @@ -39,7 +39,8 @@ | |||||||
| #include <QJsonObject> | #include <QJsonObject> | ||||||
| #include "Json.h" | #include "Json.h" | ||||||
|  |  | ||||||
| void ApplicationMessage::parse(const QByteArray & input) { | void ApplicationMessage::parse(const QByteArray& input) | ||||||
|  | { | ||||||
|     auto doc = Json::requireDocument(input, "ApplicationMessage"); |     auto doc = Json::requireDocument(input, "ApplicationMessage"); | ||||||
|     auto root = Json::requireObject(doc, "ApplicationMessage"); |     auto root = Json::requireObject(doc, "ApplicationMessage"); | ||||||
|  |  | ||||||
| @@ -52,7 +53,8 @@ void ApplicationMessage::parse(const QByteArray & input) { | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| QByteArray ApplicationMessage::serialize() { | QByteArray ApplicationMessage::serialize() | ||||||
|  | { | ||||||
|     QJsonObject root; |     QJsonObject root; | ||||||
|     root.insert("command", command); |     root.insert("command", command); | ||||||
|     QJsonObject outArgs; |     QJsonObject outArgs; | ||||||
|   | |||||||
| @@ -1,8 +1,8 @@ | |||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
| #include <QString> |  | ||||||
| #include <QHash> |  | ||||||
| #include <QByteArray> | #include <QByteArray> | ||||||
|  | #include <QHash> | ||||||
|  | #include <QString> | ||||||
|  |  | ||||||
| struct ApplicationMessage { | struct ApplicationMessage { | ||||||
|     QString command; |     QString command; | ||||||
|   | |||||||
| @@ -18,10 +18,7 @@ | |||||||
| #include "BaseInstaller.h" | #include "BaseInstaller.h" | ||||||
| #include "minecraft/MinecraftInstance.h" | #include "minecraft/MinecraftInstance.h" | ||||||
|  |  | ||||||
| BaseInstaller::BaseInstaller() | BaseInstaller::BaseInstaller() {} | ||||||
| { |  | ||||||
|  |  | ||||||
| } |  | ||||||
|  |  | ||||||
| bool BaseInstaller::isApplied(MinecraftInstance* on) | bool BaseInstaller::isApplied(MinecraftInstance* on) | ||||||
| { | { | ||||||
| @@ -30,15 +27,12 @@ bool BaseInstaller::isApplied(MinecraftInstance *on) | |||||||
|  |  | ||||||
| bool BaseInstaller::add(MinecraftInstance* to) | bool BaseInstaller::add(MinecraftInstance* to) | ||||||
| { | { | ||||||
|     if (!patchesDir(to->instanceRoot()).exists()) |     if (!patchesDir(to->instanceRoot()).exists()) { | ||||||
|     { |  | ||||||
|         QDir(to->instanceRoot()).mkdir("patches"); |         QDir(to->instanceRoot()).mkdir("patches"); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (isApplied(to)) |     if (isApplied(to)) { | ||||||
|     { |         if (!remove(to)) { | ||||||
|         if (!remove(to)) |  | ||||||
|         { |  | ||||||
|             return false; |             return false; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -26,8 +26,7 @@ class QObject; | |||||||
| class Task; | class Task; | ||||||
| class BaseVersion; | class BaseVersion; | ||||||
|  |  | ||||||
| class BaseInstaller | class BaseInstaller { | ||||||
| { |  | ||||||
|    public: |    public: | ||||||
|     BaseInstaller(); |     BaseInstaller(); | ||||||
|     virtual ~BaseInstaller(){}; |     virtual ~BaseInstaller(){}; | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| // SPDX-License-Identifier: GPL-3.0-only | // SPDX-License-Identifier: GPL-3.0-only | ||||||
| /* | /* | ||||||
|  *  PolyMC - Minecraft Launcher |  *  Prism Launcher - Minecraft Launcher | ||||||
|  *  Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net> |  *  Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net> | ||||||
|  *  Copyright (c) 2022 Jamie Mansfield <jmansfield@cadixdev.org> |  *  Copyright (c) 2022 Jamie Mansfield <jmansfield@cadixdev.org> | ||||||
|  * |  * | ||||||
| @@ -36,23 +36,22 @@ | |||||||
|  |  | ||||||
| #include "BaseInstance.h" | #include "BaseInstance.h" | ||||||
|  |  | ||||||
| #include <QFileInfo> |  | ||||||
| #include <QDir> |  | ||||||
| #include <QDebug> | #include <QDebug> | ||||||
| #include <QRegularExpression> | #include <QDir> | ||||||
|  | #include <QFileInfo> | ||||||
| #include <QJsonDocument> | #include <QJsonDocument> | ||||||
| #include <QJsonObject> | #include <QJsonObject> | ||||||
|  | #include <QRegularExpression> | ||||||
|  |  | ||||||
| #include "settings/INISettingsObject.h" | #include "settings/INISettingsObject.h" | ||||||
| #include "settings/Setting.h" |  | ||||||
| #include "settings/OverrideSetting.h" | #include "settings/OverrideSetting.h" | ||||||
|  | #include "settings/Setting.h" | ||||||
|  |  | ||||||
| #include "FileSystem.h" |  | ||||||
| #include "Commandline.h" |  | ||||||
| #include "BuildConfig.h" | #include "BuildConfig.h" | ||||||
|  | #include "Commandline.h" | ||||||
|  | #include "FileSystem.h" | ||||||
|  |  | ||||||
| BaseInstance::BaseInstance(SettingsObjectPtr globalSettings, SettingsObjectPtr settings, const QString &rootDir) | BaseInstance::BaseInstance(SettingsObjectPtr globalSettings, SettingsObjectPtr settings, const QString& rootDir) : QObject() | ||||||
|     : QObject() |  | ||||||
| { | { | ||||||
|     m_settings = settings; |     m_settings = settings; | ||||||
|     m_global_settings = globalSettings; |     m_global_settings = globalSettings; | ||||||
| @@ -148,7 +147,11 @@ QString BaseInstance::getManagedPackVersionName() const | |||||||
|     return m_settings->get("ManagedPackVersionName").toString(); |     return m_settings->get("ManagedPackVersionName").toString(); | ||||||
| } | } | ||||||
|  |  | ||||||
| void BaseInstance::setManagedPack(const QString& type, const QString& id, const QString& name, const QString& versionId, const QString& version) | void BaseInstance::setManagedPack(const QString& type, | ||||||
|  |                                   const QString& id, | ||||||
|  |                                   const QString& name, | ||||||
|  |                                   const QString& versionId, | ||||||
|  |                                   const QString& version) | ||||||
| { | { | ||||||
|     m_settings->set("ManagedPack", true); |     m_settings->set("ManagedPack", true); | ||||||
|     m_settings->set("ManagedPackType", type); |     m_settings->set("ManagedPackType", type); | ||||||
| @@ -173,8 +176,7 @@ int BaseInstance::getConsoleMaxLines() const | |||||||
|     auto lineSetting = m_settings->getSetting("ConsoleMaxLines"); |     auto lineSetting = m_settings->getSetting("ConsoleMaxLines"); | ||||||
|     bool conversionOk = false; |     bool conversionOk = false; | ||||||
|     int maxLines = lineSetting->get().toInt(&conversionOk); |     int maxLines = lineSetting->get().toInt(&conversionOk); | ||||||
|     if(!conversionOk) |     if (!conversionOk) { | ||||||
|     { |  | ||||||
|         maxLines = lineSetting->defValue().toInt(); |         maxLines = lineSetting->defValue().toInt(); | ||||||
|         qWarning() << "ConsoleMaxLines has nonsensical value, defaulting to" << maxLines; |         qWarning() << "ConsoleMaxLines has nonsensical value, defaulting to" << maxLines; | ||||||
|     } |     } | ||||||
| @@ -220,8 +222,7 @@ bool BaseInstance::isLinkedToInstanceId(const QString& id) const | |||||||
|  |  | ||||||
| void BaseInstance::iconUpdated(QString key) | void BaseInstance::iconUpdated(QString key) | ||||||
| { | { | ||||||
|     if(iconKey() == key) |     if (iconKey() == key) { | ||||||
|     { |  | ||||||
|         emit propertiesChanged(this); |         emit propertiesChanged(this); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -235,8 +236,7 @@ void BaseInstance::invalidate() | |||||||
| void BaseInstance::changeStatus(BaseInstance::Status newStatus) | void BaseInstance::changeStatus(BaseInstance::Status newStatus) | ||||||
| { | { | ||||||
|     Status status = currentStatus(); |     Status status = currentStatus(); | ||||||
|     if(status != newStatus) |     if (status != newStatus) { | ||||||
|     { |  | ||||||
|         m_status = newStatus; |         m_status = newStatus; | ||||||
|         emit statusChanged(status, newStatus); |         emit statusChanged(status, newStatus); | ||||||
|     } |     } | ||||||
| @@ -264,18 +264,14 @@ void BaseInstance::setRunning(bool running) | |||||||
|  |  | ||||||
|     m_isRunning = running; |     m_isRunning = running; | ||||||
|  |  | ||||||
|     if(!m_settings->get("RecordGameTime").toBool()) |     if (!m_settings->get("RecordGameTime").toBool()) { | ||||||
|     { |  | ||||||
|         emit runningStatusChanged(running); |         emit runningStatusChanged(running); | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if(running) |     if (running) { | ||||||
|     { |  | ||||||
|         m_timeStarted = QDateTime::currentDateTime(); |         m_timeStarted = QDateTime::currentDateTime(); | ||||||
|     } |     } else { | ||||||
|     else |  | ||||||
|     { |  | ||||||
|         QDateTime timeEnded = QDateTime::currentDateTime(); |         QDateTime timeEnded = QDateTime::currentDateTime(); | ||||||
|  |  | ||||||
|         qint64 current = settings()->get("totalTimePlayed").toLongLong(); |         qint64 current = settings()->get("totalTimePlayed").toLongLong(); | ||||||
| @@ -291,8 +287,7 @@ void BaseInstance::setRunning(bool running) | |||||||
| int64_t BaseInstance::totalTimePlayed() const | int64_t BaseInstance::totalTimePlayed() const | ||||||
| { | { | ||||||
|     qint64 current = m_settings->get("totalTimePlayed").toLongLong(); |     qint64 current = m_settings->get("totalTimePlayed").toLongLong(); | ||||||
|     if(m_isRunning) |     if (m_isRunning) { | ||||||
|     { |  | ||||||
|         QDateTime timeNow = QDateTime::currentDateTime(); |         QDateTime timeNow = QDateTime::currentDateTime(); | ||||||
|         return current + m_timeStarted.secsTo(timeNow); |         return current + m_timeStarted.secsTo(timeNow); | ||||||
|     } |     } | ||||||
| @@ -301,8 +296,7 @@ int64_t BaseInstance::totalTimePlayed() const | |||||||
|  |  | ||||||
| int64_t BaseInstance::lastTimePlayed() const | int64_t BaseInstance::lastTimePlayed() const | ||||||
| { | { | ||||||
|     if(m_isRunning) |     if (m_isRunning) { | ||||||
|     { |  | ||||||
|         QDateTime timeNow = QDateTime::currentDateTime(); |         QDateTime timeNow = QDateTime::currentDateTime(); | ||||||
|         return m_timeStarted.secsTo(timeNow); |         return m_timeStarted.secsTo(timeNow); | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| // SPDX-License-Identifier: GPL-3.0-only | // SPDX-License-Identifier: GPL-3.0-only | ||||||
| /* | /* | ||||||
|  *  PolyMC - Minecraft Launcher |  *  Prism Launcher - Minecraft Launcher | ||||||
|  *  Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net> |  *  Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net> | ||||||
|  *  Copyright (c) 2022 Jamie Mansfield <jmansfield@cadixdev.org> |  *  Copyright (c) 2022 Jamie Mansfield <jmansfield@cadixdev.org> | ||||||
|  * |  * | ||||||
| @@ -37,24 +37,24 @@ | |||||||
| #pragma once | #pragma once | ||||||
| #include <cassert> | #include <cassert> | ||||||
|  |  | ||||||
| #include <QObject> |  | ||||||
| #include "QObjectPtr.h" |  | ||||||
| #include <QDateTime> | #include <QDateTime> | ||||||
| #include <QSet> | #include <QObject> | ||||||
| #include <QProcess> | #include <QProcess> | ||||||
|  | #include <QSet> | ||||||
|  | #include "QObjectPtr.h" | ||||||
|  |  | ||||||
| #include "settings/SettingsObject.h" | #include "settings/SettingsObject.h" | ||||||
|  |  | ||||||
| #include "settings/INIFile.h" |  | ||||||
| #include "BaseVersionList.h" | #include "BaseVersionList.h" | ||||||
| #include "minecraft/auth/MinecraftAccount.h" |  | ||||||
| #include "MessageLevel.h" | #include "MessageLevel.h" | ||||||
|  | #include "minecraft/auth/MinecraftAccount.h" | ||||||
| #include "pathmatcher/IPathMatcher.h" | #include "pathmatcher/IPathMatcher.h" | ||||||
|  | #include "settings/INIFile.h" | ||||||
|  |  | ||||||
| #include "net/Mode.h" | #include "net/Mode.h" | ||||||
|  |  | ||||||
| #include "minecraft/launch/MinecraftServerTarget.h" |  | ||||||
| #include "RuntimeContext.h" | #include "RuntimeContext.h" | ||||||
|  | #include "minecraft/launch/MinecraftServerTarget.h" | ||||||
|  |  | ||||||
| class QDir; | class QDir; | ||||||
| class Task; | class Task; | ||||||
| @@ -72,16 +72,14 @@ typedef std::shared_ptr<BaseInstance> InstancePtr; | |||||||
|  * To create a new instance type, create a new class inheriting from this class |  * To create a new instance type, create a new class inheriting from this class | ||||||
|  * and implement the pure virtual functions. |  * and implement the pure virtual functions. | ||||||
|  */ |  */ | ||||||
| class BaseInstance : public QObject, public std::enable_shared_from_this<BaseInstance> | class BaseInstance : public QObject, public std::enable_shared_from_this<BaseInstance> { | ||||||
| { |  | ||||||
|     Q_OBJECT |     Q_OBJECT | ||||||
|    protected: |    protected: | ||||||
|     /// no-touchy! |     /// no-touchy! | ||||||
|     BaseInstance(SettingsObjectPtr globalSettings, SettingsObjectPtr settings, const QString& rootDir); |     BaseInstance(SettingsObjectPtr globalSettings, SettingsObjectPtr settings, const QString& rootDir); | ||||||
|  |  | ||||||
|    public: /* types */ |    public: /* types */ | ||||||
|     enum class Status |     enum class Status { | ||||||
|     { |  | ||||||
|         Present, |         Present, | ||||||
|         Gone  // either nuked or invalidated |         Gone  // either nuked or invalidated | ||||||
|     }; |     }; | ||||||
| @@ -117,10 +115,7 @@ public: | |||||||
|     QString instanceRoot() const; |     QString instanceRoot() const; | ||||||
|  |  | ||||||
|     /// Path to the instance's game root directory. |     /// Path to the instance's game root directory. | ||||||
|     virtual QString gameRoot() const |     virtual QString gameRoot() const { return instanceRoot(); } | ||||||
|     { |  | ||||||
|         return instanceRoot(); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /// Path to the instance's mods directory. |     /// Path to the instance's mods directory. | ||||||
|     virtual QString modsRoot() const = 0; |     virtual QString modsRoot() const = 0; | ||||||
| @@ -151,10 +146,7 @@ public: | |||||||
|     void copyManagedPack(BaseInstance& other); |     void copyManagedPack(BaseInstance& other); | ||||||
|  |  | ||||||
|     /// guess log level from a line of game log |     /// guess log level from a line of game log | ||||||
|     virtual MessageLevel::Enum guessLevel([[maybe_unused]] const QString &line, MessageLevel::Enum level) |     virtual MessageLevel::Enum guessLevel([[maybe_unused]] const QString& line, MessageLevel::Enum level) { return level; }; | ||||||
|     { |  | ||||||
|         return level; |  | ||||||
|     }; |  | ||||||
|  |  | ||||||
|     virtual QStringList extraArguments(); |     virtual QStringList extraArguments(); | ||||||
|  |  | ||||||
| @@ -189,8 +181,7 @@ public: | |||||||
|     virtual Task::Ptr createUpdateTask(Net::Mode mode) = 0; |     virtual Task::Ptr createUpdateTask(Net::Mode mode) = 0; | ||||||
|  |  | ||||||
|     /// returns a valid launcher (task container) |     /// returns a valid launcher (task container) | ||||||
|     virtual shared_qobject_ptr<LaunchTask> createLaunchTask( |     virtual shared_qobject_ptr<LaunchTask> createLaunchTask(AuthSessionPtr account, MinecraftServerTargetPtr serverToJoin) = 0; | ||||||
|             AuthSessionPtr account, MinecraftServerTargetPtr serverToJoin) = 0; |  | ||||||
|  |  | ||||||
|     /// returns the current launch task (if any) |     /// returns the current launch task (if any) | ||||||
|     shared_qobject_ptr<LaunchTask> getLaunchTask(); |     shared_qobject_ptr<LaunchTask> getLaunchTask(); | ||||||
| @@ -222,45 +213,30 @@ public: | |||||||
|     virtual QString typeName() const = 0; |     virtual QString typeName() const = 0; | ||||||
|  |  | ||||||
|     void updateRuntimeContext(); |     void updateRuntimeContext(); | ||||||
|     RuntimeContext runtimeContext() const |     RuntimeContext runtimeContext() const { return m_runtimeContext; } | ||||||
|     { |  | ||||||
|         return m_runtimeContext; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     bool hasVersionBroken() const |     bool hasVersionBroken() const { return m_hasBrokenVersion; } | ||||||
|     { |  | ||||||
|         return m_hasBrokenVersion; |  | ||||||
|     } |  | ||||||
|     void setVersionBroken(bool value) |     void setVersionBroken(bool value) | ||||||
|     { |     { | ||||||
|         if(m_hasBrokenVersion != value) |         if (m_hasBrokenVersion != value) { | ||||||
|         { |  | ||||||
|             m_hasBrokenVersion = value; |             m_hasBrokenVersion = value; | ||||||
|             emit propertiesChanged(this); |             emit propertiesChanged(this); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     bool hasUpdateAvailable() const |     bool hasUpdateAvailable() const { return m_hasUpdate; } | ||||||
|     { |  | ||||||
|         return m_hasUpdate; |  | ||||||
|     } |  | ||||||
|     void setUpdateAvailable(bool value) |     void setUpdateAvailable(bool value) | ||||||
|     { |     { | ||||||
|         if(m_hasUpdate != value) |         if (m_hasUpdate != value) { | ||||||
|         { |  | ||||||
|             m_hasUpdate = value; |             m_hasUpdate = value; | ||||||
|             emit propertiesChanged(this); |             emit propertiesChanged(this); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     bool hasCrashed() const |     bool hasCrashed() const { return m_crashed; } | ||||||
|     { |  | ||||||
|         return m_crashed; |  | ||||||
|     } |  | ||||||
|     void setCrashed(bool value) |     void setCrashed(bool value) | ||||||
|     { |     { | ||||||
|         if(m_crashed != value) |         if (m_crashed != value) { | ||||||
|         { |  | ||||||
|             m_crashed = value; |             m_crashed = value; | ||||||
|             emit propertiesChanged(this); |             emit propertiesChanged(this); | ||||||
|         } |         } | ||||||
| @@ -328,7 +304,6 @@ private: /* data */ | |||||||
|  |  | ||||||
|     SettingsObjectWeakPtr m_global_settings; |     SettingsObjectWeakPtr m_global_settings; | ||||||
|     bool m_specific_settings_loaded = false; |     bool m_specific_settings_loaded = false; | ||||||
|  |  | ||||||
| }; | }; | ||||||
|  |  | ||||||
| Q_DECLARE_METATYPE(shared_qobject_ptr<BaseInstance>) | Q_DECLARE_METATYPE(shared_qobject_ptr<BaseInstance>) | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| // SPDX-License-Identifier: GPL-3.0-only | // SPDX-License-Identifier: GPL-3.0-only | ||||||
| /* | /* | ||||||
|  *  PolyMC - Minecraft Launcher |  *  Prism Launcher - Minecraft Launcher | ||||||
|  *  Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net> |  *  Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net> | ||||||
|  * |  * | ||||||
|  *  This program is free software: you can redistribute it and/or modify |  *  This program is free software: you can redistribute it and/or modify | ||||||
| @@ -36,14 +36,11 @@ | |||||||
| #include "BaseVersionList.h" | #include "BaseVersionList.h" | ||||||
| #include "BaseVersion.h" | #include "BaseVersion.h" | ||||||
|  |  | ||||||
| BaseVersionList::BaseVersionList(QObject *parent) : QAbstractListModel(parent) | BaseVersionList::BaseVersionList(QObject* parent) : QAbstractListModel(parent) {} | ||||||
| { |  | ||||||
| } |  | ||||||
|  |  | ||||||
| BaseVersion::Ptr BaseVersionList::findVersion(const QString& descriptor) | BaseVersion::Ptr BaseVersionList::findVersion(const QString& descriptor) | ||||||
| { | { | ||||||
|     for (int i = 0; i < count(); i++) |     for (int i = 0; i < count(); i++) { | ||||||
|     { |  | ||||||
|         if (at(i)->descriptor() == descriptor) |         if (at(i)->descriptor() == descriptor) | ||||||
|             return at(i); |             return at(i); | ||||||
|     } |     } | ||||||
| @@ -68,8 +65,7 @@ QVariant BaseVersionList::data(const QModelIndex &index, int role) const | |||||||
|  |  | ||||||
|     BaseVersion::Ptr version = at(index.row()); |     BaseVersion::Ptr version = at(index.row()); | ||||||
|  |  | ||||||
|     switch (role) |     switch (role) { | ||||||
|     { |  | ||||||
|         case VersionPointerRole: |         case VersionPointerRole: | ||||||
|             return QVariant::fromValue(version); |             return QVariant::fromValue(version); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -15,13 +15,13 @@ | |||||||
|  |  | ||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
|  | #include <QAbstractListModel> | ||||||
| #include <QObject> | #include <QObject> | ||||||
| #include <QVariant> | #include <QVariant> | ||||||
| #include <QAbstractListModel> |  | ||||||
|  |  | ||||||
| #include "BaseVersion.h" | #include "BaseVersion.h" | ||||||
| #include "tasks/Task.h" |  | ||||||
| #include "QObjectPtr.h" | #include "QObjectPtr.h" | ||||||
|  | #include "tasks/Task.h" | ||||||
|  |  | ||||||
| /*! | /*! | ||||||
|  * \brief Class that each instance type's version list derives from. |  * \brief Class that each instance type's version list derives from. | ||||||
| @@ -35,12 +35,10 @@ | |||||||
|  * all have a default implementation, but they can be overridden by plugins to |  * all have a default implementation, but they can be overridden by plugins to | ||||||
|  * change the behavior of the list. |  * change the behavior of the list. | ||||||
|  */ |  */ | ||||||
| class BaseVersionList : public QAbstractListModel | class BaseVersionList : public QAbstractListModel { | ||||||
| { |  | ||||||
|     Q_OBJECT |     Q_OBJECT | ||||||
|    public: |    public: | ||||||
|     enum ModelRoles |     enum ModelRoles { | ||||||
|     { |  | ||||||
|         VersionPointerRole = Qt::UserRole, |         VersionPointerRole = Qt::UserRole, | ||||||
|         VersionRole, |         VersionRole, | ||||||
|         VersionIdRole, |         VersionIdRole, | ||||||
| @@ -103,8 +101,7 @@ public: | |||||||
|      */ |      */ | ||||||
|     virtual void sortVersions() = 0; |     virtual void sortVersions() = 0; | ||||||
|  |  | ||||||
| protected |    protected slots: | ||||||
| slots: |  | ||||||
|     /*! |     /*! | ||||||
|      * Updates this list with the given list of versions. |      * Updates this list with the given list of versions. | ||||||
|      * This is done by copying each version in the given list and inserting it |      * This is done by copying each version in the given list and inserting it | ||||||
|   | |||||||
| @@ -262,8 +262,6 @@ set(MINECRAFT_SOURCES | |||||||
|     minecraft/launch/CreateGameFolders.h |     minecraft/launch/CreateGameFolders.h | ||||||
|     minecraft/launch/ModMinecraftJar.cpp |     minecraft/launch/ModMinecraftJar.cpp | ||||||
|     minecraft/launch/ModMinecraftJar.h |     minecraft/launch/ModMinecraftJar.h | ||||||
|     minecraft/launch/DirectJavaLaunch.cpp |  | ||||||
|     minecraft/launch/DirectJavaLaunch.h |  | ||||||
|     minecraft/launch/ExtractNatives.cpp |     minecraft/launch/ExtractNatives.cpp | ||||||
|     minecraft/launch/ExtractNatives.h |     minecraft/launch/ExtractNatives.h | ||||||
|     minecraft/launch/LauncherPartLaunch.cpp |     minecraft/launch/LauncherPartLaunch.cpp | ||||||
| @@ -501,6 +499,11 @@ set(FTB_SOURCES | |||||||
|     modplatform/legacy_ftb/PrivatePackManager.cpp |     modplatform/legacy_ftb/PrivatePackManager.cpp | ||||||
|  |  | ||||||
|     modplatform/legacy_ftb/PackHelpers.h |     modplatform/legacy_ftb/PackHelpers.h | ||||||
|  |  | ||||||
|  |     modplatform/import_ftb/PackInstallTask.h | ||||||
|  |     modplatform/import_ftb/PackInstallTask.cpp | ||||||
|  |     modplatform/import_ftb/PackHelpers.h | ||||||
|  |     modplatform/import_ftb/PackHelpers.cpp | ||||||
| ) | ) | ||||||
|  |  | ||||||
| set(FLAME_SOURCES | set(FLAME_SOURCES | ||||||
| @@ -668,7 +671,7 @@ set(LOGIC_SOURCES | |||||||
|     ${ATLAUNCHER_SOURCES} |     ${ATLAUNCHER_SOURCES} | ||||||
| ) | ) | ||||||
|  |  | ||||||
| if(APPLE) | if(APPLE AND Launcher_ENABLE_UPDATER) | ||||||
|     set (LOGIC_SOURCES ${LOGIC_SOURCES} ${MAC_UPDATE_SOURCES}) |     set (LOGIC_SOURCES ${LOGIC_SOURCES} ${MAC_UPDATE_SOURCES}) | ||||||
| endif() | endif() | ||||||
|  |  | ||||||
| @@ -874,6 +877,11 @@ SET(LAUNCHER_SOURCES | |||||||
|     ui/pages/modplatform/legacy_ftb/ListModel.h |     ui/pages/modplatform/legacy_ftb/ListModel.h | ||||||
|     ui/pages/modplatform/legacy_ftb/ListModel.cpp |     ui/pages/modplatform/legacy_ftb/ListModel.cpp | ||||||
|  |  | ||||||
|  |     ui/pages/modplatform/import_ftb/ImportFTBPage.cpp | ||||||
|  |     ui/pages/modplatform/import_ftb/ImportFTBPage.h | ||||||
|  |     ui/pages/modplatform/import_ftb/ListModel.h | ||||||
|  |     ui/pages/modplatform/import_ftb/ListModel.cpp | ||||||
|  |  | ||||||
|     ui/pages/modplatform/flame/FlameModel.cpp |     ui/pages/modplatform/flame/FlameModel.cpp | ||||||
|     ui/pages/modplatform/flame/FlameModel.h |     ui/pages/modplatform/flame/FlameModel.h | ||||||
|     ui/pages/modplatform/flame/FlamePage.cpp |     ui/pages/modplatform/flame/FlamePage.cpp | ||||||
| @@ -1048,6 +1056,7 @@ qt_wrap_ui(LAUNCHER_UI | |||||||
|     ui/pages/modplatform/ResourcePage.ui |     ui/pages/modplatform/ResourcePage.ui | ||||||
|     ui/pages/modplatform/flame/FlamePage.ui |     ui/pages/modplatform/flame/FlamePage.ui | ||||||
|     ui/pages/modplatform/legacy_ftb/Page.ui |     ui/pages/modplatform/legacy_ftb/Page.ui | ||||||
|  |     ui/pages/modplatform/import_ftb/ImportFTBPage.ui | ||||||
|     ui/pages/modplatform/ImportPage.ui |     ui/pages/modplatform/ImportPage.ui | ||||||
|     ui/pages/modplatform/modrinth/ModrinthPage.ui |     ui/pages/modplatform/modrinth/ModrinthPage.ui | ||||||
|     ui/pages/modplatform/technic/TechnicPage.ui |     ui/pages/modplatform/technic/TechnicPage.ui | ||||||
| @@ -1143,18 +1152,24 @@ if(APPLE) | |||||||
|     set(CMAKE_MACOSX_RPATH 1) |     set(CMAKE_MACOSX_RPATH 1) | ||||||
|     set(CMAKE_INSTALL_RPATH "@loader_path/../Frameworks/") |     set(CMAKE_INSTALL_RPATH "@loader_path/../Frameworks/") | ||||||
|  |  | ||||||
|  |     if(Launcher_ENABLE_UPDATER) | ||||||
|       file(DOWNLOAD ${MACOSX_SPARKLE_DOWNLOAD_URL} ${CMAKE_BINARY_DIR}/Sparkle.tar.xz EXPECTED_HASH SHA256=${MACOSX_SPARKLE_SHA256}) |       file(DOWNLOAD ${MACOSX_SPARKLE_DOWNLOAD_URL} ${CMAKE_BINARY_DIR}/Sparkle.tar.xz EXPECTED_HASH SHA256=${MACOSX_SPARKLE_SHA256}) | ||||||
|       file(ARCHIVE_EXTRACT INPUT ${CMAKE_BINARY_DIR}/Sparkle.tar.xz DESTINATION ${CMAKE_BINARY_DIR}/frameworks/Sparkle) |       file(ARCHIVE_EXTRACT INPUT ${CMAKE_BINARY_DIR}/Sparkle.tar.xz DESTINATION ${CMAKE_BINARY_DIR}/frameworks/Sparkle) | ||||||
|  |  | ||||||
|       find_library(SPARKLE_FRAMEWORK Sparkle "${CMAKE_BINARY_DIR}/frameworks/Sparkle") |       find_library(SPARKLE_FRAMEWORK Sparkle "${CMAKE_BINARY_DIR}/frameworks/Sparkle") | ||||||
|  |       add_compile_definitions(SPARKLE_ENABLED) | ||||||
|  |     endif() | ||||||
|  |  | ||||||
|     target_link_libraries(Launcher_logic |     target_link_libraries(Launcher_logic | ||||||
|         "-framework AppKit" |         "-framework AppKit" | ||||||
|         "-framework Carbon" |         "-framework Carbon" | ||||||
|         "-framework Foundation" |         "-framework Foundation" | ||||||
|         "-framework ApplicationServices" |         "-framework ApplicationServices" | ||||||
|     ) |     ) | ||||||
|  |     if(Launcher_ENABLE_UPDATER) | ||||||
|       target_link_libraries(Launcher_logic ${SPARKLE_FRAMEWORK}) |       target_link_libraries(Launcher_logic ${SPARKLE_FRAMEWORK}) | ||||||
|     endif() |     endif() | ||||||
|  | endif() | ||||||
|  |  | ||||||
| target_link_libraries(Launcher_logic) | target_link_libraries(Launcher_logic) | ||||||
|  |  | ||||||
| @@ -1215,7 +1230,7 @@ if(WIN32) | |||||||
|     ) |     ) | ||||||
| endif() | endif() | ||||||
|  |  | ||||||
| if (UNIX AND APPLE) | if (UNIX AND APPLE AND Launcher_ENABLE_UPDATER) | ||||||
|     # Add Sparkle updater |     # Add Sparkle updater | ||||||
|     # It has to be copied here instead of just allowing fixup_bundle to install it, otherwise essential parts of |     # It has to be copied here instead of just allowing fixup_bundle to install it, otherwise essential parts of | ||||||
|     # the framework aren't installed |     # the framework aren't installed | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| // SPDX-License-Identifier: GPL-3.0-only | // SPDX-License-Identifier: GPL-3.0-only | ||||||
| /* | /* | ||||||
|  *  PolyMC - Minecraft Launcher |  *  Prism Launcher - Minecraft Launcher | ||||||
|  *  Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net> |  *  Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net> | ||||||
|  * |  * | ||||||
|  *  This program is free software: you can redistribute it and/or modify |  *  This program is free software: you can redistribute it and/or modify | ||||||
| @@ -41,8 +41,7 @@ | |||||||
|  * @file libutil/src/cmdutils.cpp |  * @file libutil/src/cmdutils.cpp | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| namespace Commandline | namespace Commandline { | ||||||
| { |  | ||||||
|  |  | ||||||
| // commandline splitter | // commandline splitter | ||||||
| QStringList splitArgs(QString args) | QStringList splitArgs(QString args) | ||||||
| @@ -51,19 +50,15 @@ QStringList splitArgs(QString args) | |||||||
|     QString current; |     QString current; | ||||||
|     bool escape = false; |     bool escape = false; | ||||||
|     QChar inquotes; |     QChar inquotes; | ||||||
|     for (int i = 0; i < args.length(); i++) |     for (int i = 0; i < args.length(); i++) { | ||||||
|     { |  | ||||||
|         QChar cchar = args.at(i); |         QChar cchar = args.at(i); | ||||||
|  |  | ||||||
|         // \ escaped |         // \ escaped | ||||||
|         if (escape) |         if (escape) { | ||||||
|         { |  | ||||||
|             current += cchar; |             current += cchar; | ||||||
|             escape = false; |             escape = false; | ||||||
|             // in "quotes" |             // in "quotes" | ||||||
|         } |         } else if (!inquotes.isNull()) { | ||||||
|         else if (!inquotes.isNull()) |  | ||||||
|         { |  | ||||||
|             if (cchar == '\\') |             if (cchar == '\\') | ||||||
|                 escape = true; |                 escape = true; | ||||||
|             else if (cchar == inquotes) |             else if (cchar == inquotes) | ||||||
| @@ -71,18 +66,13 @@ QStringList splitArgs(QString args) | |||||||
|             else |             else | ||||||
|                 current += cchar; |                 current += cchar; | ||||||
|             // otherwise |             // otherwise | ||||||
|         } |         } else { | ||||||
|         else |             if (cchar == ' ') { | ||||||
|         { |                 if (!current.isEmpty()) { | ||||||
|             if (cchar == ' ') |  | ||||||
|             { |  | ||||||
|                 if (!current.isEmpty()) |  | ||||||
|                 { |  | ||||||
|                     argv << current; |                     argv << current; | ||||||
|                     current.clear(); |                     current.clear(); | ||||||
|                 } |                 } | ||||||
|             } |             } else if (cchar == '"' || cchar == '\'') | ||||||
|             else if (cchar == '"' || cchar == '\'') |  | ||||||
|                 inquotes = cchar; |                 inquotes = cchar; | ||||||
|             else |             else | ||||||
|                 current += cchar; |                 current += cchar; | ||||||
| @@ -92,4 +82,4 @@ QStringList splitArgs(QString args) | |||||||
|         argv << current; |         argv << current; | ||||||
|     return argv; |     return argv; | ||||||
| } | } | ||||||
| } | }  // namespace Commandline | ||||||
|   | |||||||
| @@ -25,8 +25,7 @@ | |||||||
|  * @brief commandline parsing and processing utilities |  * @brief commandline parsing and processing utilities | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| namespace Commandline | namespace Commandline { | ||||||
| { |  | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * @brief split a string into argv items like a shell would do |  * @brief split a string into argv items like a shell would do | ||||||
| @@ -34,4 +33,4 @@ namespace Commandline | |||||||
|  * @return a QStringList containing all arguments |  * @return a QStringList containing all arguments | ||||||
|  */ |  */ | ||||||
| QStringList splitArgs(QString args); | QStringList splitArgs(QString args); | ||||||
| } | }  // namespace Commandline | ||||||
|   | |||||||
| @@ -1,13 +1,9 @@ | |||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
| template <typename T> | template <typename T> | ||||||
| class DefaultVariable | class DefaultVariable { | ||||||
| { |  | ||||||
|    public: |    public: | ||||||
|     DefaultVariable(const T & value) |     DefaultVariable(const T& value) { defaultValue = value; } | ||||||
|     { |  | ||||||
|         defaultValue = value; |  | ||||||
|     } |  | ||||||
|     DefaultVariable<T>& operator=(const T& value) |     DefaultVariable<T>& operator=(const T& value) | ||||||
|     { |     { | ||||||
|         currentValue = value; |         currentValue = value; | ||||||
| @@ -15,18 +11,10 @@ public: | |||||||
|         is_explicit = true; |         is_explicit = true; | ||||||
|         return *this; |         return *this; | ||||||
|     } |     } | ||||||
|     operator const T &() const |     operator const T&() const { return is_default ? defaultValue : currentValue; } | ||||||
|     { |     bool isDefault() const { return is_default; } | ||||||
|         return is_default ? defaultValue : currentValue; |     bool isExplicit() const { return is_explicit; } | ||||||
|     } |  | ||||||
|     bool isDefault() const |  | ||||||
|     { |  | ||||||
|         return is_default; |  | ||||||
|     } |  | ||||||
|     bool isExplicit() const |  | ||||||
|     { |  | ||||||
|         return is_explicit; |  | ||||||
|     } |  | ||||||
|    private: |    private: | ||||||
|     T currentValue; |     T currentValue; | ||||||
|     T defaultValue; |     T defaultValue; | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| // SPDX-License-Identifier: GPL-3.0-only | // SPDX-License-Identifier: GPL-3.0-only | ||||||
| /* | /* | ||||||
|  *  PolyMC - Minecraft Launcher |  *  Prism Launcher - Minecraft Launcher | ||||||
|  *  Copyright (C) 2022 dada513 <dada513@protonmail.com> |  *  Copyright (C) 2022 dada513 <dada513@protonmail.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 | ||||||
| @@ -33,40 +33,37 @@ | |||||||
|  *      limitations under the License. |  *      limitations under the License. | ||||||
|  */ |  */ | ||||||
| #include "DesktopServices.h" | #include "DesktopServices.h" | ||||||
| #include <QDir> |  | ||||||
| #include <QDesktopServices> |  | ||||||
| #include <QProcess> |  | ||||||
| #include <QDebug> | #include <QDebug> | ||||||
|  | #include <QDesktopServices> | ||||||
|  | #include <QDir> | ||||||
|  | #include <QProcess> | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * This shouldn't exist, but until QTBUG-9328 and other unreported bugs are fixed, it needs to be a thing. |  * This shouldn't exist, but until QTBUG-9328 and other unreported bugs are fixed, it needs to be a thing. | ||||||
|  */ |  */ | ||||||
| #if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) | #if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) | ||||||
|  |  | ||||||
| #include <unistd.h> |  | ||||||
| #include <errno.h> | #include <errno.h> | ||||||
| #include <sys/types.h> | #include <sys/types.h> | ||||||
| #include <sys/wait.h> | #include <sys/wait.h> | ||||||
|  | #include <unistd.h> | ||||||
|  |  | ||||||
| template <typename T> | template <typename T> | ||||||
| bool IndirectOpen(T callable, qint64* pid_forked = nullptr) | bool IndirectOpen(T callable, qint64* pid_forked = nullptr) | ||||||
| { | { | ||||||
|     auto pid = fork(); |     auto pid = fork(); | ||||||
|     if(pid_forked) |     if (pid_forked) { | ||||||
|     { |  | ||||||
|         if (pid > 0) |         if (pid > 0) | ||||||
|             *pid_forked = pid; |             *pid_forked = pid; | ||||||
|         else |         else | ||||||
|             *pid_forked = 0; |             *pid_forked = 0; | ||||||
|     } |     } | ||||||
|     if(pid == -1) |     if (pid == -1) { | ||||||
|     { |  | ||||||
|         qWarning() << "IndirectOpen failed to fork: " << errno; |         qWarning() << "IndirectOpen failed to fork: " << errno; | ||||||
|         return false; |         return false; | ||||||
|     } |     } | ||||||
|     // child - do the stuff |     // child - do the stuff | ||||||
|     if(pid == 0) |     if (pid == 0) { | ||||||
|     { |  | ||||||
|         // unset all this garbage so it doesn't get passed to the child process |         // unset all this garbage so it doesn't get passed to the child process | ||||||
|         qunsetenv("LD_PRELOAD"); |         qunsetenv("LD_PRELOAD"); | ||||||
|         qunsetenv("LD_LIBRARY_PATH"); |         qunsetenv("LD_LIBRARY_PATH"); | ||||||
| @@ -82,19 +79,14 @@ bool IndirectOpen(T callable, qint64 *pid_forked = nullptr) | |||||||
|  |  | ||||||
|         // die. now. do not clean up anything, it would just hang forever. |         // die. now. do not clean up anything, it would just hang forever. | ||||||
|         _exit(status ? 0 : 1); |         _exit(status ? 0 : 1); | ||||||
|     } |     } else { | ||||||
|     else |  | ||||||
|     { |  | ||||||
|         // parent - assume it worked. |         // parent - assume it worked. | ||||||
|         int status; |         int status; | ||||||
|         while (waitpid(pid, &status, 0)) |         while (waitpid(pid, &status, 0)) { | ||||||
|         { |             if (WIFEXITED(status)) { | ||||||
|             if(WIFEXITED(status)) |  | ||||||
|             { |  | ||||||
|                 return WEXITSTATUS(status) == 0; |                 return WEXITSTATUS(status) == 0; | ||||||
|             } |             } | ||||||
|             if(WIFSIGNALED(status)) |             if (WIFSIGNALED(status)) { | ||||||
|             { |  | ||||||
|                 return false; |                 return false; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| @@ -109,21 +101,14 @@ bool openDirectory(const QString &path, bool ensureExists) | |||||||
|     qDebug() << "Opening directory" << path; |     qDebug() << "Opening directory" << path; | ||||||
|     QDir parentPath; |     QDir parentPath; | ||||||
|     QDir dir(path); |     QDir dir(path); | ||||||
|     if (ensureExists && !dir.exists()) |     if (ensureExists && !dir.exists()) { | ||||||
|     { |  | ||||||
|         parentPath.mkpath(dir.absolutePath()); |         parentPath.mkpath(dir.absolutePath()); | ||||||
|     } |     } | ||||||
|     auto f = [&]() |     auto f = [&]() { return QDesktopServices::openUrl(QUrl::fromLocalFile(dir.absolutePath())); }; | ||||||
|     { |  | ||||||
|         return QDesktopServices::openUrl(QUrl::fromLocalFile(dir.absolutePath())); |  | ||||||
|     }; |  | ||||||
| #if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) | #if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) | ||||||
|     if(!isFlatpak()) |     if (!isSandbox()) { | ||||||
|     { |  | ||||||
|         return IndirectOpen(f); |         return IndirectOpen(f); | ||||||
|     } |     } else { | ||||||
|     else |  | ||||||
|     { |  | ||||||
|         return f(); |         return f(); | ||||||
|     } |     } | ||||||
| #else | #else | ||||||
| @@ -134,17 +119,11 @@ bool openDirectory(const QString &path, bool ensureExists) | |||||||
| bool openFile(const QString& path) | bool openFile(const QString& path) | ||||||
| { | { | ||||||
|     qDebug() << "Opening file" << path; |     qDebug() << "Opening file" << path; | ||||||
|     auto f = [&]() |     auto f = [&]() { return QDesktopServices::openUrl(QUrl::fromLocalFile(path)); }; | ||||||
|     { |  | ||||||
|         return QDesktopServices::openUrl(QUrl::fromLocalFile(path)); |  | ||||||
|     }; |  | ||||||
| #if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) | #if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) | ||||||
|     if(!isFlatpak()) |     if (!isSandbox()) { | ||||||
|     { |  | ||||||
|         return IndirectOpen(f); |         return IndirectOpen(f); | ||||||
|     } |     } else { | ||||||
|     else |  | ||||||
|     { |  | ||||||
|         return f(); |         return f(); | ||||||
|     } |     } | ||||||
| #else | #else | ||||||
| @@ -157,15 +136,9 @@ bool openFile(const QString &application, const QString &path, const QString &wo | |||||||
|     qDebug() << "Opening file" << path << "using" << application; |     qDebug() << "Opening file" << path << "using" << application; | ||||||
| #if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) | #if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) | ||||||
|     // FIXME: the pid here is fake. So if something depends on it, it will likely misbehave |     // FIXME: the pid here is fake. So if something depends on it, it will likely misbehave | ||||||
|     if(!isFlatpak()) |     if (!isSandbox()) { | ||||||
|     { |         return IndirectOpen([&]() { return QProcess::startDetached(application, QStringList() << path, workingDirectory); }, pid); | ||||||
|         return IndirectOpen([&]() |     } else { | ||||||
|         { |  | ||||||
|             return QProcess::startDetached(application, QStringList() << path, workingDirectory); |  | ||||||
|         }, pid); |  | ||||||
|     } |  | ||||||
|     else |  | ||||||
|     { |  | ||||||
|         return QProcess::startDetached(application, QStringList() << path, workingDirectory, pid); |         return QProcess::startDetached(application, QStringList() << path, workingDirectory, pid); | ||||||
|     } |     } | ||||||
| #else | #else | ||||||
| @@ -177,16 +150,10 @@ bool run(const QString &application, const QStringList &args, const QString &wor | |||||||
| { | { | ||||||
|     qDebug() << "Running" << application << "with args" << args.join(' '); |     qDebug() << "Running" << application << "with args" << args.join(' '); | ||||||
| #if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) | #if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) | ||||||
|     if(!isFlatpak()) |     if (!isSandbox()) { | ||||||
|     { |  | ||||||
|         // FIXME: the pid here is fake. So if something depends on it, it will likely misbehave |         // FIXME: the pid here is fake. So if something depends on it, it will likely misbehave | ||||||
|     return IndirectOpen([&]() |         return IndirectOpen([&]() { return QProcess::startDetached(application, args, workingDirectory); }, pid); | ||||||
|     { |     } else { | ||||||
|         return QProcess::startDetached(application, args, workingDirectory); |  | ||||||
|     }, pid); |  | ||||||
|     } |  | ||||||
|     else |  | ||||||
|     { |  | ||||||
|         return QProcess::startDetached(application, args, workingDirectory, pid); |         return QProcess::startDetached(application, args, workingDirectory, pid); | ||||||
|     } |     } | ||||||
| #else | #else | ||||||
| @@ -197,17 +164,11 @@ bool run(const QString &application, const QStringList &args, const QString &wor | |||||||
| bool openUrl(const QUrl& url) | bool openUrl(const QUrl& url) | ||||||
| { | { | ||||||
|     qDebug() << "Opening URL" << url.toString(); |     qDebug() << "Opening URL" << url.toString(); | ||||||
|     auto f = [&]() |     auto f = [&]() { return QDesktopServices::openUrl(url); }; | ||||||
|     { |  | ||||||
|         return QDesktopServices::openUrl(url); |  | ||||||
|     }; |  | ||||||
| #if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) | #if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) | ||||||
|     if(!isFlatpak()) |     if (!isSandbox()) { | ||||||
|     { |  | ||||||
|         return IndirectOpen(f); |         return IndirectOpen(f); | ||||||
|     } |     } else { | ||||||
|     else |  | ||||||
|     { |  | ||||||
|         return f(); |         return f(); | ||||||
|     } |     } | ||||||
| #else | #else | ||||||
| @@ -224,4 +185,18 @@ bool isFlatpak() | |||||||
| #endif | #endif | ||||||
| } | } | ||||||
|  |  | ||||||
|  | bool isSnap() | ||||||
|  | { | ||||||
|  | #ifdef Q_OS_LINUX | ||||||
|  |     return getenv("SNAP"); | ||||||
|  | #else | ||||||
|  |     return false; | ||||||
|  | #endif | ||||||
| } | } | ||||||
|  |  | ||||||
|  | bool isSandbox() | ||||||
|  | { | ||||||
|  |     return isSnap() || isFlatpak(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | }  // namespace DesktopServices | ||||||
|   | |||||||
| @@ -1,14 +1,13 @@ | |||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
| #include <QUrl> |  | ||||||
| #include <QString> | #include <QString> | ||||||
|  | #include <QUrl> | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * This wraps around QDesktopServices and adds workarounds where needed |  * This wraps around QDesktopServices and adds workarounds where needed | ||||||
|  * Use this instead of QDesktopServices! |  * Use this instead of QDesktopServices! | ||||||
|  */ |  */ | ||||||
| namespace DesktopServices | namespace DesktopServices { | ||||||
| { |  | ||||||
| /** | /** | ||||||
|  * Open a file in whatever application is applicable |  * Open a file in whatever application is applicable | ||||||
|  */ |  */ | ||||||
| @@ -34,5 +33,18 @@ namespace DesktopServices | |||||||
|  */ |  */ | ||||||
| bool openUrl(const QUrl& url); | bool openUrl(const QUrl& url); | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Determine whether the launcher is running in a Flatpak environment | ||||||
|  |  */ | ||||||
| bool isFlatpak(); | bool isFlatpak(); | ||||||
| } |  | ||||||
|  | /** | ||||||
|  |  * Determine whether the launcher is running in a Snap environment | ||||||
|  |  */ | ||||||
|  | bool isSnap(); | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Determine whether the launcher is running in a sandboxed (Flatpak or Snap) environment | ||||||
|  |  */ | ||||||
|  | bool isSandbox(); | ||||||
|  | }  // namespace DesktopServices | ||||||
|   | |||||||
| @@ -2,30 +2,17 @@ | |||||||
|  |  | ||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
| #include <QString> |  | ||||||
| #include <QDebug> | #include <QDebug> | ||||||
|  | #include <QString> | ||||||
| #include <exception> | #include <exception> | ||||||
|  |  | ||||||
| class Exception : public std::exception | class Exception : public std::exception { | ||||||
| { |  | ||||||
|    public: |    public: | ||||||
|     Exception(const QString &message) : std::exception(), m_message(message) |     Exception(const QString& message) : std::exception(), m_message(message) { qCritical() << "Exception:" << message; } | ||||||
|     { |     Exception(const Exception& other) : std::exception(), m_message(other.cause()) {} | ||||||
|         qCritical() << "Exception:" << message; |  | ||||||
|     } |  | ||||||
|     Exception(const Exception &other) |  | ||||||
|         : std::exception(), m_message(other.cause()) |  | ||||||
|     { |  | ||||||
|     } |  | ||||||
|     virtual ~Exception() noexcept {} |     virtual ~Exception() noexcept {} | ||||||
|     const char *what() const noexcept |     const char* what() const noexcept { return m_message.toLatin1().constData(); } | ||||||
|     { |     QString cause() const { return m_message; } | ||||||
|         return m_message.toLatin1().constData(); |  | ||||||
|     } |  | ||||||
|     QString cause() const |  | ||||||
|     { |  | ||||||
|         return m_message; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|    private: |    private: | ||||||
|     QString m_message; |     QString m_message; | ||||||
|   | |||||||
| @@ -4,20 +4,16 @@ | |||||||
| template <typename T> | template <typename T> | ||||||
| inline void clamp(T& current, T min, T max) | inline void clamp(T& current, T min, T max) | ||||||
| { | { | ||||||
|     if (current < min) |     if (current < min) { | ||||||
|     { |  | ||||||
|         current = min; |         current = min; | ||||||
|     } |     } else if (current > max) { | ||||||
|     else if(current > max) |  | ||||||
|     { |  | ||||||
|         current = max; |         current = max; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| // List of numbers from min to max. Next is exponent times bigger than previous. | // List of numbers from min to max. Next is exponent times bigger than previous. | ||||||
|  |  | ||||||
| class ExponentialSeries | class ExponentialSeries { | ||||||
| { |  | ||||||
|    public: |    public: | ||||||
|     ExponentialSeries(unsigned min, unsigned max, unsigned exponent = 2) |     ExponentialSeries(unsigned min, unsigned max, unsigned exponent = 2) | ||||||
|     { |     { | ||||||
| @@ -25,10 +21,7 @@ public: | |||||||
|         m_max = max; |         m_max = max; | ||||||
|         m_exponent = exponent; |         m_exponent = exponent; | ||||||
|     } |     } | ||||||
|     void reset() |     void reset() { m_current = m_min; } | ||||||
|     { |  | ||||||
|         m_current = m_min; |  | ||||||
|     } |  | ||||||
|     unsigned operator()() |     unsigned operator()() | ||||||
|     { |     { | ||||||
|         unsigned retval = m_current; |         unsigned retval = m_current; | ||||||
|   | |||||||
| @@ -779,7 +779,8 @@ bool createShortcut(QString destination, QString target, QStringList args, QStri | |||||||
|     } |     } | ||||||
| #if defined(Q_OS_MACOS) | #if defined(Q_OS_MACOS) | ||||||
|     // Create the Application |     // Create the Application | ||||||
|     QDir applicationDirectory = QStandardPaths::writableLocation(QStandardPaths::ApplicationsLocation) + "/" + BuildConfig.LAUNCHER_NAME + " Instances/"; |     QDir applicationDirectory = | ||||||
|  |         QStandardPaths::writableLocation(QStandardPaths::ApplicationsLocation) + "/" + BuildConfig.LAUNCHER_NAME + " Instances/"; | ||||||
|  |  | ||||||
|     if (!applicationDirectory.mkpath(".")) { |     if (!applicationDirectory.mkpath(".")) { | ||||||
|         qWarning() << "Couldn't create application directory"; |         qWarning() << "Couldn't create application directory"; | ||||||
| @@ -843,7 +844,9 @@ bool createShortcut(QString destination, QString target, QStringList args, QStri | |||||||
|                   "    <key>CFBundleIconFile</key>\n" |                   "    <key>CFBundleIconFile</key>\n" | ||||||
|                   "    <string>Icon.icns</string>\n" |                   "    <string>Icon.icns</string>\n" | ||||||
|                   "    <key>CFBundleName</key>\n" |                   "    <key>CFBundleName</key>\n" | ||||||
|                   "    <string>" << name << "</string>\n"  // Name of the application |                   "    <string>" | ||||||
|  |                << name | ||||||
|  |                << "</string>\n"  // Name of the application | ||||||
|                   "    <key>CFBundlePackageType</key>\n" |                   "    <key>CFBundlePackageType</key>\n" | ||||||
|                   "    <string>APPL</string>\n" |                   "    <string>APPL</string>\n" | ||||||
|                   "    <key>CFBundleShortVersionString</key>\n" |                   "    <key>CFBundleShortVersionString</key>\n" | ||||||
|   | |||||||
| @@ -43,10 +43,10 @@ | |||||||
| #include <system_error> | #include <system_error> | ||||||
|  |  | ||||||
| #include <QDir> | #include <QDir> | ||||||
| #include <QPair> |  | ||||||
| #include <QFlags> | #include <QFlags> | ||||||
| #include <QLocalServer> | #include <QLocalServer> | ||||||
| #include <QObject> | #include <QObject> | ||||||
|  | #include <QPair> | ||||||
| #include <QThread> | #include <QThread> | ||||||
|  |  | ||||||
| namespace FS { | namespace FS { | ||||||
| @@ -365,12 +365,12 @@ enum class FilesystemType { | |||||||
|  * QMap is ordered |  * QMap is ordered | ||||||
|  * |  * | ||||||
|  */ |  */ | ||||||
| static const QMap<FilesystemType, QStringList> s_filesystem_type_names = { | static const QMap<FilesystemType, QStringList> s_filesystem_type_names = { { FilesystemType::FAT, { "FAT" } }, | ||||||
|     {FilesystemType::FAT,        { "FAT" }}, |  | ||||||
|                                                                            { FilesystemType::NTFS, { "NTFS" } }, |                                                                            { FilesystemType::NTFS, { "NTFS" } }, | ||||||
|                                                                            { FilesystemType::REFS, { "REFS" } }, |                                                                            { FilesystemType::REFS, { "REFS" } }, | ||||||
|                                                                            { FilesystemType::EXT_2_OLD, { "EXT_2_OLD", "EXT2_OLD" } }, |                                                                            { FilesystemType::EXT_2_OLD, { "EXT_2_OLD", "EXT2_OLD" } }, | ||||||
|     {FilesystemType::EXT_2_3_4,  { "EXT2/3/4", "EXT_2_3_4", "EXT2", "EXT3", "EXT4" }}, |                                                                            { FilesystemType::EXT_2_3_4, | ||||||
|  |                                                                              { "EXT2/3/4", "EXT_2_3_4", "EXT2", "EXT3", "EXT4" } }, | ||||||
|                                                                            { FilesystemType::EXT, { "EXT" } }, |                                                                            { FilesystemType::EXT, { "EXT" } }, | ||||||
|                                                                            { FilesystemType::XFS, { "XFS" } }, |                                                                            { FilesystemType::XFS, { "XFS" } }, | ||||||
|                                                                            { FilesystemType::BTRFS, { "BTRFS" } }, |                                                                            { FilesystemType::BTRFS, { "BTRFS" } }, | ||||||
| @@ -382,8 +382,7 @@ static const QMap<FilesystemType, QStringList> s_filesystem_type_names = { | |||||||
|                                                                            { FilesystemType::HFSX, { "HFSX" } }, |                                                                            { FilesystemType::HFSX, { "HFSX" } }, | ||||||
|                                                                            { FilesystemType::FUSEBLK, { "FUSEBLK" } }, |                                                                            { FilesystemType::FUSEBLK, { "FUSEBLK" } }, | ||||||
|                                                                            { FilesystemType::F2FS, { "F2FS" } }, |                                                                            { FilesystemType::F2FS, { "F2FS" } }, | ||||||
|     {FilesystemType::UNKNOWN,    { "UNKNOWN" }} |                                                                            { FilesystemType::UNKNOWN, { "UNKNOWN" } } }; | ||||||
| }; |  | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * @brief Get the string name of Filesystem enum object |  * @brief Get the string name of Filesystem enum object | ||||||
|   | |||||||
| @@ -16,8 +16,7 @@ bool ExactFilter::accepts(const QString& value) | |||||||
|     return value == pattern; |     return value == pattern; | ||||||
| } | } | ||||||
|  |  | ||||||
| RegexpFilter::RegexpFilter(const QString& regexp, bool invert) | RegexpFilter::RegexpFilter(const QString& regexp, bool invert) : invert(invert) | ||||||
|     :invert(invert) |  | ||||||
| { | { | ||||||
|     pattern.setPattern(regexp); |     pattern.setPattern(regexp); | ||||||
|     pattern.optimize(); |     pattern.optimize(); | ||||||
|   | |||||||
| @@ -1,41 +1,40 @@ | |||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
| #include <QString> |  | ||||||
| #include <QRegularExpression> | #include <QRegularExpression> | ||||||
|  | #include <QString> | ||||||
|  |  | ||||||
| class Filter | class Filter { | ||||||
| { |  | ||||||
|    public: |    public: | ||||||
|     virtual ~Filter(); |     virtual ~Filter(); | ||||||
|     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(); | ||||||
|     bool accepts(const QString& value) override; |     bool accepts(const QString& value) override; | ||||||
|  |  | ||||||
|    private: |    private: | ||||||
|     QString pattern; |     QString pattern; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| class ExactFilter: public Filter | class ExactFilter : public Filter { | ||||||
| { |  | ||||||
|    public: |    public: | ||||||
|     ExactFilter(const QString& pattern); |     ExactFilter(const QString& pattern); | ||||||
|     virtual ~ExactFilter(); |     virtual ~ExactFilter(); | ||||||
|     bool accepts(const QString& value) override; |     bool accepts(const QString& value) override; | ||||||
|  |  | ||||||
|    private: |    private: | ||||||
|     QString pattern; |     QString pattern; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| 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(); | ||||||
|     bool accepts(const QString& value) override; |     bool accepts(const QString& value) override; | ||||||
|  |  | ||||||
|    private: |    private: | ||||||
|     QRegularExpression pattern; |     QRegularExpression pattern; | ||||||
|     bool invert = false; |     bool invert = false; | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| // SPDX-License-Identifier: GPL-3.0-only | // SPDX-License-Identifier: GPL-3.0-only | ||||||
| /* | /* | ||||||
|  *  PolyMC - Minecraft Launcher |  *  Prism Launcher - Minecraft Launcher | ||||||
|  *  Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net> |  *  Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net> | ||||||
|  * |  * | ||||||
|  *  This program is free software: you can redistribute it and/or modify |  *  This program is free software: you can redistribute it and/or modify | ||||||
| @@ -39,8 +39,7 @@ | |||||||
|  |  | ||||||
| bool GZip::unzip(const QByteArray& compressedBytes, QByteArray& uncompressedBytes) | bool GZip::unzip(const QByteArray& compressedBytes, QByteArray& uncompressedBytes) | ||||||
| { | { | ||||||
|     if (compressedBytes.size() == 0) |     if (compressedBytes.size() == 0) { | ||||||
|     { |  | ||||||
|         uncompressedBytes = compressedBytes; |         uncompressedBytes = compressedBytes; | ||||||
|         return true; |         return true; | ||||||
|     } |     } | ||||||
| @@ -56,18 +55,15 @@ bool GZip::unzip(const QByteArray &compressedBytes, QByteArray &uncompressedByte | |||||||
|  |  | ||||||
|     bool done = false; |     bool done = false; | ||||||
|  |  | ||||||
|     if (inflateInit2(&strm, (16 + MAX_WBITS)) != Z_OK) |     if (inflateInit2(&strm, (16 + MAX_WBITS)) != Z_OK) { | ||||||
|     { |  | ||||||
|         return false; |         return false; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     int err = Z_OK; |     int err = Z_OK; | ||||||
|  |  | ||||||
|     while (!done) |     while (!done) { | ||||||
|     { |  | ||||||
|         // If our output buffer is too small |         // If our output buffer is too small | ||||||
|         if (strm.total_out >= uncompLength) |         if (strm.total_out >= uncompLength) { | ||||||
|         { |  | ||||||
|             uncompressedBytes.resize(uncompLength * 2); |             uncompressedBytes.resize(uncompLength * 2); | ||||||
|             uncompLength *= 2; |             uncompLength *= 2; | ||||||
|         } |         } | ||||||
| @@ -79,14 +75,12 @@ bool GZip::unzip(const QByteArray &compressedBytes, QByteArray &uncompressedByte | |||||||
|         err = inflate(&strm, Z_SYNC_FLUSH); |         err = inflate(&strm, Z_SYNC_FLUSH); | ||||||
|         if (err == Z_STREAM_END) |         if (err == Z_STREAM_END) | ||||||
|             done = true; |             done = true; | ||||||
|         else if (err != Z_OK) |         else if (err != Z_OK) { | ||||||
|         { |  | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (inflateEnd(&strm) != Z_OK || !done) |     if (inflateEnd(&strm) != Z_OK || !done) { | ||||||
|     { |  | ||||||
|         return false; |         return false; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -96,8 +90,7 @@ bool GZip::unzip(const QByteArray &compressedBytes, QByteArray &uncompressedByte | |||||||
|  |  | ||||||
| bool GZip::zip(const QByteArray& uncompressedBytes, QByteArray& compressedBytes) | bool GZip::zip(const QByteArray& uncompressedBytes, QByteArray& compressedBytes) | ||||||
| { | { | ||||||
|     if (uncompressedBytes.size() == 0) |     if (uncompressedBytes.size() == 0) { | ||||||
|     { |  | ||||||
|         compressedBytes = uncompressedBytes; |         compressedBytes = uncompressedBytes; | ||||||
|         return true; |         return true; | ||||||
|     } |     } | ||||||
| @@ -109,8 +102,7 @@ bool GZip::zip(const QByteArray &uncompressedBytes, QByteArray &compressedBytes) | |||||||
|     z_stream zs; |     z_stream zs; | ||||||
|     memset(&zs, 0, sizeof(zs)); |     memset(&zs, 0, sizeof(zs)); | ||||||
|  |  | ||||||
|     if (deflateInit2(&zs, Z_DEFAULT_COMPRESSION, Z_DEFLATED, (16 + MAX_WBITS), 8, Z_DEFAULT_STRATEGY) != Z_OK) |     if (deflateInit2(&zs, Z_DEFAULT_COMPRESSION, Z_DEFLATED, (16 + MAX_WBITS), 8, Z_DEFAULT_STRATEGY) != Z_OK) { | ||||||
|     { |  | ||||||
|         return false; |         return false; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -122,11 +114,9 @@ bool GZip::zip(const QByteArray &uncompressedBytes, QByteArray &compressedBytes) | |||||||
|  |  | ||||||
|     unsigned offset = 0; |     unsigned offset = 0; | ||||||
|     unsigned temp = 0; |     unsigned temp = 0; | ||||||
|     do |     do { | ||||||
|     { |  | ||||||
|         auto remaining = compressedBytes.size() - offset; |         auto remaining = compressedBytes.size() - offset; | ||||||
|         if(remaining < 1) |         if (remaining < 1) { | ||||||
|         { |  | ||||||
|             compressedBytes.resize(compressedBytes.size() * 2); |             compressedBytes.resize(compressedBytes.size() * 2); | ||||||
|         } |         } | ||||||
|         zs.next_out = reinterpret_cast<Bytef*>((compressedBytes.data() + offset)); |         zs.next_out = reinterpret_cast<Bytef*>((compressedBytes.data() + offset)); | ||||||
| @@ -137,13 +127,11 @@ bool GZip::zip(const QByteArray &uncompressedBytes, QByteArray &compressedBytes) | |||||||
|  |  | ||||||
|     compressedBytes.resize(offset); |     compressedBytes.resize(offset); | ||||||
|  |  | ||||||
|     if (deflateEnd(&zs) != Z_OK) |     if (deflateEnd(&zs) != Z_OK) { | ||||||
|     { |  | ||||||
|         return false; |         return false; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (ret != Z_STREAM_END) |     if (ret != Z_STREAM_END) { | ||||||
|     { |  | ||||||
|         return false; |         return false; | ||||||
|     } |     } | ||||||
|     return true; |     return true; | ||||||
|   | |||||||
| @@ -1,10 +1,8 @@ | |||||||
| #pragma once | #pragma once | ||||||
| #include <QByteArray> | #include <QByteArray> | ||||||
|  |  | ||||||
| class GZip | class GZip { | ||||||
| { |  | ||||||
|    public: |    public: | ||||||
|     static bool unzip(const QByteArray& compressedBytes, QByteArray& uncompressedBytes); |     static bool unzip(const QByteArray& compressedBytes, QByteArray& uncompressedBytes); | ||||||
|     static bool zip(const QByteArray& uncompressedBytes, QByteArray& compressedBytes); |     static bool zip(const QByteArray& uncompressedBytes, QByteArray& compressedBytes); | ||||||
| }; | }; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -6,17 +6,10 @@ | |||||||
|  |  | ||||||
| bool InstanceCopyPrefs::allTrue() const | bool InstanceCopyPrefs::allTrue() const | ||||||
| { | { | ||||||
|     return copySaves && |     return copySaves && keepPlaytime && copyGameOptions && copyResourcePacks && copyShaderPacks && copyServers && copyMods && | ||||||
|         keepPlaytime && |  | ||||||
|         copyGameOptions && |  | ||||||
|         copyResourcePacks && |  | ||||||
|         copyShaderPacks && |  | ||||||
|         copyServers && |  | ||||||
|         copyMods && |  | ||||||
|            copyScreenshots; |            copyScreenshots; | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| // Returns a single RegEx string of the selected folders/files to filter out (ex: ".minecraft/saves|.minecraft/server.dat") | // Returns a single RegEx string of the selected folders/files to filter out (ex: ".minecraft/saves|.minecraft/server.dat") | ||||||
| QString InstanceCopyPrefs::getSelectedFiltersAsRegex() const | QString InstanceCopyPrefs::getSelectedFiltersAsRegex() const | ||||||
| { | { | ||||||
| @@ -33,16 +26,21 @@ QString InstanceCopyPrefs::getSelectedFiltersAsRegex(const QStringList& addition | |||||||
|         filters << "options.txt"; |         filters << "options.txt"; | ||||||
|  |  | ||||||
|     if (!copyResourcePacks) |     if (!copyResourcePacks) | ||||||
|         filters << "resourcepacks" << "texturepacks"; |         filters << "resourcepacks" | ||||||
|  |                 << "texturepacks"; | ||||||
|  |  | ||||||
|     if (!copyShaderPacks) |     if (!copyShaderPacks) | ||||||
|         filters << "shaderpacks"; |         filters << "shaderpacks"; | ||||||
|  |  | ||||||
|     if (!copyServers) |     if (!copyServers) | ||||||
|         filters << "servers.dat" << "servers.dat_old" << "server-resource-packs"; |         filters << "servers.dat" | ||||||
|  |                 << "servers.dat_old" | ||||||
|  |                 << "server-resource-packs"; | ||||||
|  |  | ||||||
|     if (!copyMods) |     if (!copyMods) | ||||||
|         filters << "coremods" << "mods" << "config"; |         filters << "coremods" | ||||||
|  |                 << "mods" | ||||||
|  |                 << "config"; | ||||||
|  |  | ||||||
|     if (!copyScreenshots) |     if (!copyScreenshots) | ||||||
|         filters << "screenshots"; |         filters << "screenshots"; | ||||||
|   | |||||||
| @@ -156,7 +156,8 @@ void InstanceCopyTask::copyFinished() | |||||||
|         allowed_symlinks.append(m_origInstance->gameRoot().toUtf8()); |         allowed_symlinks.append(m_origInstance->gameRoot().toUtf8()); | ||||||
|         allowed_symlinks.append("\n"); |         allowed_symlinks.append("\n"); | ||||||
|         if (allowed_symlinks_file.isSymLink()) |         if (allowed_symlinks_file.isSymLink()) | ||||||
|             FS::deletePath(allowed_symlinks_file |             FS::deletePath( | ||||||
|  |                 allowed_symlinks_file | ||||||
|                     .filePath());  // we dont want to modify the original. also make sure the resulting file is not itself a link. |                     .filePath());  // we dont want to modify the original. also make sure the resulting file is not itself a link. | ||||||
|  |  | ||||||
|         FS::write(allowed_symlinks_file.filePath(), allowed_symlinks); |         FS::write(allowed_symlinks_file.filePath(), allowed_symlinks); | ||||||
|   | |||||||
| @@ -11,8 +11,7 @@ | |||||||
| #include "settings/SettingsObject.h" | #include "settings/SettingsObject.h" | ||||||
| #include "tasks/Task.h" | #include "tasks/Task.h" | ||||||
|  |  | ||||||
| class InstanceCopyTask : public InstanceTask | class InstanceCopyTask : public InstanceTask { | ||||||
| { |  | ||||||
|     Q_OBJECT |     Q_OBJECT | ||||||
|    public: |    public: | ||||||
|     explicit InstanceCopyTask(InstancePtr origInstance, const InstanceCopyPrefs& prefs); |     explicit InstanceCopyTask(InstancePtr origInstance, const InstanceCopyPrefs& prefs); | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| // SPDX-License-Identifier: GPL-3.0-only | // SPDX-License-Identifier: GPL-3.0-only | ||||||
| /* | /* | ||||||
|  *  PolyMC - Minecraft Launcher |  *  Prism Launcher - Minecraft Launcher | ||||||
|  *  Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net> |  *  Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net> | ||||||
|  *  Copyright (c) 2022 flowln <flowlnlnln@gmail.com> |  *  Copyright (c) 2022 flowln <flowlnlnln@gmail.com> | ||||||
|  * |  * | ||||||
| @@ -45,9 +45,9 @@ | |||||||
| #include "icons/IconList.h" | #include "icons/IconList.h" | ||||||
| #include "icons/IconUtils.h" | #include "icons/IconUtils.h" | ||||||
|  |  | ||||||
| #include "modplatform/technic/TechnicPackProcessor.h" |  | ||||||
| #include "modplatform/modrinth/ModrinthInstanceCreationTask.h" |  | ||||||
| #include "modplatform/flame/FlameInstanceCreationTask.h" | #include "modplatform/flame/FlameInstanceCreationTask.h" | ||||||
|  | #include "modplatform/modrinth/ModrinthInstanceCreationTask.h" | ||||||
|  | #include "modplatform/technic/TechnicPackProcessor.h" | ||||||
|  |  | ||||||
| #include "settings/INISettingsObject.h" | #include "settings/INISettingsObject.h" | ||||||
|  |  | ||||||
| @@ -138,8 +138,7 @@ void InstanceImportTask::processZipPack() | |||||||
|  |  | ||||||
|     // open the zip and find relevant files in it |     // open the zip and find relevant files in it | ||||||
|     m_packZip.reset(new QuaZip(m_archivePath)); |     m_packZip.reset(new QuaZip(m_archivePath)); | ||||||
|     if (!m_packZip->open(QuaZip::mdUnzip)) |     if (!m_packZip->open(QuaZip::mdUnzip)) { | ||||||
|     { |  | ||||||
|         emitFailed(tr("Unable to open supplied modpack zip file.")); |         emitFailed(tr("Unable to open supplied modpack zip file.")); | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
| @@ -153,22 +152,17 @@ void InstanceImportTask::processZipPack() | |||||||
|  |  | ||||||
|     // NOTE: Prioritize modpack platforms that aren't searched for recursively. |     // NOTE: Prioritize modpack platforms that aren't searched for recursively. | ||||||
|     // Especially Flame has a very common filename for its manifest, which may appear inside overrides for example |     // Especially Flame has a very common filename for its manifest, which may appear inside overrides for example | ||||||
|     if(modrinthFound) |     if (modrinthFound) { | ||||||
|     { |  | ||||||
|         // process as Modrinth pack |         // process as Modrinth pack | ||||||
|         qDebug() << "Modrinth:" << modrinthFound; |         qDebug() << "Modrinth:" << modrinthFound; | ||||||
|         m_modpackType = ModpackType::Modrinth; |         m_modpackType = ModpackType::Modrinth; | ||||||
|     } |     } else if (technicFound) { | ||||||
|     else if (technicFound) |  | ||||||
|     { |  | ||||||
|         // process as Technic pack |         // process as Technic pack | ||||||
|         qDebug() << "Technic:" << technicFound; |         qDebug() << "Technic:" << technicFound; | ||||||
|         extractDir.mkpath(".minecraft"); |         extractDir.mkpath(".minecraft"); | ||||||
|         extractDir.cd(".minecraft"); |         extractDir.cd(".minecraft"); | ||||||
|         m_modpackType = ModpackType::Technic; |         m_modpackType = ModpackType::Technic; | ||||||
|     } |     } else { | ||||||
|     else |  | ||||||
|     { |  | ||||||
|         QStringList paths_to_ignore{ "overrides/" }; |         QStringList paths_to_ignore{ "overrides/" }; | ||||||
|  |  | ||||||
|         if (QString mmcRoot = MMCZip::findFolderOfFileInZip(m_packZip.get(), "instance.cfg", paths_to_ignore); !mmcRoot.isNull()) { |         if (QString mmcRoot = MMCZip::findFolderOfFileInZip(m_packZip.get(), "instance.cfg", paths_to_ignore); !mmcRoot.isNull()) { | ||||||
| @@ -176,21 +170,22 @@ void InstanceImportTask::processZipPack() | |||||||
|             qDebug() << "MultiMC:" << mmcRoot; |             qDebug() << "MultiMC:" << mmcRoot; | ||||||
|             root = mmcRoot; |             root = mmcRoot; | ||||||
|             m_modpackType = ModpackType::MultiMC; |             m_modpackType = ModpackType::MultiMC; | ||||||
|         } else if (QString flameRoot = MMCZip::findFolderOfFileInZip(m_packZip.get(), "manifest.json", paths_to_ignore); !flameRoot.isNull()) { |         } else if (QString flameRoot = MMCZip::findFolderOfFileInZip(m_packZip.get(), "manifest.json", paths_to_ignore); | ||||||
|  |                    !flameRoot.isNull()) { | ||||||
|             // process as Flame pack |             // process as Flame pack | ||||||
|             qDebug() << "Flame:" << flameRoot; |             qDebug() << "Flame:" << flameRoot; | ||||||
|             root = flameRoot; |             root = flameRoot; | ||||||
|             m_modpackType = ModpackType::Flame; |             m_modpackType = ModpackType::Flame; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     if(m_modpackType == ModpackType::Unknown) |     if (m_modpackType == ModpackType::Unknown) { | ||||||
|     { |  | ||||||
|         emitFailed(tr("Archive does not contain a recognized modpack type.")); |         emitFailed(tr("Archive does not contain a recognized modpack type.")); | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // make sure we extract just the pack |     // make sure we extract just the pack | ||||||
|     m_extractFuture = QtConcurrent::run(QThreadPool::globalInstance(), MMCZip::extractSubDir, m_packZip.get(), root, extractDir.absolutePath()); |     m_extractFuture = | ||||||
|  |         QtConcurrent::run(QThreadPool::globalInstance(), MMCZip::extractSubDir, m_packZip.get(), root, extractDir.absolutePath()); | ||||||
|     connect(&m_extractFutureWatcher, &QFutureWatcher<QStringList>::finished, this, &InstanceImportTask::extractFinished); |     connect(&m_extractFutureWatcher, &QFutureWatcher<QStringList>::finished, this, &InstanceImportTask::extractFinished); | ||||||
|     m_extractFutureWatcher.setFuture(m_extractFuture); |     m_extractFutureWatcher.setFuture(m_extractFuture); | ||||||
| } | } | ||||||
| @@ -210,37 +205,28 @@ void InstanceImportTask::extractFinished() | |||||||
|  |  | ||||||
|     qDebug() << "Fixing permissions for extracted pack files..."; |     qDebug() << "Fixing permissions for extracted pack files..."; | ||||||
|     QDirIterator it(extractDir, QDirIterator::Subdirectories); |     QDirIterator it(extractDir, QDirIterator::Subdirectories); | ||||||
|     while (it.hasNext()) |     while (it.hasNext()) { | ||||||
|     { |  | ||||||
|         auto filepath = it.next(); |         auto filepath = it.next(); | ||||||
|         QFileInfo file(filepath); |         QFileInfo file(filepath); | ||||||
|         auto permissions = QFile::permissions(filepath); |         auto permissions = QFile::permissions(filepath); | ||||||
|         auto origPermissions = permissions; |         auto origPermissions = permissions; | ||||||
|         if(file.isDir()) |         if (file.isDir()) { | ||||||
|         { |  | ||||||
|             // Folder +rwx for current user |             // Folder +rwx for current user | ||||||
|             permissions |= QFileDevice::Permission::ReadUser | QFileDevice::Permission::WriteUser | QFileDevice::Permission::ExeUser; |             permissions |= QFileDevice::Permission::ReadUser | QFileDevice::Permission::WriteUser | QFileDevice::Permission::ExeUser; | ||||||
|         } |         } else { | ||||||
|         else |  | ||||||
|         { |  | ||||||
|             // File +rw for current user |             // File +rw for current user | ||||||
|             permissions |= QFileDevice::Permission::ReadUser | QFileDevice::Permission::WriteUser; |             permissions |= QFileDevice::Permission::ReadUser | QFileDevice::Permission::WriteUser; | ||||||
|         } |         } | ||||||
|         if(origPermissions != permissions) |         if (origPermissions != permissions) { | ||||||
|         { |             if (!QFile::setPermissions(filepath, permissions)) { | ||||||
|             if(!QFile::setPermissions(filepath, permissions)) |  | ||||||
|             { |  | ||||||
|                 logWarning(tr("Could not fix permissions for %1").arg(filepath)); |                 logWarning(tr("Could not fix permissions for %1").arg(filepath)); | ||||||
|             } |             } else { | ||||||
|             else |  | ||||||
|             { |  | ||||||
|                 qDebug() << "Fixed" << filepath; |                 qDebug() << "Fixed" << filepath; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     switch(m_modpackType) |     switch (m_modpackType) { | ||||||
|     { |  | ||||||
|         case ModpackType::MultiMC: |         case ModpackType::MultiMC: | ||||||
|             processMultiMC(); |             processMultiMC(); | ||||||
|             return; |             return; | ||||||
| @@ -276,7 +262,8 @@ void InstanceImportTask::processFlame() | |||||||
|         if (original_instance_id_it != m_extra_info.constEnd()) |         if (original_instance_id_it != m_extra_info.constEnd()) | ||||||
|             original_instance_id = original_instance_id_it.value(); |             original_instance_id = original_instance_id_it.value(); | ||||||
|  |  | ||||||
|         inst_creation_task = makeShared<FlameCreationTask>(m_stagingPath, m_globalSettings, m_parent, pack_id, pack_version_id, original_instance_id); |         inst_creation_task = | ||||||
|  |             makeShared<FlameCreationTask>(m_stagingPath, m_globalSettings, m_parent, pack_id, pack_version_id, original_instance_id); | ||||||
|     } else { |     } else { | ||||||
|         // FIXME: Find a way to get IDs in directly imported ZIPs |         // FIXME: Find a way to get IDs in directly imported ZIPs | ||||||
|         inst_creation_task = makeShared<FlameCreationTask>(m_stagingPath, m_globalSettings, m_parent, QString(), QString()); |         inst_creation_task = makeShared<FlameCreationTask>(m_stagingPath, m_globalSettings, m_parent, QString(), QString()); | ||||||
| @@ -362,7 +349,8 @@ void InstanceImportTask::processModrinth() | |||||||
|         if (original_instance_id_it != m_extra_info.constEnd()) |         if (original_instance_id_it != m_extra_info.constEnd()) | ||||||
|             original_instance_id = original_instance_id_it.value(); |             original_instance_id = original_instance_id_it.value(); | ||||||
|  |  | ||||||
|         inst_creation_task = new ModrinthCreationTask(m_stagingPath, m_globalSettings, m_parent, pack_id, pack_version_id, original_instance_id); |         inst_creation_task = | ||||||
|  |             new ModrinthCreationTask(m_stagingPath, m_globalSettings, m_parent, pack_id, pack_version_id, original_instance_id); | ||||||
|     } else { |     } else { | ||||||
|         QString pack_id; |         QString pack_id; | ||||||
|         if (!m_sourceUrl.isEmpty()) { |         if (!m_sourceUrl.isEmpty()) { | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| // SPDX-License-Identifier: GPL-3.0-only | // SPDX-License-Identifier: GPL-3.0-only | ||||||
| /* | /* | ||||||
|  *  PolyMC - Minecraft Launcher |  *  Prism Launcher - Minecraft Launcher | ||||||
|  *  Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net> |  *  Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net> | ||||||
|  * |  * | ||||||
|  *  This program is free software: you can redistribute it and/or modify |  *  This program is free software: you can redistribute it and/or modify | ||||||
| @@ -35,34 +35,29 @@ | |||||||
|  |  | ||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
| #include "InstanceTask.h" |  | ||||||
| #include "net/NetJob.h" |  | ||||||
| #include <QUrl> |  | ||||||
| #include <QFuture> | #include <QFuture> | ||||||
| #include <QFutureWatcher> | #include <QFutureWatcher> | ||||||
| #include "settings/SettingsObject.h" | #include <QUrl> | ||||||
|  | #include "InstanceTask.h" | ||||||
| #include "QObjectPtr.h" | #include "QObjectPtr.h" | ||||||
| #include "modplatform/flame/PackManifest.h" | #include "modplatform/flame/PackManifest.h" | ||||||
|  | #include "net/NetJob.h" | ||||||
|  | #include "settings/SettingsObject.h" | ||||||
|  |  | ||||||
| #include <optional> | #include <optional> | ||||||
|  |  | ||||||
| class QuaZip; | class QuaZip; | ||||||
| namespace Flame | namespace Flame { | ||||||
| { |  | ||||||
| class FileResolvingTask; | class FileResolvingTask; | ||||||
| } | } | ||||||
|  |  | ||||||
| class InstanceImportTask : public InstanceTask | class InstanceImportTask : public InstanceTask { | ||||||
| { |  | ||||||
|     Q_OBJECT |     Q_OBJECT | ||||||
|    public: |    public: | ||||||
|     explicit InstanceImportTask(const QUrl sourceUrl, QWidget* parent = nullptr, QMap<QString, QString>&& extra_info = {}); |     explicit InstanceImportTask(const QUrl sourceUrl, QWidget* parent = nullptr, QMap<QString, QString>&& extra_info = {}); | ||||||
|  |  | ||||||
|     bool abort() override; |     bool abort() override; | ||||||
|     const QVector<Flame::File> &getBlockedFiles() const |     const QVector<Flame::File>& getBlockedFiles() const { return m_blockedMods; } | ||||||
|     { |  | ||||||
|         return m_blockedMods; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|    protected: |    protected: | ||||||
|     //! Entry point for tasks. |     //! Entry point for tasks. | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| // SPDX-License-Identifier: GPL-3.0-only | // SPDX-License-Identifier: GPL-3.0-only | ||||||
| /* | /* | ||||||
|  *  PolyMC - Minecraft Launcher |  *  Prism Launcher - Minecraft Launcher | ||||||
|  *  Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net> |  *  Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net> | ||||||
|  * |  * | ||||||
|  *  This program is free software: you can redistribute it and/or modify |  *  This program is free software: you can redistribute it and/or modify | ||||||
| @@ -41,9 +41,9 @@ | |||||||
| #include <QJsonArray> | #include <QJsonArray> | ||||||
| #include <QJsonDocument> | #include <QJsonDocument> | ||||||
| #include <QMimeData> | #include <QMimeData> | ||||||
|  | #include <QPair> | ||||||
| #include <QSet> | #include <QSet> | ||||||
| #include <QStack> | #include <QStack> | ||||||
| #include <QPair> |  | ||||||
| #include <QTextStream> | #include <QTextStream> | ||||||
| #include <QThread> | #include <QThread> | ||||||
| #include <QTimer> | #include <QTimer> | ||||||
| @@ -159,37 +159,29 @@ QVariant InstanceList::data(const QModelIndex& index, int role) const | |||||||
|         return QVariant(); |         return QVariant(); | ||||||
|     } |     } | ||||||
|     BaseInstance* pdata = static_cast<BaseInstance*>(index.internalPointer()); |     BaseInstance* pdata = static_cast<BaseInstance*>(index.internalPointer()); | ||||||
|     switch (role) |     switch (role) { | ||||||
|     { |         case InstancePointerRole: { | ||||||
|     case InstancePointerRole: |  | ||||||
|     { |  | ||||||
|             QVariant v = QVariant::fromValue((void*)pdata); |             QVariant v = QVariant::fromValue((void*)pdata); | ||||||
|             return v; |             return v; | ||||||
|         } |         } | ||||||
|     case InstanceIDRole: |         case InstanceIDRole: { | ||||||
|     { |  | ||||||
|             return pdata->id(); |             return pdata->id(); | ||||||
|         } |         } | ||||||
|         case Qt::EditRole: |         case Qt::EditRole: | ||||||
|     case Qt::DisplayRole: |         case Qt::DisplayRole: { | ||||||
|     { |  | ||||||
|             return pdata->name(); |             return pdata->name(); | ||||||
|         } |         } | ||||||
|     case Qt::AccessibleTextRole: |         case Qt::AccessibleTextRole: { | ||||||
|     { |  | ||||||
|             return tr("%1 Instance").arg(pdata->name()); |             return tr("%1 Instance").arg(pdata->name()); | ||||||
|         } |         } | ||||||
|     case Qt::ToolTipRole: |         case Qt::ToolTipRole: { | ||||||
|     { |  | ||||||
|             return pdata->instanceRoot(); |             return pdata->instanceRoot(); | ||||||
|         } |         } | ||||||
|     case Qt::DecorationRole: |         case Qt::DecorationRole: { | ||||||
|     { |  | ||||||
|             return pdata->iconKey(); |             return pdata->iconKey(); | ||||||
|         } |         } | ||||||
|         // HACK: see InstanceView.h in gui! |         // HACK: see InstanceView.h in gui! | ||||||
|     case GroupRole: |         case GroupRole: { | ||||||
|     { |  | ||||||
|             return getInstanceGroup(pdata->id()); |             return getInstanceGroup(pdata->id()); | ||||||
|         } |         } | ||||||
|         default: |         default: | ||||||
| @@ -325,11 +317,13 @@ bool InstanceList::trashInstance(const InstanceId& id) | |||||||
|     return true; |     return true; | ||||||
| } | } | ||||||
|  |  | ||||||
| bool InstanceList::trashedSomething() { | bool InstanceList::trashedSomething() | ||||||
|  | { | ||||||
|     return !m_trashHistory.empty(); |     return !m_trashHistory.empty(); | ||||||
| } | } | ||||||
|  |  | ||||||
| void InstanceList::undoTrashInstance() { | void InstanceList::undoTrashInstance() | ||||||
|  | { | ||||||
|     if (m_trashHistory.empty()) { |     if (m_trashHistory.empty()) { | ||||||
|         qWarning() << "Nothing to recover from trash."; |         qWarning() << "Nothing to recover from trash."; | ||||||
|         return; |         return; | ||||||
| @@ -597,13 +591,11 @@ InstancePtr InstanceList::loadInstance(const InstanceId& id) | |||||||
|  |  | ||||||
|     QString inst_type = instanceSettings->get("InstanceType").toString(); |     QString inst_type = instanceSettings->get("InstanceType").toString(); | ||||||
|  |  | ||||||
|     // NOTE: Some PolyMC versions didn't save the InstanceType properly. We will just bank on the probability that this is probably a OneSix instance |     // NOTE: Some PolyMC versions didn't save the InstanceType properly. We will just bank on the probability that this is probably a OneSix | ||||||
|     if (inst_type == "OneSix" || inst_type.isEmpty()) |     // instance | ||||||
|     { |     if (inst_type == "OneSix" || inst_type.isEmpty()) { | ||||||
|         inst.reset(new MinecraftInstance(m_globalSettings, instanceSettings, instanceRoot)); |         inst.reset(new MinecraftInstance(m_globalSettings, instanceSettings, instanceRoot)); | ||||||
|     } |     } else { | ||||||
|     else |  | ||||||
|     { |  | ||||||
|         inst.reset(new NullInstance(m_globalSettings, instanceSettings, instanceRoot)); |         inst.reset(new NullInstance(m_globalSettings, instanceSettings, instanceRoot)); | ||||||
|     } |     } | ||||||
|     qDebug() << "Loaded instance " << inst->name() << " from " << inst->instanceRoot(); |     qDebug() << "Loaded instance " << inst->name() << " from " << inst->instanceRoot(); | ||||||
| @@ -787,9 +779,14 @@ class InstanceStaging : public Task { | |||||||
|     Q_OBJECT |     Q_OBJECT | ||||||
|     const unsigned minBackoff = 1; |     const unsigned minBackoff = 1; | ||||||
|     const unsigned maxBackoff = 16; |     const unsigned maxBackoff = 16; | ||||||
|  |  | ||||||
|    public: |    public: | ||||||
|     InstanceStaging(InstanceList* parent, InstanceTask* child, QString stagingPath, InstanceName const& instanceName, QString groupName) |     InstanceStaging(InstanceList* parent, InstanceTask* child, QString stagingPath, InstanceName const& instanceName, QString groupName) | ||||||
|         : m_parent(parent), backoff(minBackoff, maxBackoff), m_stagingPath(std::move(stagingPath)), m_instance_name(std::move(instanceName)), m_groupName(std::move(groupName)) |         : m_parent(parent) | ||||||
|  |         , backoff(minBackoff, maxBackoff) | ||||||
|  |         , m_stagingPath(std::move(stagingPath)) | ||||||
|  |         , m_instance_name(std::move(instanceName)) | ||||||
|  |         , m_groupName(std::move(groupName)) | ||||||
|     { |     { | ||||||
|         m_child.reset(child); |         m_child.reset(child); | ||||||
|         connect(child, &Task::succeeded, this, &InstanceStaging::childSucceded); |         connect(child, &Task::succeeded, this, &InstanceStaging::childSucceded); | ||||||
| @@ -815,10 +812,7 @@ class InstanceStaging : public Task { | |||||||
|  |  | ||||||
|         return Task::abort(); |         return Task::abort(); | ||||||
|     } |     } | ||||||
|     bool canAbort() const override |     bool canAbort() const override { return (m_child && m_child->canAbort()); } | ||||||
|     { |  | ||||||
|         return (m_child && m_child->canAbort()); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|    protected: |    protected: | ||||||
|     virtual void executeTask() override { m_child->start(); } |     virtual void executeTask() override { m_child->start(); } | ||||||
| @@ -828,8 +822,7 @@ class InstanceStaging : public Task { | |||||||
|     void childSucceded() |     void childSucceded() | ||||||
|     { |     { | ||||||
|         unsigned sleepTime = backoff(); |         unsigned sleepTime = backoff(); | ||||||
|         if (m_parent->commitStagedInstance(m_stagingPath, m_instance_name, m_groupName, *m_child.get())) |         if (m_parent->commitStagedInstance(m_stagingPath, m_instance_name, m_groupName, *m_child.get())) { | ||||||
|         { |  | ||||||
|             emitSucceeded(); |             emitSucceeded(); | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
| @@ -847,10 +840,7 @@ class InstanceStaging : public Task { | |||||||
|         emitFailed(reason); |         emitFailed(reason); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     void childAborted() |     void childAborted() { emitAborted(); } | ||||||
|     { |  | ||||||
|         emitAborted(); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|    private: |    private: | ||||||
|     InstanceList* m_parent; |     InstanceList* m_parent; | ||||||
| @@ -892,7 +882,10 @@ QString InstanceList::getStagedInstancePath() | |||||||
|     return path; |     return path; | ||||||
| } | } | ||||||
|  |  | ||||||
| bool InstanceList::commitStagedInstance(const QString& path, InstanceName const& instanceName, const QString& groupName, InstanceTask const& commiting) | bool InstanceList::commitStagedInstance(const QString& path, | ||||||
|  |                                         InstanceName const& instanceName, | ||||||
|  |                                         const QString& groupName, | ||||||
|  |                                         InstanceTask const& commiting) | ||||||
| { | { | ||||||
|     QDir dir; |     QDir dir; | ||||||
|     QString instID; |     QString instID; | ||||||
|   | |||||||
| @@ -15,12 +15,12 @@ | |||||||
|  |  | ||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
| #include <QObject> |  | ||||||
| #include <QAbstractListModel> | #include <QAbstractListModel> | ||||||
| #include <QSet> |  | ||||||
| #include <QList> | #include <QList> | ||||||
| #include <QStack> | #include <QObject> | ||||||
| #include <QPair> | #include <QPair> | ||||||
|  | #include <QSet> | ||||||
|  | #include <QStack> | ||||||
|  |  | ||||||
| #include "BaseInstance.h" | #include "BaseInstance.h" | ||||||
|  |  | ||||||
| @@ -32,21 +32,9 @@ using InstanceId = QString; | |||||||
| using GroupId = QString; | using GroupId = QString; | ||||||
| using InstanceLocator = std::pair<InstancePtr, int>; | using InstanceLocator = std::pair<InstancePtr, int>; | ||||||
|  |  | ||||||
| enum class InstCreateError | enum class InstCreateError { NoCreateError = 0, NoSuchVersion, UnknownCreateError, InstExists, CantCreateDir }; | ||||||
| { |  | ||||||
|     NoCreateError = 0, |  | ||||||
|     NoSuchVersion, |  | ||||||
|     UnknownCreateError, |  | ||||||
|     InstExists, |  | ||||||
|     CantCreateDir |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| enum class GroupsState | enum class GroupsState { NotLoaded, Steady, Dirty }; | ||||||
| { |  | ||||||
|     NotLoaded, |  | ||||||
|     Steady, |  | ||||||
|     Dirty |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| struct TrashHistoryItem { | struct TrashHistoryItem { | ||||||
|     QString id; |     QString id; | ||||||
| @@ -55,8 +43,7 @@ struct TrashHistoryItem { | |||||||
|     QString groupName; |     QString groupName; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| class InstanceList : public QAbstractListModel | class InstanceList : public QAbstractListModel { | ||||||
| { |  | ||||||
|     Q_OBJECT |     Q_OBJECT | ||||||
|  |  | ||||||
|    public: |    public: | ||||||
| @@ -71,8 +58,7 @@ public: | |||||||
|  |  | ||||||
|     bool setData(const QModelIndex& index, const QVariant& value, int role) override; |     bool setData(const QModelIndex& index, const QVariant& value, int role) override; | ||||||
|  |  | ||||||
|     enum AdditionalRoles |     enum AdditionalRoles { | ||||||
|     { |  | ||||||
|         GroupRole = Qt::UserRole, |         GroupRole = Qt::UserRole, | ||||||
|         InstancePointerRole = 0x34B1CB48,  ///< Return pointer to real instance |         InstancePointerRole = 0x34B1CB48,  ///< Return pointer to real instance | ||||||
|         InstanceIDRole = 0x34B1CB49        ///< Return id if the instance |         InstanceIDRole = 0x34B1CB49        ///< Return id if the instance | ||||||
| @@ -82,21 +68,11 @@ public: | |||||||
|      * NoError Indicates that no error occurred. |      * NoError Indicates that no error occurred. | ||||||
|      * UnknownError indicates that an unspecified error occurred. |      * UnknownError indicates that an unspecified error occurred. | ||||||
|      */ |      */ | ||||||
|     enum InstListError |     enum InstListError { NoError = 0, UnknownError }; | ||||||
|     { |  | ||||||
|         NoError = 0, |  | ||||||
|         UnknownError |  | ||||||
|     }; |  | ||||||
|  |  | ||||||
|     InstancePtr at(int i) const |     InstancePtr at(int i) const { return m_instances.at(i); } | ||||||
|     { |  | ||||||
|         return m_instances.at(i); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     int count() const |     int count() const { return m_instances.count(); } | ||||||
|     { |  | ||||||
|         return m_instances.count(); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     InstListError loadList(); |     InstListError loadList(); | ||||||
|     void saveNow(); |     void saveNow(); | ||||||
|   | |||||||
| @@ -1,31 +1,26 @@ | |||||||
| #pragma once | #pragma once | ||||||
| #include "minecraft/MinecraftInstance.h" |  | ||||||
| #include <FileSystem.h> | #include <FileSystem.h> | ||||||
|  | #include "minecraft/MinecraftInstance.h" | ||||||
| #include "ui/pages/BasePage.h" | #include "ui/pages/BasePage.h" | ||||||
| #include "ui/pages/BasePageProvider.h" | #include "ui/pages/BasePageProvider.h" | ||||||
|  | #include "ui/pages/instance/InstanceSettingsPage.h" | ||||||
| #include "ui/pages/instance/LogPage.h" | #include "ui/pages/instance/LogPage.h" | ||||||
| #include "ui/pages/instance/VersionPage.h" |  | ||||||
| #include "ui/pages/instance/ManagedPackPage.h" | #include "ui/pages/instance/ManagedPackPage.h" | ||||||
| #include "ui/pages/instance/ModFolderPage.h" | #include "ui/pages/instance/ModFolderPage.h" | ||||||
| #include "ui/pages/instance/ResourcePackPage.h" |  | ||||||
| #include "ui/pages/instance/TexturePackPage.h" |  | ||||||
| #include "ui/pages/instance/ShaderPackPage.h" |  | ||||||
| #include "ui/pages/instance/NotesPage.h" | #include "ui/pages/instance/NotesPage.h" | ||||||
| #include "ui/pages/instance/ScreenshotsPage.h" |  | ||||||
| #include "ui/pages/instance/InstanceSettingsPage.h" |  | ||||||
| #include "ui/pages/instance/OtherLogsPage.h" | #include "ui/pages/instance/OtherLogsPage.h" | ||||||
| #include "ui/pages/instance/WorldListPage.h" | #include "ui/pages/instance/ResourcePackPage.h" | ||||||
|  | #include "ui/pages/instance/ScreenshotsPage.h" | ||||||
| #include "ui/pages/instance/ServersPage.h" | #include "ui/pages/instance/ServersPage.h" | ||||||
| #include "ui/pages/instance/GameOptionsPage.h" | #include "ui/pages/instance/ShaderPackPage.h" | ||||||
|  | #include "ui/pages/instance/TexturePackPage.h" | ||||||
|  | #include "ui/pages/instance/VersionPage.h" | ||||||
|  | #include "ui/pages/instance/WorldListPage.h" | ||||||
|  |  | ||||||
| class InstancePageProvider : public QObject, public BasePageProvider | class InstancePageProvider : protected QObject, public BasePageProvider { | ||||||
| { |  | ||||||
|     Q_OBJECT |     Q_OBJECT | ||||||
|    public: |    public: | ||||||
|     explicit InstancePageProvider(InstancePtr parent) |     explicit InstancePageProvider(InstancePtr parent) { inst = parent; } | ||||||
|     { |  | ||||||
|         inst = parent; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     virtual ~InstancePageProvider(){}; |     virtual ~InstancePageProvider(){}; | ||||||
|     virtual QList<BasePage*> getPages() override |     virtual QList<BasePage*> getPages() override | ||||||
| @@ -50,18 +45,14 @@ public: | |||||||
|         values.append(new ScreenshotsPage(FS::PathCombine(onesix->gameRoot(), "screenshots"))); |         values.append(new ScreenshotsPage(FS::PathCombine(onesix->gameRoot(), "screenshots"))); | ||||||
|         values.append(new InstanceSettingsPage(onesix.get())); |         values.append(new InstanceSettingsPage(onesix.get())); | ||||||
|         auto logMatcher = inst->getLogFileMatcher(); |         auto logMatcher = inst->getLogFileMatcher(); | ||||||
|         if(logMatcher) |         if (logMatcher) { | ||||||
|         { |  | ||||||
|             values.append(new OtherLogsPage(inst->getLogFileRoot(), logMatcher)); |             values.append(new OtherLogsPage(inst->getLogFileRoot(), logMatcher)); | ||||||
|         } |         } | ||||||
|         return values; |         return values; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     virtual QString dialogTitle() override |     virtual QString dialogTitle() override { return tr("Edit Instance (%1)").arg(inst->name()); } | ||||||
|     { |  | ||||||
|         return tr("Edit Instance (%1)").arg(inst->name()); |  | ||||||
|     } |  | ||||||
|    protected: |    protected: | ||||||
|     InstancePtr inst; |     InstancePtr inst; | ||||||
| }; | }; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -22,7 +22,8 @@ ShouldUpdate askIfShouldUpdate(QWidget *parent, QString original_version_name) | |||||||
| { | { | ||||||
|     auto info = CustomMessageBox::selectable( |     auto info = CustomMessageBox::selectable( | ||||||
|         parent, QObject::tr("Similar modpack was found!"), |         parent, QObject::tr("Similar modpack was found!"), | ||||||
|         QObject::tr("One or more of your instances are from this same modpack%1. Do you want to create a " |         QObject::tr( | ||||||
|  |             "One or more of your instances are from this same modpack%1. Do you want to create a " | ||||||
|             "separate instance, or update the existing one?\n\nNOTE: Make sure you made a backup of your important instance data before " |             "separate instance, or update the existing one?\n\nNOTE: Make sure you made a backup of your important instance data before " | ||||||
|             "updating, as worlds can be corrupted and some configuration may be lost (due to pack overrides).") |             "updating, as worlds can be corrupted and some configuration may be lost (due to pack overrides).") | ||||||
|             .arg(original_version_name), |             .arg(original_version_name), | ||||||
| @@ -38,7 +39,6 @@ ShouldUpdate askIfShouldUpdate(QWidget *parent, QString original_version_name) | |||||||
|     if (info->clickedButton() == info->button(QMessageBox::Abort)) |     if (info->clickedButton() == info->button(QMessageBox::Abort)) | ||||||
|         return ShouldUpdate::SkipUpdating; |         return ShouldUpdate::SkipUpdating; | ||||||
|     return ShouldUpdate::Cancel; |     return ShouldUpdate::Cancel; | ||||||
|  |  | ||||||
| } | } | ||||||
|  |  | ||||||
| QString InstanceName::name() const | QString InstanceName::name() const | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| // SPDX-License-Identifier: GPL-3.0-only | // SPDX-License-Identifier: GPL-3.0-only | ||||||
| /* | /* | ||||||
|  *  PolyMC - Minecraft Launcher |  *  Prism Launcher - Minecraft Launcher | ||||||
|  *  Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net> |  *  Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net> | ||||||
|  * |  * | ||||||
|  *  This program is free software: you can redistribute it and/or modify |  *  This program is free software: you can redistribute it and/or modify | ||||||
| @@ -41,41 +41,37 @@ | |||||||
|  |  | ||||||
| bool JavaCommon::checkJVMArgs(QString jvmargs, QWidget* parent) | bool JavaCommon::checkJVMArgs(QString jvmargs, QWidget* parent) | ||||||
| { | { | ||||||
|     if (jvmargs.contains("-XX:PermSize=") || jvmargs.contains(QRegularExpression("-Xm[sx]")) |     if (jvmargs.contains("-XX:PermSize=") || jvmargs.contains(QRegularExpression("-Xm[sx]")) || jvmargs.contains("-XX-MaxHeapSize") || | ||||||
|         || jvmargs.contains("-XX-MaxHeapSize") || jvmargs.contains("-XX:InitialHeapSize")) |         jvmargs.contains("-XX:InitialHeapSize")) { | ||||||
|     { |  | ||||||
|         auto warnStr = QObject::tr( |         auto warnStr = QObject::tr( | ||||||
|             "You tried to manually set a JVM memory option (using \"-XX:PermSize\", \"-XX-MaxHeapSize\", \"-XX:InitialHeapSize\", \"-Xmx\" or \"-Xms\").\n" |             "You tried to manually set a JVM memory option (using \"-XX:PermSize\", \"-XX-MaxHeapSize\", \"-XX:InitialHeapSize\", \"-Xmx\" " | ||||||
|  |             "or \"-Xms\").\n" | ||||||
|             "There are dedicated boxes for these in the settings (Java tab, in the Memory group at the top).\n" |             "There are dedicated boxes for these in the settings (Java tab, in the Memory group at the top).\n" | ||||||
|             "This message will be displayed until you remove them from the JVM arguments."); |             "This message will be displayed until you remove them from the JVM arguments."); | ||||||
|         CustomMessageBox::selectable( |         CustomMessageBox::selectable(parent, QObject::tr("JVM arguments warning"), warnStr, QMessageBox::Warning)->exec(); | ||||||
|             parent, QObject::tr("JVM arguments warning"), |  | ||||||
|             warnStr, |  | ||||||
|             QMessageBox::Warning)->exec(); |  | ||||||
|         return false; |         return false; | ||||||
|     } |     } | ||||||
|     // block lunacy with passing required version to the JVM |     // block lunacy with passing required version to the JVM | ||||||
|     if (jvmargs.contains(QRegularExpression("-version:.*"))) { |     if (jvmargs.contains(QRegularExpression("-version:.*"))) { | ||||||
|         auto warnStr = QObject::tr( |         auto warnStr = QObject::tr( | ||||||
|             "You tried to pass required Java version argument to the JVM (using \"-version:xxx\"). This is not safe and will not be allowed.\n" |             "You tried to pass required Java version argument to the JVM (using \"-version:xxx\"). This is not safe and will not be " | ||||||
|  |             "allowed.\n" | ||||||
|             "This message will be displayed until you remove this from the JVM arguments."); |             "This message will be displayed until you remove this from the JVM arguments."); | ||||||
|         CustomMessageBox::selectable( |         CustomMessageBox::selectable(parent, QObject::tr("JVM arguments warning"), warnStr, QMessageBox::Warning)->exec(); | ||||||
|             parent, QObject::tr("JVM arguments warning"), |  | ||||||
|             warnStr, |  | ||||||
|             QMessageBox::Warning)->exec(); |  | ||||||
|         return false; |         return false; | ||||||
|     } |     } | ||||||
|     return true; |     return true; | ||||||
| } | } | ||||||
|  |  | ||||||
| void JavaCommon::javaWasOk(QWidget *parent, JavaCheckResult result) | void JavaCommon::javaWasOk(QWidget* parent, const JavaCheckResult& result) | ||||||
| { | { | ||||||
|     QString text; |     QString text; | ||||||
|     text += QObject::tr("Java test succeeded!<br />Platform reported: %1<br />Java version " |     text += QObject::tr( | ||||||
|  |                 "Java test succeeded!<br />Platform reported: %1<br />Java version " | ||||||
|                 "reported: %2<br />Java vendor " |                 "reported: %2<br />Java vendor " | ||||||
|         "reported: %3<br />").arg(result.realPlatform, result.javaVersion.toString(), result.javaVendor); |                 "reported: %3<br />") | ||||||
|     if (result.errorLog.size()) |                 .arg(result.realPlatform, result.javaVersion.toString(), result.javaVendor); | ||||||
|     { |     if (result.errorLog.size()) { | ||||||
|         auto htmlError = result.errorLog; |         auto htmlError = result.errorLog; | ||||||
|         htmlError.replace('\n', "<br />"); |         htmlError.replace('\n', "<br />"); | ||||||
|         text += QObject::tr("<br />Warnings:<br /><font color=\"orange\">%1</font>").arg(htmlError); |         text += QObject::tr("<br />Warnings:<br /><font color=\"orange\">%1</font>").arg(htmlError); | ||||||
| @@ -83,7 +79,7 @@ void JavaCommon::javaWasOk(QWidget *parent, 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, JavaCheckResult result) | void JavaCommon::javaArgsWereBad(QWidget* parent, const JavaCheckResult& result) | ||||||
| { | { | ||||||
|     auto htmlError = result.errorLog; |     auto htmlError = result.errorLog; | ||||||
|     QString text; |     QString text; | ||||||
| @@ -93,7 +89,7 @@ void JavaCommon::javaArgsWereBad(QWidget *parent, 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, JavaCheckResult result) | void JavaCommon::javaBinaryWasBad(QWidget* parent, const JavaCheckResult& result) | ||||||
| { | { | ||||||
|     QString text; |     QString text; | ||||||
|     text += QObject::tr( |     text += QObject::tr( | ||||||
| @@ -111,8 +107,7 @@ void JavaCommon::javaCheckNotFound(QWidget *parent) | |||||||
|  |  | ||||||
| void JavaCommon::TestCheck::run() | void JavaCommon::TestCheck::run() | ||||||
| { | { | ||||||
|     if (!JavaCommon::checkJVMArgs(m_args, m_parent)) |     if (!JavaCommon::checkJVMArgs(m_args, m_parent)) { | ||||||
|     { |  | ||||||
|         emit finished(); |         emit finished(); | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
| @@ -129,8 +124,7 @@ void JavaCommon::TestCheck::run() | |||||||
|  |  | ||||||
| void JavaCommon::TestCheck::checkFinished(JavaCheckResult result) | void JavaCommon::TestCheck::checkFinished(JavaCheckResult result) | ||||||
| { | { | ||||||
|     if (result.validity != JavaCheckResult::Validity::Valid) |     if (result.validity != JavaCheckResult::Validity::Valid) { | ||||||
|     { |  | ||||||
|         javaBinaryWasBad(m_parent, result); |         javaBinaryWasBad(m_parent, result); | ||||||
|         emit finished(); |         emit finished(); | ||||||
|         return; |         return; | ||||||
| @@ -141,8 +135,7 @@ void JavaCommon::TestCheck::checkFinished(JavaCheckResult result) | |||||||
|     checker->m_args = m_args; |     checker->m_args = m_args; | ||||||
|     checker->m_minMem = m_minMem; |     checker->m_minMem = m_minMem; | ||||||
|     checker->m_maxMem = m_maxMem; |     checker->m_maxMem = m_maxMem; | ||||||
|     if (result.javaVersion.requiresPermGen()) |     if (result.javaVersion.requiresPermGen()) { | ||||||
|     { |  | ||||||
|         checker->m_permGen = m_permGen; |         checker->m_permGen = m_permGen; | ||||||
|     } |     } | ||||||
|     checker->performCheck(); |     checker->performCheck(); | ||||||
| @@ -150,8 +143,7 @@ void JavaCommon::TestCheck::checkFinished(JavaCheckResult result) | |||||||
|  |  | ||||||
| void JavaCommon::TestCheck::checkFinishedWithArgs(JavaCheckResult result) | void JavaCommon::TestCheck::checkFinishedWithArgs(JavaCheckResult result) | ||||||
| { | { | ||||||
|     if (result.validity == JavaCheckResult::Validity::Valid) |     if (result.validity == JavaCheckResult::Validity::Valid) { | ||||||
|     { |  | ||||||
|         javaWasOk(m_parent, result); |         javaWasOk(m_parent, result); | ||||||
|         emit finished(); |         emit finished(); | ||||||
|         return; |         return; | ||||||
| @@ -159,4 +151,3 @@ void JavaCommon::TestCheck::checkFinishedWithArgs(JavaCheckResult result) | |||||||
|     javaArgsWereBad(m_parent, result); |     javaArgsWereBad(m_parent, result); | ||||||
|     emit finished(); |     emit finished(); | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -6,27 +6,24 @@ class QWidget; | |||||||
| /** | /** | ||||||
|  * Common UI bits for the java pages to use. |  * Common UI bits for the java pages to use. | ||||||
|  */ |  */ | ||||||
| namespace JavaCommon | 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, JavaCheckResult result); | void javaWasOk(QWidget* parent, const JavaCheckResult& 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, JavaCheckResult result); | void javaArgsWereBad(QWidget* parent, const JavaCheckResult& 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, JavaCheckResult result); | void javaBinaryWasBad(QWidget* parent, const JavaCheckResult& 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); | ||||||
|  |  | ||||||
|     class TestCheck : public QObject | class TestCheck : public QObject { | ||||||
|     { |  | ||||||
|     Q_OBJECT |     Q_OBJECT | ||||||
|    public: |    public: | ||||||
|     TestCheck(QWidget* parent, QString path, QString args, int minMem, int maxMem, int permGen) |     TestCheck(QWidget* parent, QString path, QString args, int minMem, int maxMem, int permGen) | ||||||
|         : m_parent(parent), m_path(path), m_args(args), m_minMem(minMem), m_maxMem(maxMem), m_permGen(permGen) |         : m_parent(parent), m_path(path), m_args(args), m_minMem(minMem), m_maxMem(maxMem), m_permGen(permGen) | ||||||
|         { |     {} | ||||||
|         } |  | ||||||
|     virtual ~TestCheck(){}; |     virtual ~TestCheck(){}; | ||||||
|  |  | ||||||
|     void run(); |     void run(); | ||||||
| @@ -47,4 +44,4 @@ namespace JavaCommon | |||||||
|     int m_maxMem = 0; |     int m_maxMem = 0; | ||||||
|     int m_permGen = 64; |     int m_permGen = 64; | ||||||
| }; | }; | ||||||
| } | }  // namespace JavaCommon | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| // SPDX-License-Identifier: GPL-3.0-only | // SPDX-License-Identifier: GPL-3.0-only | ||||||
| /* | /* | ||||||
|  *  PolyMC - Minecraft Launcher |  *  Prism Launcher - Minecraft Launcher | ||||||
|  *  Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net> |  *  Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net> | ||||||
|  * |  * | ||||||
|  *  This program is free software: you can redistribute it and/or modify |  *  This program is free software: you can redistribute it and/or modify | ||||||
| @@ -37,11 +37,10 @@ | |||||||
|  |  | ||||||
| #include <QFile> | #include <QFile> | ||||||
|  |  | ||||||
| #include "FileSystem.h" |  | ||||||
| #include <math.h> | #include <math.h> | ||||||
|  | #include "FileSystem.h" | ||||||
|  |  | ||||||
| namespace Json | namespace Json { | ||||||
| { |  | ||||||
| void write(const QJsonDocument& doc, const QString& filename) | void write(const QJsonDocument& doc, const QString& filename) | ||||||
| { | { | ||||||
|     FS::write(filename, doc.toJson()); |     FS::write(filename, doc.toJson()); | ||||||
| @@ -71,17 +70,13 @@ static bool isBinaryJson(const QByteArray &data) | |||||||
| } | } | ||||||
| QJsonDocument requireDocument(const QByteArray& data, const QString& what) | QJsonDocument requireDocument(const QByteArray& data, const QString& what) | ||||||
| { | { | ||||||
|     if (isBinaryJson(data)) |     if (isBinaryJson(data)) { | ||||||
|     { |  | ||||||
|         // FIXME: Is this needed? |         // FIXME: Is this needed? | ||||||
|         throw JsonException(what + ": Invalid JSON. Binary JSON unsupported"); |         throw JsonException(what + ": Invalid JSON. Binary JSON unsupported"); | ||||||
|     } |     } else { | ||||||
|     else |  | ||||||
|     { |  | ||||||
|         QJsonParseError error; |         QJsonParseError error; | ||||||
|         QJsonDocument doc = QJsonDocument::fromJson(data, &error); |         QJsonDocument doc = QJsonDocument::fromJson(data, &error); | ||||||
|         if (error.error != QJsonParseError::NoError) |         if (error.error != QJsonParseError::NoError) { | ||||||
|         { |  | ||||||
|             throw JsonException(what + ": Error parsing JSON: " + error.errorString()); |             throw JsonException(what + ": Error parsing JSON: " + error.errorString()); | ||||||
|         } |         } | ||||||
|         return doc; |         return doc; | ||||||
| @@ -93,16 +88,14 @@ QJsonDocument requireDocument(const QString &filename, const QString &what) | |||||||
| } | } | ||||||
| QJsonObject requireObject(const QJsonDocument& doc, const QString& what) | QJsonObject requireObject(const QJsonDocument& doc, const QString& what) | ||||||
| { | { | ||||||
|     if (!doc.isObject()) |     if (!doc.isObject()) { | ||||||
|     { |  | ||||||
|         throw JsonException(what + " is not an object"); |         throw JsonException(what + " is not an object"); | ||||||
|     } |     } | ||||||
|     return doc.object(); |     return doc.object(); | ||||||
| } | } | ||||||
| QJsonArray requireArray(const QJsonDocument& doc, const QString& what) | QJsonArray requireArray(const QJsonDocument& doc, const QString& what) | ||||||
| { | { | ||||||
|     if (!doc.isArray()) |     if (!doc.isArray()) { | ||||||
|     { |  | ||||||
|         throw JsonException(what + " is not an array"); |         throw JsonException(what + " is not an array"); | ||||||
|     } |     } | ||||||
|     return doc.array(); |     return doc.array(); | ||||||
| @@ -110,19 +103,16 @@ QJsonArray requireArray(const QJsonDocument &doc, const QString &what) | |||||||
|  |  | ||||||
| void writeString(QJsonObject& to, const QString& key, const QString& value) | void writeString(QJsonObject& to, const QString& key, const QString& value) | ||||||
| { | { | ||||||
|     if (!value.isEmpty()) |     if (!value.isEmpty()) { | ||||||
|     { |  | ||||||
|         to.insert(key, value); |         to.insert(key, value); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| void writeStringList(QJsonObject& to, const QString& key, const QStringList& values) | void writeStringList(QJsonObject& to, const QString& key, const QStringList& values) | ||||||
| { | { | ||||||
|     if (!values.isEmpty()) |     if (!values.isEmpty()) { | ||||||
|     { |  | ||||||
|         QJsonArray array; |         QJsonArray array; | ||||||
|         for(auto value: values) |         for (auto value : values) { | ||||||
|         { |  | ||||||
|             array.append(value); |             array.append(value); | ||||||
|         } |         } | ||||||
|         to.insert(key, array); |         to.insert(key, array); | ||||||
| @@ -160,99 +150,98 @@ QJsonValue toJson<QVariant>(const QVariant &variant) | |||||||
|     return QJsonValue::fromVariant(variant); |     return QJsonValue::fromVariant(variant); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | template <> | ||||||
| template<> QByteArray requireIsType<QByteArray>(const QJsonValue &value, const QString &what) | QByteArray requireIsType<QByteArray>(const QJsonValue& value, const QString& what) | ||||||
| { | { | ||||||
|     const QString string = ensureIsType<QString>(value, what); |     const QString string = ensureIsType<QString>(value, what); | ||||||
|     // ensure that the string can be safely cast to Latin1 |     // ensure that the string can be safely cast to Latin1 | ||||||
|     if (string != QString::fromLatin1(string.toLatin1())) |     if (string != QString::fromLatin1(string.toLatin1())) { | ||||||
|     { |  | ||||||
|         throw JsonException(what + " is not encodable as Latin1"); |         throw JsonException(what + " is not encodable as Latin1"); | ||||||
|     } |     } | ||||||
|     return QByteArray::fromHex(string.toLatin1()); |     return QByteArray::fromHex(string.toLatin1()); | ||||||
| } | } | ||||||
|  |  | ||||||
| template<> QJsonArray requireIsType<QJsonArray>(const QJsonValue &value, const QString &what) | template <> | ||||||
| { | QJsonArray requireIsType<QJsonArray>(const QJsonValue& value, const QString& what) | ||||||
|     if (!value.isArray()) |  | ||||||
| { | { | ||||||
|  |     if (!value.isArray()) { | ||||||
|         throw JsonException(what + " is not an array"); |         throw JsonException(what + " is not an array"); | ||||||
|     } |     } | ||||||
|     return value.toArray(); |     return value.toArray(); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | template <> | ||||||
| template<> QString requireIsType<QString>(const QJsonValue &value, const QString &what) | QString requireIsType<QString>(const QJsonValue& value, const QString& what) | ||||||
| { |  | ||||||
|     if (!value.isString()) |  | ||||||
| { | { | ||||||
|  |     if (!value.isString()) { | ||||||
|         throw JsonException(what + " is not a string"); |         throw JsonException(what + " is not a string"); | ||||||
|     } |     } | ||||||
|     return value.toString(); |     return value.toString(); | ||||||
| } | } | ||||||
|  |  | ||||||
| template<> bool requireIsType<bool>(const QJsonValue &value, const QString &what) | template <> | ||||||
| { | bool requireIsType<bool>(const QJsonValue& value, const QString& what) | ||||||
|     if (!value.isBool()) |  | ||||||
| { | { | ||||||
|  |     if (!value.isBool()) { | ||||||
|         throw JsonException(what + " is not a bool"); |         throw JsonException(what + " is not a bool"); | ||||||
|     } |     } | ||||||
|     return value.toBool(); |     return value.toBool(); | ||||||
| } | } | ||||||
|  |  | ||||||
| template<> double requireIsType<double>(const QJsonValue &value, const QString &what) | template <> | ||||||
| { | double requireIsType<double>(const QJsonValue& value, const QString& what) | ||||||
|     if (!value.isDouble()) |  | ||||||
| { | { | ||||||
|  |     if (!value.isDouble()) { | ||||||
|         throw JsonException(what + " is not a double"); |         throw JsonException(what + " is not a double"); | ||||||
|     } |     } | ||||||
|     return value.toDouble(); |     return value.toDouble(); | ||||||
| } | } | ||||||
|  |  | ||||||
| template<> int requireIsType<int>(const QJsonValue &value, const QString &what) | template <> | ||||||
|  | int requireIsType<int>(const QJsonValue& value, const QString& what) | ||||||
| { | { | ||||||
|     const double doubl = requireIsType<double>(value, what); |     const double doubl = requireIsType<double>(value, what); | ||||||
|     if (fmod(doubl, 1) != 0) |     if (fmod(doubl, 1) != 0) { | ||||||
|     { |  | ||||||
|         throw JsonException(what + " is not an integer"); |         throw JsonException(what + " is not an integer"); | ||||||
|     } |     } | ||||||
|     return int(doubl); |     return int(doubl); | ||||||
| } | } | ||||||
|  |  | ||||||
| template<> QDateTime requireIsType<QDateTime>(const QJsonValue &value, const QString &what) | template <> | ||||||
|  | QDateTime requireIsType<QDateTime>(const QJsonValue& value, const QString& what) | ||||||
| { | { | ||||||
|     const QString string = requireIsType<QString>(value, what); |     const QString string = requireIsType<QString>(value, what); | ||||||
|     const QDateTime datetime = QDateTime::fromString(string, Qt::ISODate); |     const QDateTime datetime = QDateTime::fromString(string, Qt::ISODate); | ||||||
|     if (!datetime.isValid()) |     if (!datetime.isValid()) { | ||||||
|     { |  | ||||||
|         throw JsonException(what + " is not a ISO formatted date/time value"); |         throw JsonException(what + " is not a ISO formatted date/time value"); | ||||||
|     } |     } | ||||||
|     return datetime; |     return datetime; | ||||||
| } | } | ||||||
|  |  | ||||||
| template<> QUrl requireIsType<QUrl>(const QJsonValue &value, const QString &what) | template <> | ||||||
|  | QUrl requireIsType<QUrl>(const QJsonValue& value, const QString& what) | ||||||
| { | { | ||||||
|     const QString string = ensureIsType<QString>(value, what); |     const QString string = ensureIsType<QString>(value, what); | ||||||
|     if (string.isEmpty()) |     if (string.isEmpty()) { | ||||||
|     { |  | ||||||
|         return QUrl(); |         return QUrl(); | ||||||
|     } |     } | ||||||
|     const QUrl url = QUrl(string, QUrl::StrictMode); |     const QUrl url = QUrl(string, QUrl::StrictMode); | ||||||
|     if (!url.isValid()) |     if (!url.isValid()) { | ||||||
|     { |  | ||||||
|         throw JsonException(what + " is not a correctly formatted URL"); |         throw JsonException(what + " is not a correctly formatted URL"); | ||||||
|     } |     } | ||||||
|     return url; |     return url; | ||||||
| } | } | ||||||
|  |  | ||||||
| template<> QDir requireIsType<QDir>(const QJsonValue &value, const QString &what) | template <> | ||||||
|  | QDir requireIsType<QDir>(const QJsonValue& value, const QString& what) | ||||||
| { | { | ||||||
|     const QString string = requireIsType<QString>(value, what); |     const QString string = requireIsType<QString>(value, what); | ||||||
|     // FIXME: does not handle invalid characters! |     // FIXME: does not handle invalid characters! | ||||||
|     return QDir::current().absoluteFilePath(string); |     return QDir::current().absoluteFilePath(string); | ||||||
| } | } | ||||||
|  |  | ||||||
| template<> QUuid requireIsType<QUuid>(const QJsonValue &value, const QString &what) | template <> | ||||||
|  | QUuid requireIsType<QUuid>(const QJsonValue& value, const QString& what) | ||||||
| { | { | ||||||
|     const QString string = requireIsType<QString>(value, what); |     const QString string = requireIsType<QString>(value, what); | ||||||
|     const QUuid uuid = QUuid(string); |     const QUuid uuid = QUuid(string); | ||||||
| @@ -263,31 +252,31 @@ template<> QUuid requireIsType<QUuid>(const QJsonValue &value, const QString &wh | |||||||
|     return uuid; |     return uuid; | ||||||
| } | } | ||||||
|  |  | ||||||
| template<> QJsonObject requireIsType<QJsonObject>(const QJsonValue &value, const QString &what) | template <> | ||||||
| { | QJsonObject requireIsType<QJsonObject>(const QJsonValue& value, const QString& what) | ||||||
|     if (!value.isObject()) |  | ||||||
| { | { | ||||||
|  |     if (!value.isObject()) { | ||||||
|         throw JsonException(what + " is not an object"); |         throw JsonException(what + " is not an object"); | ||||||
|     } |     } | ||||||
|     return value.toObject(); |     return value.toObject(); | ||||||
| } | } | ||||||
|  |  | ||||||
| template<> QVariant requireIsType<QVariant>(const QJsonValue &value, const QString &what) | template <> | ||||||
| { | QVariant requireIsType<QVariant>(const QJsonValue& value, const QString& what) | ||||||
|     if (value.isNull() || value.isUndefined()) |  | ||||||
| { | { | ||||||
|  |     if (value.isNull() || value.isUndefined()) { | ||||||
|         throw JsonException(what + " is null or undefined"); |         throw JsonException(what + " is null or undefined"); | ||||||
|     } |     } | ||||||
|     return value.toVariant(); |     return value.toVariant(); | ||||||
| } | } | ||||||
|  |  | ||||||
| template<> QJsonValue requireIsType<QJsonValue>(const QJsonValue &value, const QString &what) | template <> | ||||||
| { | QJsonValue requireIsType<QJsonValue>(const QJsonValue& value, const QString& what) | ||||||
|     if (value.isNull() || value.isUndefined()) |  | ||||||
| { | { | ||||||
|  |     if (value.isNull() || value.isUndefined()) { | ||||||
|         throw JsonException(what + " is null or undefined"); |         throw JsonException(what + " is null or undefined"); | ||||||
|     } |     } | ||||||
|     return value; |     return value; | ||||||
| } | } | ||||||
|  |  | ||||||
| } | }  // namespace Json | ||||||
|   | |||||||
							
								
								
									
										100
									
								
								launcher/Json.h
									
									
									
									
									
								
							
							
						
						
									
										100
									
								
								launcher/Json.h
									
									
									
									
									
								
							| @@ -1,6 +1,6 @@ | |||||||
| // SPDX-License-Identifier: GPL-3.0-only | // SPDX-License-Identifier: GPL-3.0-only | ||||||
| /* | /* | ||||||
|  *  PolyMC - Minecraft Launcher |  *  Prism Launcher - Minecraft Launcher | ||||||
|  *  Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net> |  *  Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net> | ||||||
|  * |  * | ||||||
|  *  This program is free software: you can redistribute it and/or modify |  *  This program is free software: you can redistribute it and/or modify | ||||||
| @@ -35,22 +35,20 @@ | |||||||
|  |  | ||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
| #include <QJsonDocument> |  | ||||||
| #include <QJsonArray> |  | ||||||
| #include <QJsonObject> |  | ||||||
| #include <QDateTime> | #include <QDateTime> | ||||||
| #include <QUrl> |  | ||||||
| #include <QDir> | #include <QDir> | ||||||
|  | #include <QJsonArray> | ||||||
|  | #include <QJsonDocument> | ||||||
|  | #include <QJsonObject> | ||||||
|  | #include <QUrl> | ||||||
| #include <QUuid> | #include <QUuid> | ||||||
| #include <QVariant> | #include <QVariant> | ||||||
| #include <memory> | #include <memory> | ||||||
|  |  | ||||||
| #include "Exception.h" | #include "Exception.h" | ||||||
|  |  | ||||||
| namespace Json | namespace Json { | ||||||
| { | class JsonException : public ::Exception { | ||||||
| class JsonException : public ::Exception |  | ||||||
| { |  | ||||||
|    public: |    public: | ||||||
|     JsonException(const QString& message) : Exception(message) {} |     JsonException(const QString& message) : Exception(message) {} | ||||||
| }; | }; | ||||||
| @@ -101,8 +99,7 @@ template<typename T> | |||||||
| QJsonArray toJsonArray(const QList<T>& container) | QJsonArray toJsonArray(const QList<T>& container) | ||||||
| { | { | ||||||
|     QJsonArray array; |     QJsonArray array; | ||||||
|     for (const T item : container) |     for (const T item : container) { | ||||||
|     { |  | ||||||
|         array.append(toJson<T>(item)); |         array.append(toJson<T>(item)); | ||||||
|     } |     } | ||||||
|     return array; |     return array; | ||||||
| @@ -115,47 +112,56 @@ template <typename T> | |||||||
| T requireIsType(const QJsonValue& value, const QString& what = "Value"); | T requireIsType(const QJsonValue& value, const QString& what = "Value"); | ||||||
|  |  | ||||||
| /// @throw JsonException | /// @throw JsonException | ||||||
| template<> double requireIsType<double>(const QJsonValue &value, const QString &what); | template <> | ||||||
|  | double requireIsType<double>(const QJsonValue& value, const QString& what); | ||||||
| /// @throw JsonException | /// @throw JsonException | ||||||
| template<> bool requireIsType<bool>(const QJsonValue &value, const QString &what); | template <> | ||||||
|  | bool requireIsType<bool>(const QJsonValue& value, const QString& what); | ||||||
| /// @throw JsonException | /// @throw JsonException | ||||||
| template<> int requireIsType<int>(const QJsonValue &value, const QString &what); | template <> | ||||||
|  | int requireIsType<int>(const QJsonValue& value, const QString& what); | ||||||
| /// @throw JsonException | /// @throw JsonException | ||||||
| template<> QJsonObject requireIsType<QJsonObject>(const QJsonValue &value, const QString &what); | template <> | ||||||
|  | QJsonObject requireIsType<QJsonObject>(const QJsonValue& value, const QString& what); | ||||||
| /// @throw JsonException | /// @throw JsonException | ||||||
| template<> QJsonArray requireIsType<QJsonArray>(const QJsonValue &value, const QString &what); | template <> | ||||||
|  | QJsonArray requireIsType<QJsonArray>(const QJsonValue& value, const QString& what); | ||||||
| /// @throw JsonException | /// @throw JsonException | ||||||
| template<> QJsonValue requireIsType<QJsonValue>(const QJsonValue &value, const QString &what); | template <> | ||||||
|  | QJsonValue requireIsType<QJsonValue>(const QJsonValue& value, const QString& what); | ||||||
| /// @throw JsonException | /// @throw JsonException | ||||||
| template<> QByteArray requireIsType<QByteArray>(const QJsonValue &value, const QString &what); | template <> | ||||||
|  | QByteArray requireIsType<QByteArray>(const QJsonValue& value, const QString& what); | ||||||
| /// @throw JsonException | /// @throw JsonException | ||||||
| template<> QDateTime requireIsType<QDateTime>(const QJsonValue &value, const QString &what); | template <> | ||||||
|  | QDateTime requireIsType<QDateTime>(const QJsonValue& value, const QString& what); | ||||||
| /// @throw JsonException | /// @throw JsonException | ||||||
| template<> QVariant requireIsType<QVariant>(const QJsonValue &value, const QString &what); | template <> | ||||||
|  | QVariant requireIsType<QVariant>(const QJsonValue& value, const QString& what); | ||||||
| /// @throw JsonException | /// @throw JsonException | ||||||
| template<> QString requireIsType<QString>(const QJsonValue &value, const QString &what); | template <> | ||||||
|  | QString requireIsType<QString>(const QJsonValue& value, const QString& what); | ||||||
| /// @throw JsonException | /// @throw JsonException | ||||||
| template<> QUuid requireIsType<QUuid>(const QJsonValue &value, const QString &what); | template <> | ||||||
|  | QUuid requireIsType<QUuid>(const QJsonValue& value, const QString& what); | ||||||
| /// @throw JsonException | /// @throw JsonException | ||||||
| template<> QDir requireIsType<QDir>(const QJsonValue &value, const QString &what); | template <> | ||||||
|  | QDir requireIsType<QDir>(const QJsonValue& value, const QString& what); | ||||||
| /// @throw JsonException | /// @throw JsonException | ||||||
| template<> QUrl requireIsType<QUrl>(const QJsonValue &value, const QString &what); | template <> | ||||||
|  | QUrl requireIsType<QUrl>(const QJsonValue& value, const QString& what); | ||||||
|  |  | ||||||
| // the following functions are higher level functions, that make use of the above functions for | // the following functions are higher level functions, that make use of the above functions for | ||||||
| // type conversion | // type conversion | ||||||
| template <typename T> | template <typename T> | ||||||
| T ensureIsType(const QJsonValue& value, const T default_ = T(), const QString& what = "Value") | T ensureIsType(const QJsonValue& value, const T default_ = T(), const QString& what = "Value") | ||||||
| { | { | ||||||
|     if (value.isUndefined() || value.isNull()) |     if (value.isUndefined() || value.isNull()) { | ||||||
|     { |  | ||||||
|         return default_; |         return default_; | ||||||
|     } |     } | ||||||
|     try |     try { | ||||||
|     { |  | ||||||
|         return requireIsType<T>(value, what); |         return requireIsType<T>(value, what); | ||||||
|     } |     } catch (const JsonException&) { | ||||||
|     catch (const JsonException &) |  | ||||||
|     { |  | ||||||
|         return default_; |         return default_; | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -165,8 +171,7 @@ template <typename T> | |||||||
| T requireIsType(const QJsonObject& parent, const QString& key, const QString& what = "__placeholder__") | T requireIsType(const QJsonObject& parent, const QString& key, const QString& what = "__placeholder__") | ||||||
| { | { | ||||||
|     const QString localWhat = QString(what).replace("__placeholder__", '\'' + key + '\''); |     const QString localWhat = QString(what).replace("__placeholder__", '\'' + key + '\''); | ||||||
|     if (!parent.contains(key)) |     if (!parent.contains(key)) { | ||||||
|     { |  | ||||||
|         throw JsonException(localWhat + "s parent does not contain " + localWhat); |         throw JsonException(localWhat + "s parent does not contain " + localWhat); | ||||||
|     } |     } | ||||||
|     return requireIsType<T>(parent.value(key), localWhat); |     return requireIsType<T>(parent.value(key), localWhat); | ||||||
| @@ -176,8 +181,7 @@ template <typename T> | |||||||
| T ensureIsType(const QJsonObject& parent, const QString& key, const T default_ = T(), const QString& what = "__placeholder__") | T ensureIsType(const QJsonObject& parent, const QString& key, const T default_ = T(), const QString& what = "__placeholder__") | ||||||
| { | { | ||||||
|     const QString localWhat = QString(what).replace("__placeholder__", '\'' + key + '\''); |     const QString localWhat = QString(what).replace("__placeholder__", '\'' + key + '\''); | ||||||
|     if (!parent.contains(key)) |     if (!parent.contains(key)) { | ||||||
|     { |  | ||||||
|         return default_; |         return default_; | ||||||
|     } |     } | ||||||
|     return ensureIsType<T>(parent.value(key), default_, localWhat); |     return ensureIsType<T>(parent.value(key), default_, localWhat); | ||||||
| @@ -188,8 +192,7 @@ QVector<T> requireIsArrayOf(const QJsonDocument &doc) | |||||||
| { | { | ||||||
|     const QJsonArray array = requireArray(doc); |     const QJsonArray array = requireArray(doc); | ||||||
|     QVector<T> out; |     QVector<T> out; | ||||||
|     for (const QJsonValue val : array) |     for (const QJsonValue val : array) { | ||||||
|     { |  | ||||||
|         out.append(requireIsType<T>(val, "Document")); |         out.append(requireIsType<T>(val, "Document")); | ||||||
|     } |     } | ||||||
|     return out; |     return out; | ||||||
| @@ -200,8 +203,7 @@ QVector<T> ensureIsArrayOf(const QJsonValue &value, const QString &what = "Value | |||||||
| { | { | ||||||
|     const QJsonArray array = ensureIsType<QJsonArray>(value, QJsonArray(), what); |     const QJsonArray array = ensureIsType<QJsonArray>(value, QJsonArray(), what); | ||||||
|     QVector<T> out; |     QVector<T> out; | ||||||
|     for (const QJsonValue val : array) |     for (const QJsonValue val : array) { | ||||||
|     { |  | ||||||
|         out.append(requireIsType<T>(val, what)); |         out.append(requireIsType<T>(val, what)); | ||||||
|     } |     } | ||||||
|     return out; |     return out; | ||||||
| @@ -210,8 +212,7 @@ QVector<T> ensureIsArrayOf(const QJsonValue &value, const QString &what = "Value | |||||||
| template <typename T> | template <typename T> | ||||||
| QVector<T> ensureIsArrayOf(const QJsonValue& value, const QVector<T> default_, const QString& what = "Value") | QVector<T> ensureIsArrayOf(const QJsonValue& value, const QVector<T> default_, const QString& what = "Value") | ||||||
| { | { | ||||||
|     if (value.isUndefined()) |     if (value.isUndefined()) { | ||||||
|     { |  | ||||||
|         return default_; |         return default_; | ||||||
|     } |     } | ||||||
|     return ensureIsArrayOf<T>(value, what); |     return ensureIsArrayOf<T>(value, what); | ||||||
| @@ -222,20 +223,20 @@ template <typename T> | |||||||
| QVector<T> requireIsArrayOf(const QJsonObject& parent, const QString& key, const QString& what = "__placeholder__") | QVector<T> requireIsArrayOf(const QJsonObject& parent, const QString& key, const QString& what = "__placeholder__") | ||||||
| { | { | ||||||
|     const QString localWhat = QString(what).replace("__placeholder__", '\'' + key + '\''); |     const QString localWhat = QString(what).replace("__placeholder__", '\'' + key + '\''); | ||||||
|     if (!parent.contains(key)) |     if (!parent.contains(key)) { | ||||||
|     { |  | ||||||
|         throw JsonException(localWhat + "s parent does not contain " + localWhat); |         throw JsonException(localWhat + "s parent does not contain " + localWhat); | ||||||
|     } |     } | ||||||
|     return ensureIsArrayOf<T>(parent.value(key), localWhat); |     return ensureIsArrayOf<T>(parent.value(key), localWhat); | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename T> | template <typename T> | ||||||
| QVector<T> ensureIsArrayOf(const QJsonObject &parent, const QString &key, | QVector<T> ensureIsArrayOf(const QJsonObject& parent, | ||||||
|                          const QVector<T> &default_ = QVector<T>(), const QString &what = "__placeholder__") |                            const QString& key, | ||||||
|  |                            const QVector<T>& default_ = QVector<T>(), | ||||||
|  |                            const QString& what = "__placeholder__") | ||||||
| { | { | ||||||
|     const QString localWhat = QString(what).replace("__placeholder__", '\'' + key + '\''); |     const QString localWhat = QString(what).replace("__placeholder__", '\'' + key + '\''); | ||||||
|     if (!parent.contains(key)) |     if (!parent.contains(key)) { | ||||||
|     { |  | ||||||
|         return default_; |         return default_; | ||||||
|     } |     } | ||||||
|     return ensureIsArrayOf<T>(parent.value(key), default_, localWhat); |     return ensureIsArrayOf<T>(parent.value(key), default_, localWhat); | ||||||
| @@ -255,7 +256,8 @@ QVector<T> ensureIsArrayOf(const QJsonObject &parent, const QString &key, | |||||||
|     {                                                                                                                 \ |     {                                                                                                                 \ | ||||||
|         return requireIsType<TYPE>(parent, key, what);                                                                \ |         return requireIsType<TYPE>(parent, key, what);                                                                \ | ||||||
|     }                                                                                                                 \ |     }                                                                                                                 \ | ||||||
|     inline TYPE ensure##NAME(const QJsonObject &parent, const QString &key, const TYPE default_ = TYPE(), const QString &what = "__placeholder") \ |     inline TYPE ensure##NAME(const QJsonObject& parent, const QString& key, const TYPE default_ = TYPE(),             \ | ||||||
|  |                              const QString& what = "__placeholder")                                                   \ | ||||||
|     {                                                                                                                 \ |     {                                                                                                                 \ | ||||||
|         return ensureIsType<TYPE>(parent, key, default_, what);                                                       \ |         return ensureIsType<TYPE>(parent, key, default_, what);                                                       \ | ||||||
|     } |     } | ||||||
| @@ -276,5 +278,5 @@ JSON_HELPERFUNCTIONS(Variant, QVariant) | |||||||
|  |  | ||||||
| #undef JSON_HELPERFUNCTIONS | #undef JSON_HELPERFUNCTIONS | ||||||
|  |  | ||||||
| } | }  // namespace Json | ||||||
| using JSONValidationError = Json::JsonException; | using JSONValidationError = Json::JsonException; | ||||||
|   | |||||||
| @@ -1,42 +1,26 @@ | |||||||
| #include "KonamiCode.h" | #include "KonamiCode.h" | ||||||
|  |  | ||||||
| #include <array> |  | ||||||
| #include <QDebug> | #include <QDebug> | ||||||
|  | #include <array> | ||||||
|  |  | ||||||
| namespace { | namespace { | ||||||
| const std::array<Qt::Key, 10> konamiCode = | const std::array<Qt::Key, 10> konamiCode = { { Qt::Key_Up, Qt::Key_Up, Qt::Key_Down, Qt::Key_Down, Qt::Key_Left, Qt::Key_Right, | ||||||
| { |                                                Qt::Key_Left, Qt::Key_Right, Qt::Key_B, Qt::Key_A } }; | ||||||
|     { |  | ||||||
|         Qt::Key_Up, Qt::Key_Up, |  | ||||||
|         Qt::Key_Down, Qt::Key_Down, |  | ||||||
|         Qt::Key_Left, Qt::Key_Right, |  | ||||||
|         Qt::Key_Left, Qt::Key_Right, |  | ||||||
|         Qt::Key_B, Qt::Key_A |  | ||||||
|     } |  | ||||||
| }; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| KonamiCode::KonamiCode(QObject* parent) : QObject(parent) |  | ||||||
| { |  | ||||||
| } | } | ||||||
|  |  | ||||||
|  | KonamiCode::KonamiCode(QObject* parent) : QObject(parent) {} | ||||||
|  |  | ||||||
| void KonamiCode::input(QEvent* event) | void KonamiCode::input(QEvent* event) | ||||||
| { | { | ||||||
|     if( event->type() == QEvent::KeyPress ) |     if (event->type() == QEvent::KeyPress) { | ||||||
|     { |  | ||||||
|         QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event); |         QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event); | ||||||
|         auto key = Qt::Key(keyEvent->key()); |         auto key = Qt::Key(keyEvent->key()); | ||||||
|         if(key == konamiCode[m_progress]) |         if (key == konamiCode[m_progress]) { | ||||||
|         { |  | ||||||
|             m_progress++; |             m_progress++; | ||||||
|         } |         } else { | ||||||
|         else |  | ||||||
|         { |  | ||||||
|             m_progress = 0; |             m_progress = 0; | ||||||
|         } |         } | ||||||
|         if(m_progress == static_cast<int>(konamiCode.size())) |         if (m_progress == static_cast<int>(konamiCode.size())) { | ||||||
|         { |  | ||||||
|             m_progress = 0; |             m_progress = 0; | ||||||
|             emit triggered(); |             emit triggered(); | ||||||
|         } |         } | ||||||
|   | |||||||
| @@ -2,8 +2,7 @@ | |||||||
|  |  | ||||||
| #include <QKeyEvent> | #include <QKeyEvent> | ||||||
|  |  | ||||||
| class KonamiCode : public QObject | class KonamiCode : public QObject { | ||||||
| { |  | ||||||
|     Q_OBJECT |     Q_OBJECT | ||||||
|    public: |    public: | ||||||
|     KonamiCode(QObject* parent = 0); |     KonamiCode(QObject* parent = 0); | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| // SPDX-License-Identifier: GPL-3.0-only | // SPDX-License-Identifier: GPL-3.0-only | ||||||
| /* | /* | ||||||
|  *  PolyMC - Minecraft Launcher |  *  Prism Launcher - Minecraft Launcher | ||||||
|  *  Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net> |  *  Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net> | ||||||
|  * |  * | ||||||
|  *  This program is free software: you can redistribute it and/or modify |  *  This program is free software: you can redistribute it and/or modify | ||||||
| @@ -34,39 +34,36 @@ | |||||||
|  */ |  */ | ||||||
|  |  | ||||||
| #include "LaunchController.h" | #include "LaunchController.h" | ||||||
| #include "minecraft/auth/AccountList.h" |  | ||||||
| #include "Application.h" | #include "Application.h" | ||||||
|  | #include "minecraft/auth/AccountList.h" | ||||||
|  |  | ||||||
| #include "ui/MainWindow.h" |  | ||||||
| #include "ui/InstanceWindow.h" | #include "ui/InstanceWindow.h" | ||||||
|  | #include "ui/MainWindow.h" | ||||||
| #include "ui/dialogs/CustomMessageBox.h" | #include "ui/dialogs/CustomMessageBox.h" | ||||||
| #include "ui/dialogs/ProfileSelectDialog.h" |  | ||||||
| #include "ui/dialogs/ProgressDialog.h" |  | ||||||
| #include "ui/dialogs/EditAccountDialog.h" | #include "ui/dialogs/EditAccountDialog.h" | ||||||
|  | #include "ui/dialogs/ProfileSelectDialog.h" | ||||||
| #include "ui/dialogs/ProfileSetupDialog.h" | #include "ui/dialogs/ProfileSetupDialog.h" | ||||||
|  | #include "ui/dialogs/ProgressDialog.h" | ||||||
|  |  | ||||||
| #include <QLineEdit> |  | ||||||
| #include <QInputDialog> |  | ||||||
| #include <QStringList> |  | ||||||
| #include <QHostInfo> |  | ||||||
| #include <QList> |  | ||||||
| #include <QHostAddress> | #include <QHostAddress> | ||||||
|  | #include <QHostInfo> | ||||||
|  | #include <QInputDialog> | ||||||
|  | #include <QLineEdit> | ||||||
|  | #include <QList> | ||||||
| #include <QPushButton> | #include <QPushButton> | ||||||
|  | #include <QStringList> | ||||||
|  |  | ||||||
| #include "BuildConfig.h" | #include "BuildConfig.h" | ||||||
| #include "JavaCommon.h" | #include "JavaCommon.h" | ||||||
| #include "tasks/Task.h" |  | ||||||
| #include "minecraft/auth/AccountTask.h" |  | ||||||
| #include "launch/steps/TextPrint.h" | #include "launch/steps/TextPrint.h" | ||||||
|  | #include "minecraft/auth/AccountTask.h" | ||||||
|  | #include "tasks/Task.h" | ||||||
|  |  | ||||||
| LaunchController::LaunchController(QObject *parent) : Task(parent) | LaunchController::LaunchController(QObject* parent) : Task(parent) {} | ||||||
| { |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void LaunchController::executeTask() | void LaunchController::executeTask() | ||||||
| { | { | ||||||
|     if (!m_instance) |     if (!m_instance) { | ||||||
|     { |  | ||||||
|         emitFailed(tr("No instance specified!")); |         emitFailed(tr("No instance specified!")); | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
| @@ -87,26 +84,19 @@ void LaunchController::decideAccount() | |||||||
|  |  | ||||||
|     // Find an account to use. |     // Find an account to use. | ||||||
|     auto accounts = APPLICATION->accounts(); |     auto accounts = APPLICATION->accounts(); | ||||||
|     if (accounts->count() <= 0) |     if (accounts->count() <= 0) { | ||||||
|     { |  | ||||||
|         // Tell the user they need to log in at least one account in order to play. |         // Tell the user they need to log in at least one account in order to play. | ||||||
|         auto reply = CustomMessageBox::selectable( |         auto reply = CustomMessageBox::selectable(m_parentWidget, tr("No Accounts"), | ||||||
|             m_parentWidget, |  | ||||||
|             tr("No Accounts"), |  | ||||||
|                                                   tr("In order to play Minecraft, you must have at least one Microsoft or Mojang " |                                                   tr("In order to play Minecraft, you must have at least one Microsoft or Mojang " | ||||||
|                                                      "account logged in. Mojang accounts can only be used offline. " |                                                      "account logged in. Mojang accounts can only be used offline. " | ||||||
|                                                      "Would you like to open the account manager to add an account now?"), |                                                      "Would you like to open the account manager to add an account now?"), | ||||||
|             QMessageBox::Information, |                                                   QMessageBox::Information, QMessageBox::Yes | QMessageBox::No) | ||||||
|             QMessageBox::Yes | QMessageBox::No |                          ->exec(); | ||||||
|         )->exec(); |  | ||||||
|  |  | ||||||
|         if (reply == QMessageBox::Yes) |         if (reply == QMessageBox::Yes) { | ||||||
|         { |  | ||||||
|             // Open the account manager. |             // Open the account manager. | ||||||
|             APPLICATION->ShowGlobalSettings(m_parentWidget, "accounts"); |             APPLICATION->ShowGlobalSettings(m_parentWidget, "accounts"); | ||||||
|         } |         } else if (reply == QMessageBox::No) { | ||||||
|         else if (reply == QMessageBox::No) |  | ||||||
|         { |  | ||||||
|             // Do not open "profile select" dialog. |             // Do not open "profile select" dialog. | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
| @@ -121,14 +111,10 @@ void LaunchController::decideAccount() | |||||||
|         m_accountToUse = accounts->at(instanceAccountIndex); |         m_accountToUse = accounts->at(instanceAccountIndex); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (!m_accountToUse) |     if (!m_accountToUse) { | ||||||
|     { |  | ||||||
|         // If no default account is set, ask the user which one to use. |         // If no default account is set, ask the user which one to use. | ||||||
|         ProfileSelectDialog selectDialog( |         ProfileSelectDialog selectDialog(tr("Which account would you like to use?"), ProfileSelectDialog::GlobalDefaultCheckbox, | ||||||
|             tr("Which account would you like to use?"), |                                          m_parentWidget); | ||||||
|             ProfileSelectDialog::GlobalDefaultCheckbox, |  | ||||||
|             m_parentWidget |  | ||||||
|         ); |  | ||||||
|  |  | ||||||
|         selectDialog.exec(); |         selectDialog.exec(); | ||||||
|  |  | ||||||
| @@ -142,13 +128,12 @@ void LaunchController::decideAccount() | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | void LaunchController::login() | ||||||
| void LaunchController::login() { | { | ||||||
|     decideAccount(); |     decideAccount(); | ||||||
|  |  | ||||||
|     // if no account is selected, we bail |     // if no account is selected, we bail | ||||||
|     if (!m_accountToUse) |     if (!m_accountToUse) { | ||||||
|     { |  | ||||||
|         emitFailed(tr("No account selected for launch.")); |         emitFailed(tr("No account selected for launch.")); | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
| @@ -157,15 +142,11 @@ void LaunchController::login() { | |||||||
|     bool tryagain = true; |     bool tryagain = true; | ||||||
|     unsigned int tries = 0; |     unsigned int tries = 0; | ||||||
|  |  | ||||||
|     while (tryagain) |     while (tryagain) { | ||||||
|     { |  | ||||||
|         if (tries > 0 && tries % 3 == 0) { |         if (tries > 0 && tries % 3 == 0) { | ||||||
|             auto result = QMessageBox::question( |             auto result = | ||||||
|                 m_parentWidget, |                 QMessageBox::question(m_parentWidget, tr("Continue launch?"), | ||||||
|                 tr("Continue launch?"), |                                       tr("It looks like we couldn't launch after %1 tries. Do you want to continue trying?").arg(tries)); | ||||||
|                 tr("It looks like we couldn't launch after %1 tries. Do you want to continue trying?") |  | ||||||
|                     .arg(tries) |  | ||||||
|             ); |  | ||||||
|  |  | ||||||
|             if (result == QMessageBox::No) { |             if (result == QMessageBox::No) { | ||||||
|                 emitAborted(); |                 emitAborted(); | ||||||
| @@ -201,21 +182,12 @@ void LaunchController::login() { | |||||||
|  |  | ||||||
|                     QString lastOfflinePlayerName = APPLICATION->settings()->get("LastOfflinePlayerName").toString(); |                     QString lastOfflinePlayerName = APPLICATION->settings()->get("LastOfflinePlayerName").toString(); | ||||||
|                     QString usedname = lastOfflinePlayerName.isEmpty() ? m_session->player_name : lastOfflinePlayerName; |                     QString usedname = lastOfflinePlayerName.isEmpty() ? m_session->player_name : lastOfflinePlayerName; | ||||||
|                     QString name = QInputDialog::getText( |                     QString name = QInputDialog::getText(m_parentWidget, tr("Player name"), message, QLineEdit::Normal, usedname, &ok); | ||||||
|                         m_parentWidget, |                     if (!ok) { | ||||||
|                         tr("Player name"), |  | ||||||
|                         message, |  | ||||||
|                         QLineEdit::Normal, |  | ||||||
|                         usedname, |  | ||||||
|                         &ok |  | ||||||
|                     ); |  | ||||||
|                     if (!ok) |  | ||||||
|                     { |  | ||||||
|                         tryagain = false; |                         tryagain = false; | ||||||
|                         break; |                         break; | ||||||
|                     } |                     } | ||||||
|                     if (name.length()) |                     if (name.length()) { | ||||||
|                     { |  | ||||||
|                         usedname = name; |                         usedname = name; | ||||||
|                         APPLICATION->settings()->set("LastOfflinePlayerName", usedname); |                         APPLICATION->settings()->set("LastOfflinePlayerName", usedname); | ||||||
|                     } |                     } | ||||||
| @@ -226,13 +198,10 @@ void LaunchController::login() { | |||||||
|                     if (!m_accountToUse->hasProfile()) { |                     if (!m_accountToUse->hasProfile()) { | ||||||
|                         // Now handle setting up a profile name here... |                         // Now handle setting up a profile name here... | ||||||
|                         ProfileSetupDialog dialog(m_accountToUse, m_parentWidget); |                         ProfileSetupDialog dialog(m_accountToUse, m_parentWidget); | ||||||
|                         if (dialog.exec() == QDialog::Accepted) |                         if (dialog.exec() == QDialog::Accepted) { | ||||||
|                         { |  | ||||||
|                             tryagain = true; |                             tryagain = true; | ||||||
|                             continue; |                             continue; | ||||||
|                         } |                         } else { | ||||||
|                         else |  | ||||||
|                         { |  | ||||||
|                             emitFailed(tr("Received undetermined session status during login.")); |                             emitFailed(tr("Received undetermined session status during login.")); | ||||||
|                             return; |                             return; | ||||||
|                         } |                         } | ||||||
| @@ -240,12 +209,13 @@ void LaunchController::login() { | |||||||
|                     // we own Minecraft, there is a profile, it's all ready to go! |                     // we own Minecraft, there is a profile, it's all ready to go! | ||||||
|                     launchInstance(); |                     launchInstance(); | ||||||
|                     return; |                     return; | ||||||
|                 } |                 } else { | ||||||
|                 else { |  | ||||||
|                     // play demo ? |                     // play demo ? | ||||||
|                     QMessageBox box(m_parentWidget); |                     QMessageBox box(m_parentWidget); | ||||||
|                     box.setWindowTitle(tr("Play demo?")); |                     box.setWindowTitle(tr("Play demo?")); | ||||||
|                     box.setText(tr("This account does not own Minecraft.\nYou need to purchase the game first to play it.\n\nDo you want to play the demo?")); |                     box.setText( | ||||||
|  |                         tr("This account does not own Minecraft.\nYou need to purchase the game first to play it.\n\nDo you want to play " | ||||||
|  |                            "the demo?")); | ||||||
|                     box.setIcon(QMessageBox::Warning); |                     box.setIcon(QMessageBox::Warning); | ||||||
|                     auto demoButton = box.addButton(tr("Play Demo"), QMessageBox::ButtonRole::YesRole); |                     auto demoButton = box.addButton(tr("Play Demo"), QMessageBox::ButtonRole::YesRole); | ||||||
|                     auto cancelButton = box.addButton(tr("Cancel"), QMessageBox::ButtonRole::NoRole); |                     auto cancelButton = box.addButton(tr("Cancel"), QMessageBox::ButtonRole::NoRole); | ||||||
| @@ -256,8 +226,7 @@ void LaunchController::login() { | |||||||
|                         // play demo here |                         // play demo here | ||||||
|                         m_session->MakeDemo(); |                         m_session->MakeDemo(); | ||||||
|                         launchInstance(); |                         launchInstance(); | ||||||
|                     } |                     } else { | ||||||
|                     else { |  | ||||||
|                         emitFailed(tr("Launch cancelled - account does not own Minecraft.")); |                         emitFailed(tr("Launch cancelled - account does not own Minecraft.")); | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
| @@ -272,8 +241,7 @@ void LaunchController::login() { | |||||||
|             case AccountState::Working: { |             case AccountState::Working: { | ||||||
|                 // refresh is in progress, we need to wait for it to finish to proceed. |                 // refresh is in progress, we need to wait for it to finish to proceed. | ||||||
|                 ProgressDialog progDialog(m_parentWidget); |                 ProgressDialog progDialog(m_parentWidget); | ||||||
|                 if (m_online) |                 if (m_online) { | ||||||
|                 { |  | ||||||
|                     progDialog.setSkipButton(true, tr("Play Offline")); |                     progDialog.setSkipButton(true, tr("Play Offline")); | ||||||
|                 } |                 } | ||||||
|                 auto task = m_accountToUse->currentTask(); |                 auto task = m_accountToUse->currentTask(); | ||||||
| @@ -288,37 +256,24 @@ void LaunchController::login() { | |||||||
|             */ |             */ | ||||||
|             case AccountState::Expired: { |             case AccountState::Expired: { | ||||||
|                 auto errorString = tr("The account has expired and needs to be logged into manually again."); |                 auto errorString = tr("The account has expired and needs to be logged into manually again."); | ||||||
|                 QMessageBox::warning( |                 QMessageBox::warning(m_parentWidget, tr("Account refresh failed"), errorString, QMessageBox::StandardButton::Ok, | ||||||
|                     m_parentWidget, |                                      QMessageBox::StandardButton::Ok); | ||||||
|                     tr("Account refresh failed"), |  | ||||||
|                     errorString, |  | ||||||
|                     QMessageBox::StandardButton::Ok, |  | ||||||
|                     QMessageBox::StandardButton::Ok |  | ||||||
|                 ); |  | ||||||
|                 emitFailed(errorString); |                 emitFailed(errorString); | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
|             case AccountState::Disabled: { |             case AccountState::Disabled: { | ||||||
|                 auto errorString = tr("The launcher's client identification has changed. Please remove this account and add it again."); |                 auto errorString = tr("The launcher's client identification has changed. Please remove this account and add it again."); | ||||||
|                 QMessageBox::warning( |                 QMessageBox::warning(m_parentWidget, tr("Client identification changed"), errorString, QMessageBox::StandardButton::Ok, | ||||||
|                         m_parentWidget, |                                      QMessageBox::StandardButton::Ok); | ||||||
|                         tr("Client identification changed"), |  | ||||||
|                         errorString, |  | ||||||
|                         QMessageBox::StandardButton::Ok, |  | ||||||
|                         QMessageBox::StandardButton::Ok |  | ||||||
|                 ); |  | ||||||
|                 emitFailed(errorString); |                 emitFailed(errorString); | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
|             case AccountState::Gone: { |             case AccountState::Gone: { | ||||||
|                 auto errorString = tr("The account no longer exists on the servers. It may have been migrated, in which case please add the new account you migrated this one to."); |                 auto errorString = | ||||||
|                 QMessageBox::warning( |                     tr("The account no longer exists on the servers. It may have been migrated, in which case please add the new account " | ||||||
|                     m_parentWidget, |                        "you migrated this one to."); | ||||||
|                     tr("Account gone"), |                 QMessageBox::warning(m_parentWidget, tr("Account gone"), errorString, QMessageBox::StandardButton::Ok, | ||||||
|                     errorString, |                                      QMessageBox::StandardButton::Ok); | ||||||
|                     QMessageBox::StandardButton::Ok, |  | ||||||
|                     QMessageBox::StandardButton::Ok |  | ||||||
|                 ); |  | ||||||
|                 emitFailed(errorString); |                 emitFailed(errorString); | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
| @@ -332,24 +287,21 @@ void LaunchController::launchInstance() | |||||||
|     Q_ASSERT_X(m_instance != NULL, "launchInstance", "instance is NULL"); |     Q_ASSERT_X(m_instance != NULL, "launchInstance", "instance is NULL"); | ||||||
|     Q_ASSERT_X(m_session.get() != nullptr, "launchInstance", "session is NULL"); |     Q_ASSERT_X(m_session.get() != nullptr, "launchInstance", "session is NULL"); | ||||||
|  |  | ||||||
|     if(!m_instance->reloadSettings()) |     if (!m_instance->reloadSettings()) { | ||||||
|     { |  | ||||||
|         QMessageBox::critical(m_parentWidget, tr("Error!"), tr("Couldn't load the instance profile.")); |         QMessageBox::critical(m_parentWidget, tr("Error!"), tr("Couldn't load the instance profile.")); | ||||||
|         emitFailed(tr("Couldn't load the instance profile.")); |         emitFailed(tr("Couldn't load the instance profile.")); | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     m_launcher = m_instance->createLaunchTask(m_session, m_serverToJoin); |     m_launcher = m_instance->createLaunchTask(m_session, m_serverToJoin); | ||||||
|     if (!m_launcher) |     if (!m_launcher) { | ||||||
|     { |  | ||||||
|         emitFailed(tr("Couldn't instantiate a launcher.")); |         emitFailed(tr("Couldn't instantiate a launcher.")); | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     auto console = qobject_cast<InstanceWindow*>(m_parentWidget); |     auto console = qobject_cast<InstanceWindow*>(m_parentWidget); | ||||||
|     auto showConsole = m_instance->settings()->get("ShowConsole").toBool(); |     auto showConsole = m_instance->settings()->get("ShowConsole").toBool(); | ||||||
|     if(!console && showConsole) |     if (!console && showConsole) { | ||||||
|     { |  | ||||||
|         APPLICATION->showInstanceWindow(m_instance); |         APPLICATION->showInstanceWindow(m_instance); | ||||||
|     } |     } | ||||||
|     connect(m_launcher.get(), &LaunchTask::readyForLaunch, this, &LaunchController::readyForLaunch); |     connect(m_launcher.get(), &LaunchTask::readyForLaunch, this, &LaunchController::readyForLaunch); | ||||||
| @@ -387,11 +339,13 @@ void LaunchController::launchInstance() | |||||||
|         online_mode = m_demo ? "demo" : "offline"; |         online_mode = m_demo ? "demo" : "offline"; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     m_launcher->prependStep(makeShared<TextPrint>(m_launcher.get(), "Launched instance in " + online_mode + " mode\n", MessageLevel::Launcher)); |     m_launcher->prependStep( | ||||||
|  |         makeShared<TextPrint>(m_launcher.get(), "Launched instance in " + online_mode + " mode\n", MessageLevel::Launcher)); | ||||||
|  |  | ||||||
|     // Prepend Version |     // Prepend Version | ||||||
|     { |     { | ||||||
|         auto versionString = QString("%1 version: %2 (%3)").arg(BuildConfig.LAUNCHER_DISPLAYNAME, BuildConfig.printableVersionString(), BuildConfig.BUILD_PLATFORM); |         auto versionString = QString("%1 version: %2 (%3)") | ||||||
|  |                                  .arg(BuildConfig.LAUNCHER_DISPLAYNAME, BuildConfig.printableVersionString(), BuildConfig.BUILD_PLATFORM); | ||||||
|         m_launcher->prependStep(makeShared<TextPrint>(m_launcher.get(), versionString + "\n\n", MessageLevel::Launcher)); |         m_launcher->prependStep(makeShared<TextPrint>(m_launcher.get(), versionString + "\n\n", MessageLevel::Launcher)); | ||||||
|     } |     } | ||||||
|     m_launcher->start(); |     m_launcher->start(); | ||||||
| @@ -399,15 +353,13 @@ void LaunchController::launchInstance() | |||||||
|  |  | ||||||
| void LaunchController::readyForLaunch() | void LaunchController::readyForLaunch() | ||||||
| { | { | ||||||
|     if (!m_profiler) |     if (!m_profiler) { | ||||||
|     { |  | ||||||
|         m_launcher->proceed(); |         m_launcher->proceed(); | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     QString error; |     QString error; | ||||||
|     if (!m_profiler->check(&error)) |     if (!m_profiler->check(&error)) { | ||||||
|     { |  | ||||||
|         m_launcher->abort(); |         m_launcher->abort(); | ||||||
|         QMessageBox::critical(m_parentWidget, tr("Error!"), tr("Couldn't start profiler: %1").arg(error)); |         QMessageBox::critical(m_parentWidget, tr("Error!"), tr("Couldn't start profiler: %1").arg(error)); | ||||||
|         emitFailed("Profiler startup failed!"); |         emitFailed("Profiler startup failed!"); | ||||||
| @@ -415,12 +367,12 @@ void LaunchController::readyForLaunch() | |||||||
|     } |     } | ||||||
|     BaseProfiler* profilerInstance = m_profiler->createProfiler(m_launcher->instance(), this); |     BaseProfiler* profilerInstance = m_profiler->createProfiler(m_launcher->instance(), this); | ||||||
|  |  | ||||||
|     connect(profilerInstance, &BaseProfiler::readyToLaunch, [this](const QString & message) |     connect(profilerInstance, &BaseProfiler::readyToLaunch, [this](const QString& message) { | ||||||
|     { |  | ||||||
|         QMessageBox msg; |         QMessageBox msg; | ||||||
|         msg.setText(tr("The game launch is delayed until you press the " |         msg.setText(tr("The game launch is delayed until you press the " | ||||||
|                        "button. This is the right time to setup the profiler, as the " |                        "button. This is the right time to setup the profiler, as the " | ||||||
|                         "profiler server is running now.\n\n%1").arg(message)); |                        "profiler server is running now.\n\n%1") | ||||||
|  |                         .arg(message)); | ||||||
|         msg.setWindowTitle(tr("Waiting.")); |         msg.setWindowTitle(tr("Waiting.")); | ||||||
|         msg.setIcon(QMessageBox::Information); |         msg.setIcon(QMessageBox::Information); | ||||||
|         msg.addButton(tr("Launch"), QMessageBox::AcceptRole); |         msg.addButton(tr("Launch"), QMessageBox::AcceptRole); | ||||||
| @@ -428,8 +380,7 @@ void LaunchController::readyForLaunch() | |||||||
|         msg.exec(); |         msg.exec(); | ||||||
|         m_launcher->proceed(); |         m_launcher->proceed(); | ||||||
|     }); |     }); | ||||||
|     connect(profilerInstance, &BaseProfiler::abortLaunch, [this](const QString & message) |     connect(profilerInstance, &BaseProfiler::abortLaunch, [this](const QString& message) { | ||||||
|     { |  | ||||||
|         QMessageBox msg; |         QMessageBox msg; | ||||||
|         msg.setText(tr("Couldn't start the profiler: %1").arg(message)); |         msg.setText(tr("Couldn't start the profiler: %1").arg(message)); | ||||||
|         msg.setWindowTitle(tr("Error")); |         msg.setWindowTitle(tr("Error")); | ||||||
| @@ -450,8 +401,7 @@ void LaunchController::onSucceeded() | |||||||
|  |  | ||||||
| void LaunchController::onFailed(QString reason) | void LaunchController::onFailed(QString reason) | ||||||
| { | { | ||||||
|     if(m_instance->settings()->get("ShowConsoleOnError").toBool()) |     if (m_instance->settings()->get("ShowConsoleOnError").toBool()) { | ||||||
|     { |  | ||||||
|         APPLICATION->showInstanceWindow(m_instance, "console"); |         APPLICATION->showInstanceWindow(m_instance, "console"); | ||||||
|     } |     } | ||||||
|     emitFailed(reason); |     emitFailed(reason); | ||||||
| @@ -467,21 +417,18 @@ void LaunchController::onProgressRequested(Task* task) | |||||||
|  |  | ||||||
| bool LaunchController::abort() | bool LaunchController::abort() | ||||||
| { | { | ||||||
|     if(!m_launcher) |     if (!m_launcher) { | ||||||
|     { |  | ||||||
|         return true; |         return true; | ||||||
|     } |     } | ||||||
|     if(!m_launcher->canAbort()) |     if (!m_launcher->canAbort()) { | ||||||
|     { |  | ||||||
|         return false; |         return false; | ||||||
|     } |     } | ||||||
|     auto response = CustomMessageBox::selectable( |     auto response = CustomMessageBox::selectable(m_parentWidget, tr("Kill Minecraft?"), | ||||||
|             m_parentWidget, tr("Kill Minecraft?"), |  | ||||||
|                                                  tr("This can cause the instance to get corrupted and should only be used if Minecraft " |                                                  tr("This can cause the instance to get corrupted and should only be used if Minecraft " | ||||||
|                                                     "is frozen for some reason"), |                                                     "is frozen for some reason"), | ||||||
|             QMessageBox::Question, QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes)->exec(); |                                                  QMessageBox::Question, QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes) | ||||||
|     if (response == QMessageBox::Yes) |                         ->exec(); | ||||||
|     { |     if (response == QMessageBox::Yes) { | ||||||
|         return m_launcher->abort(); |         return m_launcher->abort(); | ||||||
|     } |     } | ||||||
|     return false; |     return false; | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| // SPDX-License-Identifier: GPL-3.0-only | // SPDX-License-Identifier: GPL-3.0-only | ||||||
| /* | /* | ||||||
|  *  PolyMC - Minecraft Launcher |  *  Prism Launcher - Minecraft Launcher | ||||||
|  *  Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net> |  *  Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net> | ||||||
|  * |  * | ||||||
|  *  This program is free software: you can redistribute it and/or modify |  *  This program is free software: you can redistribute it and/or modify | ||||||
| @@ -34,16 +34,15 @@ | |||||||
|  */ |  */ | ||||||
|  |  | ||||||
| #pragma once | #pragma once | ||||||
| #include <QObject> |  | ||||||
| #include <BaseInstance.h> | #include <BaseInstance.h> | ||||||
| #include <tools/BaseProfiler.h> | #include <tools/BaseProfiler.h> | ||||||
|  | #include <QObject> | ||||||
|  |  | ||||||
| #include "minecraft/launch/MinecraftServerTarget.h" |  | ||||||
| #include "minecraft/auth/MinecraftAccount.h" | #include "minecraft/auth/MinecraftAccount.h" | ||||||
|  | #include "minecraft/launch/MinecraftServerTarget.h" | ||||||
|  |  | ||||||
| class InstanceWindow; | class InstanceWindow; | ||||||
| class LaunchController: public Task | class LaunchController : public Task { | ||||||
| { |  | ||||||
|     Q_OBJECT |     Q_OBJECT | ||||||
|    public: |    public: | ||||||
|     void executeTask() override; |     void executeTask() override; | ||||||
| @@ -51,42 +50,23 @@ public: | |||||||
|     LaunchController(QObject* parent = nullptr); |     LaunchController(QObject* parent = nullptr); | ||||||
|     virtual ~LaunchController(){}; |     virtual ~LaunchController(){}; | ||||||
|  |  | ||||||
|     void setInstance(InstancePtr instance) { |     void setInstance(InstancePtr instance) { m_instance = instance; } | ||||||
|         m_instance = instance; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     InstancePtr instance() { |     InstancePtr instance() { return m_instance; } | ||||||
|         return m_instance; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     void setOnline(bool online) { |     void setOnline(bool online) { m_online = online; } | ||||||
|         m_online = online; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     void setDemo(bool demo) { |     void setDemo(bool demo) { m_demo = demo; } | ||||||
|         m_demo = demo; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     void setProfiler(BaseProfilerFactory *profiler) { |     void setProfiler(BaseProfilerFactory* profiler) { m_profiler = profiler; } | ||||||
|         m_profiler = profiler; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     void setParentWidget(QWidget * widget) { |     void setParentWidget(QWidget* widget) { m_parentWidget = widget; } | ||||||
|         m_parentWidget = widget; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     void setServerToJoin(MinecraftServerTargetPtr serverToJoin) { |     void setServerToJoin(MinecraftServerTargetPtr serverToJoin) { m_serverToJoin = std::move(serverToJoin); } | ||||||
|         m_serverToJoin = std::move(serverToJoin); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     void setAccountToUse(MinecraftAccountPtr accountToUse) { |     void setAccountToUse(MinecraftAccountPtr accountToUse) { m_accountToUse = std::move(accountToUse); } | ||||||
|         m_accountToUse = std::move(accountToUse); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     QString id() |     QString id() { return m_instance->id(); } | ||||||
|     { |  | ||||||
|         return m_instance->id(); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     bool abort() override; |     bool abort() override; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -51,8 +51,7 @@ LoggedProcess::LoggedProcess(QObject *parent) : QProcess(parent) | |||||||
|  |  | ||||||
| LoggedProcess::~LoggedProcess() | LoggedProcess::~LoggedProcess() | ||||||
| { | { | ||||||
|     if(m_is_detachable) |     if (m_is_detachable) { | ||||||
|     { |  | ||||||
|         setProcessState(QProcess::NotRunning); |         setProcessState(QProcess::NotRunning); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -95,16 +94,12 @@ void LoggedProcess::on_exit(int exit_code, QProcess::ExitStatus status) | |||||||
|     m_exit_code = exit_code; |     m_exit_code = exit_code; | ||||||
|  |  | ||||||
|     // based on state, send signals |     // based on state, send signals | ||||||
|     if (!m_is_aborting) |     if (!m_is_aborting) { | ||||||
|     { |         if (status == QProcess::NormalExit) { | ||||||
|         if (status == QProcess::NormalExit) |  | ||||||
|         { |  | ||||||
|             //: Message displayed on instance exit |             //: Message displayed on instance exit | ||||||
|             emit log({ tr("Process exited with code %1.").arg(exit_code) }, MessageLevel::Launcher); |             emit log({ tr("Process exited with code %1.").arg(exit_code) }, MessageLevel::Launcher); | ||||||
|             changeState(LoggedProcess::Finished); |             changeState(LoggedProcess::Finished); | ||||||
|         } |         } else { | ||||||
|         else |  | ||||||
|         { |  | ||||||
|             //: Message displayed on instance crashed |             //: Message displayed on instance crashed | ||||||
|             if (exit_code == -1) |             if (exit_code == -1) | ||||||
|                 emit log({ tr("Process crashed.") }, MessageLevel::Launcher); |                 emit log({ tr("Process crashed.") }, MessageLevel::Launcher); | ||||||
| @@ -112,9 +107,7 @@ void LoggedProcess::on_exit(int exit_code, QProcess::ExitStatus status) | |||||||
|                 emit log({ tr("Process crashed with exitcode %1.").arg(exit_code) }, MessageLevel::Launcher); |                 emit log({ tr("Process crashed with exitcode %1.").arg(exit_code) }, MessageLevel::Launcher); | ||||||
|             changeState(LoggedProcess::Crashed); |             changeState(LoggedProcess::Crashed); | ||||||
|         } |         } | ||||||
|     } |     } else { | ||||||
|     else |  | ||||||
|     { |  | ||||||
|         //: Message displayed after the instance exits due to kill request |         //: Message displayed after the instance exits due to kill request | ||||||
|         emit log({ tr("Process was killed by user.") }, MessageLevel::Error); |         emit log({ tr("Process was killed by user.") }, MessageLevel::Error); | ||||||
|         changeState(LoggedProcess::Aborted); |         changeState(LoggedProcess::Aborted); | ||||||
| @@ -123,10 +116,8 @@ void LoggedProcess::on_exit(int exit_code, QProcess::ExitStatus status) | |||||||
|  |  | ||||||
| void LoggedProcess::on_error(QProcess::ProcessError error) | void LoggedProcess::on_error(QProcess::ProcessError error) | ||||||
| { | { | ||||||
|     switch(error) |     switch (error) { | ||||||
|     { |         case QProcess::FailedToStart: { | ||||||
|         case QProcess::FailedToStart: |  | ||||||
|         { |  | ||||||
|             emit log({ tr("The process failed to start.") }, MessageLevel::Fatal); |             emit log({ tr("The process failed to start.") }, MessageLevel::Fatal); | ||||||
|             changeState(LoggedProcess::FailedToStart); |             changeState(LoggedProcess::FailedToStart); | ||||||
|             break; |             break; | ||||||
| @@ -167,23 +158,18 @@ LoggedProcess::State LoggedProcess::state() const | |||||||
|  |  | ||||||
| void LoggedProcess::on_stateChange(QProcess::ProcessState state) | void LoggedProcess::on_stateChange(QProcess::ProcessState state) | ||||||
| { | { | ||||||
|     switch(state) |     switch (state) { | ||||||
|     { |  | ||||||
|         case QProcess::NotRunning: |         case QProcess::NotRunning: | ||||||
|             break;  // let's not - there are too many that handle this already. |             break;  // let's not - there are too many that handle this already. | ||||||
|         case QProcess::Starting: |         case QProcess::Starting: { | ||||||
|         { |             if (m_state != LoggedProcess::NotRunning) { | ||||||
|             if(m_state != LoggedProcess::NotRunning) |  | ||||||
|             { |  | ||||||
|                 qWarning() << "Wrong state change for process from state" << m_state << "to" << (int)LoggedProcess::Starting; |                 qWarning() << "Wrong state change for process from state" << m_state << "to" << (int)LoggedProcess::Starting; | ||||||
|             } |             } | ||||||
|             changeState(LoggedProcess::Starting); |             changeState(LoggedProcess::Starting); | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|         case QProcess::Running: |         case QProcess::Running: { | ||||||
|         { |             if (m_state != LoggedProcess::Starting) { | ||||||
|             if(m_state != LoggedProcess::Starting) |  | ||||||
|             { |  | ||||||
|                 qWarning() << "Wrong state change for process from state" << m_state << "to" << (int)LoggedProcess::Running; |                 qWarning() << "Wrong state change for process from state" << m_state << "to" << (int)LoggedProcess::Running; | ||||||
|             } |             } | ||||||
|             changeState(LoggedProcess::Running); |             changeState(LoggedProcess::Running); | ||||||
|   | |||||||
| @@ -43,20 +43,10 @@ | |||||||
|  * This is a basic process. |  * This is a basic process. | ||||||
|  * It has line-based logging support and hides some of the nasty bits. |  * It has line-based logging support and hides some of the nasty bits. | ||||||
|  */ |  */ | ||||||
| class LoggedProcess : public QProcess | class LoggedProcess : public QProcess { | ||||||
| { |  | ||||||
|     Q_OBJECT |     Q_OBJECT | ||||||
|    public: |    public: | ||||||
|     enum State |     enum State { NotRunning, Starting, FailedToStart, Running, Finished, Crashed, Aborted }; | ||||||
|     { |  | ||||||
|         NotRunning, |  | ||||||
|         Starting, |  | ||||||
|         FailedToStart, |  | ||||||
|         Running, |  | ||||||
|         Finished, |  | ||||||
|         Crashed, |  | ||||||
|         Aborted |  | ||||||
|     }; |  | ||||||
|  |  | ||||||
|    public: |    public: | ||||||
|     explicit LoggedProcess(QObject* parent = 0); |     explicit LoggedProcess(QObject* parent = 0); | ||||||
| @@ -77,7 +67,6 @@ public slots: | |||||||
|      */ |      */ | ||||||
|     void kill(); |     void kill(); | ||||||
|  |  | ||||||
|  |  | ||||||
|    private slots: |    private slots: | ||||||
|     void on_stdErr(); |     void on_stdErr(); | ||||||
|     void on_stdOut(); |     void on_stdOut(); | ||||||
|   | |||||||
| @@ -17,30 +17,29 @@ | |||||||
|  |  | ||||||
| #include <MMCTime.h> | #include <MMCTime.h> | ||||||
|  |  | ||||||
| #include <QObject> |  | ||||||
| #include <QDateTime> | #include <QDateTime> | ||||||
|  | #include <QObject> | ||||||
| #include <QTextStream> | #include <QTextStream> | ||||||
|  |  | ||||||
| QString Time::prettifyDuration(int64_t duration) { | QString Time::prettifyDuration(int64_t duration) | ||||||
|  | { | ||||||
|     int seconds = (int)(duration % 60); |     int seconds = (int)(duration % 60); | ||||||
|     duration /= 60; |     duration /= 60; | ||||||
|     int minutes = (int)(duration % 60); |     int minutes = (int)(duration % 60); | ||||||
|     duration /= 60; |     duration /= 60; | ||||||
|     int hours = (int)(duration % 24); |     int hours = (int)(duration % 24); | ||||||
|     int days = (int)(duration / 24); |     int days = (int)(duration / 24); | ||||||
|     if((hours == 0)&&(days == 0)) |     if ((hours == 0) && (days == 0)) { | ||||||
|     { |  | ||||||
|         return QObject::tr("%1min %2s").arg(minutes).arg(seconds); |         return QObject::tr("%1min %2s").arg(minutes).arg(seconds); | ||||||
|     } |     } | ||||||
|     if (days == 0) |     if (days == 0) { | ||||||
|     { |  | ||||||
|         return QObject::tr("%1h %2min").arg(hours).arg(minutes); |         return QObject::tr("%1h %2min").arg(hours).arg(minutes); | ||||||
|     } |     } | ||||||
|     return QObject::tr("%1d %2h %3min").arg(days).arg(hours).arg(minutes); |     return QObject::tr("%1d %2h %3min").arg(days).arg(hours).arg(minutes); | ||||||
| } | } | ||||||
|  |  | ||||||
| QString Time::humanReadableDuration(double duration, int precision) { | QString Time::humanReadableDuration(double duration, int precision) | ||||||
|  | { | ||||||
|     using days = std::chrono::duration<int, std::ratio<86400>>; |     using days = std::chrono::duration<int, std::ratio<86400>>; | ||||||
|  |  | ||||||
|     QString outStr; |     QString outStr; | ||||||
|   | |||||||
| @@ -31,4 +31,4 @@ QString prettifyDuration(int64_t duration); | |||||||
|  * @return QString |  * @return QString | ||||||
|  */ |  */ | ||||||
| QString humanReadableDuration(double duration, int precision = 0); | QString humanReadableDuration(double duration, int precision = 0); | ||||||
| } | }  // namespace Time | ||||||
|   | |||||||
| @@ -1,10 +1,10 @@ | |||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
| #include <QCoreApplication> | #include <QCoreApplication> | ||||||
|  | #include <QDebug> | ||||||
| #include <QPixmapCache> | #include <QPixmapCache> | ||||||
| #include <QThread> | #include <QThread> | ||||||
| #include <QTime> | #include <QTime> | ||||||
| #include <QDebug> |  | ||||||
|  |  | ||||||
| #define GET_TYPE()                                                          \ | #define GET_TYPE()                                                          \ | ||||||
|     Qt::ConnectionType type;                                                \ |     Qt::ConnectionType type;                                                \ | ||||||
|   | |||||||
| @@ -16,15 +16,15 @@ | |||||||
|  *  along with this program.  If not, see <https://www.gnu.org/licenses/>. |  *  along with this program.  If not, see <https://www.gnu.org/licenses/>. | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| #include <QStringList> |  | ||||||
| #include <QDir> | #include <QDir> | ||||||
| #include <QString> | #include <QString> | ||||||
|  | #include <QStringList> | ||||||
| #include <QSysInfo> | #include <QSysInfo> | ||||||
| #include <QtGlobal> | #include <QtGlobal> | ||||||
|  |  | ||||||
| #include "MangoHud.h" |  | ||||||
| #include "FileSystem.h" | #include "FileSystem.h" | ||||||
| #include "Json.h" | #include "Json.h" | ||||||
|  | #include "MangoHud.h" | ||||||
|  |  | ||||||
| namespace MangoHud { | namespace MangoHud { | ||||||
|  |  | ||||||
|   | |||||||
| @@ -18,7 +18,7 @@ | |||||||
|  |  | ||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
| #include <QString> |  | ||||||
| #include <cmark.h> | #include <cmark.h> | ||||||
|  | #include <QString> | ||||||
|  |  | ||||||
| QString markdownToHTML(const QString& markdown); | QString markdownToHTML(const QString& markdown); | ||||||
| @@ -26,8 +26,7 @@ MessageLevel::Enum MessageLevel::fromLine(QString &line) | |||||||
| { | { | ||||||
|     // Level prefix |     // Level prefix | ||||||
|     int endmark = line.indexOf("]!"); |     int endmark = line.indexOf("]!"); | ||||||
|     if (line.startsWith("!![") && endmark != -1) |     if (line.startsWith("!![") && endmark != -1) { | ||||||
|     { |  | ||||||
|         auto level = MessageLevel::getLevel(line.left(endmark).mid(3)); |         auto level = MessageLevel::getLevel(line.left(endmark).mid(3)); | ||||||
|         line = line.mid(endmark + 2); |         line = line.mid(endmark + 2); | ||||||
|         return level; |         return level; | ||||||
|   | |||||||
| @@ -6,10 +6,8 @@ | |||||||
|  * @brief the MessageLevel Enum |  * @brief the MessageLevel Enum | ||||||
|  * defines what level a log message is |  * defines what level a log message is | ||||||
|  */ |  */ | ||||||
| namespace MessageLevel | namespace MessageLevel { | ||||||
| { | enum Enum { | ||||||
| enum Enum |  | ||||||
| { |  | ||||||
|     Unknown,  /**< No idea what this is or where it came from */ |     Unknown,  /**< No idea what this is or where it came from */ | ||||||
|     StdOut,   /**< Undetermined stderr messages */ |     StdOut,   /**< Undetermined stderr messages */ | ||||||
|     StdErr,   /**< Undetermined stdout messages */ |     StdErr,   /**< Undetermined stdout messages */ | ||||||
| @@ -25,4 +23,4 @@ MessageLevel::Enum getLevel(const QString &levelName); | |||||||
|  |  | ||||||
| /* Get message level from a line. Line is modified if it was successful. */ | /* Get message level from a line. Line is modified if it was successful. */ | ||||||
| MessageLevel::Enum fromLine(QString& line); | MessageLevel::Enum fromLine(QString& line); | ||||||
| } | }  // namespace MessageLevel | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| // SPDX-License-Identifier: GPL-3.0-only | // SPDX-License-Identifier: GPL-3.0-only | ||||||
| /* | /* | ||||||
|  *  PolyMC - Minecraft Launcher |  *  Prism Launcher - Minecraft Launcher | ||||||
|  *  Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net> |  *  Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net> | ||||||
|  * |  * | ||||||
|  *  This program is free software: you can redistribute it and/or modify |  *  This program is free software: you can redistribute it and/or modify | ||||||
| @@ -37,8 +37,7 @@ | |||||||
| #include "BaseInstance.h" | #include "BaseInstance.h" | ||||||
| #include "launch/LaunchTask.h" | #include "launch/LaunchTask.h" | ||||||
|  |  | ||||||
| class NullInstance: public BaseInstance | class NullInstance : public BaseInstance { | ||||||
| { |  | ||||||
|     Q_OBJECT |     Q_OBJECT | ||||||
|    public: |    public: | ||||||
|     NullInstance(SettingsObjectPtr globalSettings, SettingsObjectPtr settings, const QString& rootDir) |     NullInstance(SettingsObjectPtr globalSettings, SettingsObjectPtr settings, const QString& rootDir) | ||||||
| @@ -47,78 +46,29 @@ public: | |||||||
|         setVersionBroken(true); |         setVersionBroken(true); | ||||||
|     } |     } | ||||||
|     virtual ~NullInstance(){}; |     virtual ~NullInstance(){}; | ||||||
|     void saveNow() override |     void saveNow() override {} | ||||||
|     { |     void loadSpecificSettings() override { setSpecificSettingsLoaded(true); } | ||||||
|     } |     QString getStatusbarDescription() override { return tr("Unknown instance type"); }; | ||||||
|     void loadSpecificSettings() override |     QSet<QString> traits() const override { return {}; }; | ||||||
|     { |     QString instanceConfigFolder() const override { return instanceRoot(); }; | ||||||
|         setSpecificSettingsLoaded(true); |     shared_qobject_ptr<LaunchTask> createLaunchTask(AuthSessionPtr, MinecraftServerTargetPtr) override { return nullptr; } | ||||||
|     } |     shared_qobject_ptr<Task> createUpdateTask(Net::Mode mode) override { return nullptr; } | ||||||
|     QString getStatusbarDescription() override |     QProcessEnvironment createEnvironment() override { return QProcessEnvironment(); } | ||||||
|     { |     QProcessEnvironment createLaunchEnvironment() override { return QProcessEnvironment(); } | ||||||
|         return tr("Unknown instance type"); |     QMap<QString, QString> getVariables() override { return QMap<QString, QString>(); } | ||||||
|     }; |     IPathMatcher::Ptr getLogFileMatcher() override { return nullptr; } | ||||||
|     QSet< QString > traits() const override |     QString getLogFileRoot() override { return instanceRoot(); } | ||||||
|     { |     QString typeName() const override { return "Null"; } | ||||||
|         return {}; |     bool canExport() const override { return false; } | ||||||
|     }; |     bool canEdit() const override { return false; } | ||||||
|     QString instanceConfigFolder() const override |     bool canLaunch() const override { return false; } | ||||||
|     { |  | ||||||
|         return instanceRoot(); |  | ||||||
|     }; |  | ||||||
|     shared_qobject_ptr<LaunchTask> createLaunchTask(AuthSessionPtr, MinecraftServerTargetPtr) override |  | ||||||
|     { |  | ||||||
|         return nullptr; |  | ||||||
|     } |  | ||||||
|     shared_qobject_ptr< Task > createUpdateTask(Net::Mode mode) override |  | ||||||
|     { |  | ||||||
|         return nullptr; |  | ||||||
|     } |  | ||||||
|     QProcessEnvironment createEnvironment() override |  | ||||||
|     { |  | ||||||
|         return QProcessEnvironment(); |  | ||||||
|     } |  | ||||||
|     QProcessEnvironment createLaunchEnvironment() override |  | ||||||
|     { |  | ||||||
|         return QProcessEnvironment(); |  | ||||||
|     } |  | ||||||
|     QMap<QString, QString> getVariables() override |  | ||||||
|     { |  | ||||||
|         return QMap<QString, QString>(); |  | ||||||
|     } |  | ||||||
|     IPathMatcher::Ptr getLogFileMatcher() override |  | ||||||
|     { |  | ||||||
|         return nullptr; |  | ||||||
|     } |  | ||||||
|     QString getLogFileRoot() override |  | ||||||
|     { |  | ||||||
|         return instanceRoot(); |  | ||||||
|     } |  | ||||||
|     QString typeName() const override |  | ||||||
|     { |  | ||||||
|         return "Null"; |  | ||||||
|     } |  | ||||||
|     bool canExport() const override |  | ||||||
|     { |  | ||||||
|         return false; |  | ||||||
|     } |  | ||||||
|     bool canEdit() const override |  | ||||||
|     { |  | ||||||
|         return false; |  | ||||||
|     } |  | ||||||
|     bool canLaunch() const override |  | ||||||
|     { |  | ||||||
|         return false; |  | ||||||
|     } |  | ||||||
|     QStringList verboseDescription(AuthSessionPtr session, MinecraftServerTargetPtr serverToJoin) override |     QStringList verboseDescription(AuthSessionPtr session, MinecraftServerTargetPtr serverToJoin) override | ||||||
|     { |     { | ||||||
|         QStringList out; |         QStringList out; | ||||||
|         out << "Null instance - placeholder."; |         out << "Null instance - placeholder."; | ||||||
|         return out; |         return out; | ||||||
|     } |     } | ||||||
|     QString modsRoot() const override { |     QString modsRoot() const override { return QString(); } | ||||||
|         return QString(); |  | ||||||
|     } |  | ||||||
|     void updateRuntimeContext() |     void updateRuntimeContext() | ||||||
|     { |     { | ||||||
|         // NOOP |         // NOOP | ||||||
|   | |||||||
| @@ -1,41 +1,29 @@ | |||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
| enum class ProblemSeverity | #include <QList> | ||||||
| { | #include <QString> | ||||||
|     None, |  | ||||||
|     Warning, |  | ||||||
|     Error |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| struct PatchProblem | enum class ProblemSeverity { None, Warning, Error }; | ||||||
| { |  | ||||||
|  | struct PatchProblem { | ||||||
|     ProblemSeverity m_severity; |     ProblemSeverity m_severity; | ||||||
|     QString m_description; |     QString m_description; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| class ProblemProvider | class ProblemProvider { | ||||||
| { |  | ||||||
|    public: |    public: | ||||||
|     virtual ~ProblemProvider(){}; |     virtual ~ProblemProvider(){}; | ||||||
|     virtual const QList<PatchProblem> getProblems() const = 0; |     virtual const QList<PatchProblem> getProblems() const = 0; | ||||||
|     virtual ProblemSeverity getProblemSeverity() const = 0; |     virtual ProblemSeverity getProblemSeverity() const = 0; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| class ProblemContainer : public ProblemProvider | class ProblemContainer : public ProblemProvider { | ||||||
| { |  | ||||||
|    public: |    public: | ||||||
|     const QList<PatchProblem> getProblems() const override |     const QList<PatchProblem> getProblems() const override { return m_problems; } | ||||||
|     { |     ProblemSeverity getProblemSeverity() const override { return m_problemSeverity; } | ||||||
|         return m_problems; |  | ||||||
|     } |  | ||||||
|     ProblemSeverity getProblemSeverity() const override |  | ||||||
|     { |  | ||||||
|         return m_problemSeverity; |  | ||||||
|     } |  | ||||||
|     virtual void addProblem(ProblemSeverity severity, const QString& description) |     virtual void addProblem(ProblemSeverity severity, const QString& description) | ||||||
|     { |     { | ||||||
|         if(severity > m_problemSeverity) |         if (severity > m_problemSeverity) { | ||||||
|         { |  | ||||||
|             m_problemSeverity = severity; |             m_problemSeverity = severity; | ||||||
|         } |         } | ||||||
|         m_problems.append({ severity, description }); |         m_problems.append({ severity, description }); | ||||||
|   | |||||||
| @@ -36,35 +36,34 @@ | |||||||
|  |  | ||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
|  |  | ||||||
| #include <QVariant> |  | ||||||
| #include <QList> | #include <QList> | ||||||
|  | #include <QVariant> | ||||||
|  |  | ||||||
| namespace QVariantUtils { | namespace QVariantUtils { | ||||||
|  |  | ||||||
| template <typename T> | template <typename T> | ||||||
| inline QList<T> toList(QVariant src) { | inline QList<T> toList(QVariant src) | ||||||
|  | { | ||||||
|     QVariantList variantList = src.toList(); |     QVariantList variantList = src.toList(); | ||||||
|  |  | ||||||
|     QList<T> list_t; |     QList<T> list_t; | ||||||
|     list_t.reserve(variantList.size()); |     list_t.reserve(variantList.size()); | ||||||
|     for (const QVariant& v : variantList) |     for (const QVariant& v : variantList) { | ||||||
|     { |  | ||||||
|         list_t.append(v.value<T>()); |         list_t.append(v.value<T>()); | ||||||
|     } |     } | ||||||
|     return list_t; |     return list_t; | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename T> | template <typename T> | ||||||
| inline QVariant fromList(QList<T> val) { | inline QVariant fromList(QList<T> val) | ||||||
|  | { | ||||||
|     QVariantList variantList; |     QVariantList variantList; | ||||||
|     variantList.reserve(val.size()); |     variantList.reserve(val.size()); | ||||||
|     for (const T& v : val) |     for (const T& v : val) { | ||||||
|     { |  | ||||||
|         variantList.append(v); |         variantList.append(v); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     return variantList; |     return variantList; | ||||||
| } | } | ||||||
|  |  | ||||||
| } | }  // namespace QVariantUtils | ||||||
| @@ -1,12 +1,11 @@ | |||||||
| #pragma once | #pragma once | ||||||
| #include <QWriteLocker> |  | ||||||
| #include <QReadLocker> |  | ||||||
| #include <QMap> | #include <QMap> | ||||||
|  | #include <QReadLocker> | ||||||
| #include <QSet> | #include <QSet> | ||||||
|  | #include <QWriteLocker> | ||||||
|  |  | ||||||
| template <typename K, typename V> | template <typename K, typename V> | ||||||
| class RWStorage | class RWStorage { | ||||||
| { |  | ||||||
|    public: |    public: | ||||||
|     void add(K key, V value) |     void add(K key, V value) | ||||||
|     { |     { | ||||||
| @@ -17,21 +16,19 @@ public: | |||||||
|     V get(K key) |     V get(K key) | ||||||
|     { |     { | ||||||
|         QReadLocker l(&lock); |         QReadLocker l(&lock); | ||||||
|         if(cache.contains(key)) |         if (cache.contains(key)) { | ||||||
|         { |  | ||||||
|             return cache[key]; |             return cache[key]; | ||||||
|         } |         } else | ||||||
|         else return V(); |             return V(); | ||||||
|     } |     } | ||||||
|     bool get(K key, V& value) |     bool get(K key, V& value) | ||||||
|     { |     { | ||||||
|         QReadLocker l(&lock); |         QReadLocker l(&lock); | ||||||
|         if(cache.contains(key)) |         if (cache.contains(key)) { | ||||||
|         { |  | ||||||
|             value = cache[key]; |             value = cache[key]; | ||||||
|             return true; |             return true; | ||||||
|         } |         } else | ||||||
|         else return false; |             return false; | ||||||
|     } |     } | ||||||
|     bool has(K key) |     bool has(K key) | ||||||
|     { |     { | ||||||
| @@ -48,8 +45,7 @@ public: | |||||||
|     void setStale(K key) |     void setStale(K key) | ||||||
|     { |     { | ||||||
|         QWriteLocker l(&lock); |         QWriteLocker l(&lock); | ||||||
|         if(cache.contains(key)) |         if (cache.contains(key)) { | ||||||
|         { |  | ||||||
|             stale_entries.insert(key); |             stale_entries.insert(key); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @@ -59,6 +55,7 @@ public: | |||||||
|         cache.clear(); |         cache.clear(); | ||||||
|         stale_entries.clear(); |         stale_entries.clear(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|    private: |    private: | ||||||
|     QReadWriteLock lock; |     QReadWriteLock lock; | ||||||
|     QMap<K, V> cache; |     QMap<K, V> cache; | ||||||
|   | |||||||
| @@ -1,15 +1,12 @@ | |||||||
| #include "RecursiveFileSystemWatcher.h" | #include "RecursiveFileSystemWatcher.h" | ||||||
|  |  | ||||||
| #include <QRegularExpression> |  | ||||||
| #include <QDebug> | #include <QDebug> | ||||||
|  | #include <QRegularExpression> | ||||||
|  |  | ||||||
| RecursiveFileSystemWatcher::RecursiveFileSystemWatcher(QObject *parent) | RecursiveFileSystemWatcher::RecursiveFileSystemWatcher(QObject* parent) : QObject(parent), m_watcher(new QFileSystemWatcher(this)) | ||||||
|     : QObject(parent), m_watcher(new QFileSystemWatcher(this)) |  | ||||||
| { | { | ||||||
|     connect(m_watcher, &QFileSystemWatcher::fileChanged, this, |     connect(m_watcher, &QFileSystemWatcher::fileChanged, this, &RecursiveFileSystemWatcher::fileChange); | ||||||
|             &RecursiveFileSystemWatcher::fileChange); |     connect(m_watcher, &QFileSystemWatcher::directoryChanged, this, &RecursiveFileSystemWatcher::directoryChange); | ||||||
|     connect(m_watcher, &QFileSystemWatcher::directoryChanged, this, |  | ||||||
|             &RecursiveFileSystemWatcher::directoryChange); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| void RecursiveFileSystemWatcher::setRootDir(const QDir& root) | void RecursiveFileSystemWatcher::setRootDir(const QDir& root) | ||||||
| @@ -18,8 +15,7 @@ void RecursiveFileSystemWatcher::setRootDir(const QDir &root) | |||||||
|     disable(); |     disable(); | ||||||
|     m_root = root; |     m_root = root; | ||||||
|     setFiles(scanRecursive(m_root)); |     setFiles(scanRecursive(m_root)); | ||||||
|     if (wasEnabled) |     if (wasEnabled) { | ||||||
|     { |  | ||||||
|         enable(); |         enable(); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -28,16 +24,14 @@ void RecursiveFileSystemWatcher::setWatchFiles(const bool watchFiles) | |||||||
|     bool wasEnabled = m_isEnabled; |     bool wasEnabled = m_isEnabled; | ||||||
|     disable(); |     disable(); | ||||||
|     m_watchFiles = watchFiles; |     m_watchFiles = watchFiles; | ||||||
|     if (wasEnabled) |     if (wasEnabled) { | ||||||
|     { |  | ||||||
|         enable(); |         enable(); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| void RecursiveFileSystemWatcher::enable() | void RecursiveFileSystemWatcher::enable() | ||||||
| { | { | ||||||
|     if (m_isEnabled) |     if (m_isEnabled) { | ||||||
|     { |  | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|     Q_ASSERT(m_root != QDir::root()); |     Q_ASSERT(m_root != QDir::root()); | ||||||
| @@ -46,8 +40,7 @@ void RecursiveFileSystemWatcher::enable() | |||||||
| } | } | ||||||
| void RecursiveFileSystemWatcher::disable() | void RecursiveFileSystemWatcher::disable() | ||||||
| { | { | ||||||
|     if (!m_isEnabled) |     if (!m_isEnabled) { | ||||||
|     { |  | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|     m_isEnabled = false; |     m_isEnabled = false; | ||||||
| @@ -57,8 +50,7 @@ void RecursiveFileSystemWatcher::disable() | |||||||
|  |  | ||||||
| void RecursiveFileSystemWatcher::setFiles(const QStringList& files) | void RecursiveFileSystemWatcher::setFiles(const QStringList& files) | ||||||
| { | { | ||||||
|     if (files != m_files) |     if (files != m_files) { | ||||||
|     { |  | ||||||
|         m_files = files; |         m_files = files; | ||||||
|         emit filesChanged(); |         emit filesChanged(); | ||||||
|     } |     } | ||||||
| @@ -67,14 +59,11 @@ void RecursiveFileSystemWatcher::setFiles(const QStringList &files) | |||||||
| void RecursiveFileSystemWatcher::addFilesToWatcherRecursive(const QDir& dir) | void RecursiveFileSystemWatcher::addFilesToWatcherRecursive(const QDir& dir) | ||||||
| { | { | ||||||
|     m_watcher->addPath(dir.absolutePath()); |     m_watcher->addPath(dir.absolutePath()); | ||||||
|     for (const QString &directory : dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot)) |     for (const QString& directory : dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot)) { | ||||||
|     { |  | ||||||
|         addFilesToWatcherRecursive(dir.absoluteFilePath(directory)); |         addFilesToWatcherRecursive(dir.absoluteFilePath(directory)); | ||||||
|     } |     } | ||||||
|     if (m_watchFiles) |     if (m_watchFiles) { | ||||||
|     { |         for (const QFileInfo& info : dir.entryInfoList(QDir::Files)) { | ||||||
|         for (const QFileInfo &info : dir.entryInfoList(QDir::Files)) |  | ||||||
|         { |  | ||||||
|             m_watcher->addPath(info.absoluteFilePath()); |             m_watcher->addPath(info.absoluteFilePath()); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @@ -82,19 +71,15 @@ void RecursiveFileSystemWatcher::addFilesToWatcherRecursive(const QDir &dir) | |||||||
| QStringList RecursiveFileSystemWatcher::scanRecursive(const QDir& directory) | QStringList RecursiveFileSystemWatcher::scanRecursive(const QDir& directory) | ||||||
| { | { | ||||||
|     QStringList ret; |     QStringList ret; | ||||||
|     if(!m_matcher) |     if (!m_matcher) { | ||||||
|     { |  | ||||||
|         return {}; |         return {}; | ||||||
|     } |     } | ||||||
|     for (const QString &dir : directory.entryList(QDir::Dirs | QDir::NoDotAndDotDot | QDir::Hidden)) |     for (const QString& dir : directory.entryList(QDir::Dirs | QDir::NoDotAndDotDot | QDir::Hidden)) { | ||||||
|     { |  | ||||||
|         ret.append(scanRecursive(directory.absoluteFilePath(dir))); |         ret.append(scanRecursive(directory.absoluteFilePath(dir))); | ||||||
|     } |     } | ||||||
|     for (const QString &file : directory.entryList(QDir::Files | QDir::Hidden)) |     for (const QString& file : directory.entryList(QDir::Files | QDir::Hidden)) { | ||||||
|     { |  | ||||||
|         auto relPath = m_root.relativeFilePath(directory.absoluteFilePath(file)); |         auto relPath = m_root.relativeFilePath(directory.absoluteFilePath(file)); | ||||||
|         if (m_matcher->matches(relPath)) |         if (m_matcher->matches(relPath)) { | ||||||
|         { |  | ||||||
|             ret.append(relPath); |             ret.append(relPath); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -1,37 +1,24 @@ | |||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
| #include <QFileSystemWatcher> |  | ||||||
| #include <QDir> | #include <QDir> | ||||||
|  | #include <QFileSystemWatcher> | ||||||
| #include "pathmatcher/IPathMatcher.h" | #include "pathmatcher/IPathMatcher.h" | ||||||
|  |  | ||||||
| class RecursiveFileSystemWatcher : public QObject | class RecursiveFileSystemWatcher : public QObject { | ||||||
| { |  | ||||||
|     Q_OBJECT |     Q_OBJECT | ||||||
|    public: |    public: | ||||||
|     RecursiveFileSystemWatcher(QObject* parent); |     RecursiveFileSystemWatcher(QObject* parent); | ||||||
|  |  | ||||||
|     void setRootDir(const QDir& root); |     void setRootDir(const QDir& root); | ||||||
|     QDir rootDir() const |     QDir rootDir() const { return m_root; } | ||||||
|     { |  | ||||||
|         return m_root; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     // WARNING: setting this to true may be bad for performance |     // WARNING: setting this to true may be bad for performance | ||||||
|     void setWatchFiles(const bool watchFiles); |     void setWatchFiles(const bool watchFiles); | ||||||
|     bool watchFiles() const |     bool watchFiles() const { return m_watchFiles; } | ||||||
|     { |  | ||||||
|         return m_watchFiles; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     void setMatcher(IPathMatcher::Ptr matcher) |     void setMatcher(IPathMatcher::Ptr matcher) { m_matcher = matcher; } | ||||||
|     { |  | ||||||
|         m_matcher = matcher; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     QStringList files() const |     QStringList files() const { return m_files; } | ||||||
|     { |  | ||||||
|         return m_files; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|    signals: |    signals: | ||||||
|     void filesChanged(); |     void filesChanged(); | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| // SPDX-License-Identifier: GPL-3.0-only | // SPDX-License-Identifier: GPL-3.0-only | ||||||
| /* | /* | ||||||
|  *  PolyMC - Minecraft Launcher |  *  Prism Launcher - Minecraft Launcher | ||||||
|  *  Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net> |  *  Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net> | ||||||
|  * |  * | ||||||
|  *  This program is free software: you can redistribute it and/or modify |  *  This program is free software: you can redistribute it and/or modify | ||||||
|   | |||||||
| @@ -1,26 +1,18 @@ | |||||||
| #pragma once | #pragma once | ||||||
| #include <QString> |  | ||||||
| #include <QMap> | #include <QMap> | ||||||
|  | #include <QString> | ||||||
| #include <QStringList> | #include <QStringList> | ||||||
|  |  | ||||||
| template <char Tseparator> | template <char Tseparator> | ||||||
| class SeparatorPrefixTree | class SeparatorPrefixTree { | ||||||
| { |  | ||||||
|    public: |    public: | ||||||
|     SeparatorPrefixTree(QStringList paths) |     SeparatorPrefixTree(QStringList paths) { insert(paths); } | ||||||
|     { |  | ||||||
|         insert(paths); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     SeparatorPrefixTree(bool contained = false) |     SeparatorPrefixTree(bool contained = false) { m_contained = contained; } | ||||||
|     { |  | ||||||
|         m_contained = contained; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     void insert(QStringList paths) |     void insert(QStringList paths) | ||||||
|     { |     { | ||||||
|         for(auto &path: paths) |         for (auto& path : paths) { | ||||||
|         { |  | ||||||
|             insert(path); |             insert(path); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @@ -29,16 +21,12 @@ public: | |||||||
|     SeparatorPrefixTree& insert(QString path) |     SeparatorPrefixTree& insert(QString path) | ||||||
|     { |     { | ||||||
|         auto sepIndex = path.indexOf(Tseparator); |         auto sepIndex = path.indexOf(Tseparator); | ||||||
|         if(sepIndex == -1) |         if (sepIndex == -1) { | ||||||
|         { |  | ||||||
|             children[path] = SeparatorPrefixTree(true); |             children[path] = SeparatorPrefixTree(true); | ||||||
|             return children[path]; |             return children[path]; | ||||||
|         } |         } else { | ||||||
|         else |  | ||||||
|         { |  | ||||||
|             auto prefix = path.left(sepIndex); |             auto prefix = path.left(sepIndex); | ||||||
|             if(!children.contains(prefix)) |             if (!children.contains(prefix)) { | ||||||
|             { |  | ||||||
|                 children[prefix] = SeparatorPrefixTree(false); |                 children[prefix] = SeparatorPrefixTree(false); | ||||||
|             } |             } | ||||||
|             return children[prefix].insert(path.mid(sepIndex + 1)); |             return children[prefix].insert(path.mid(sepIndex + 1)); | ||||||
| @@ -56,26 +44,20 @@ public: | |||||||
|     bool covers(QString path) const |     bool covers(QString path) const | ||||||
|     { |     { | ||||||
|         // if we found some valid node, it's good enough. the tree covers the path |         // if we found some valid node, it's good enough. the tree covers the path | ||||||
|         if(m_contained) |         if (m_contained) { | ||||||
|         { |  | ||||||
|             return true; |             return true; | ||||||
|         } |         } | ||||||
|         auto sepIndex = path.indexOf(Tseparator); |         auto sepIndex = path.indexOf(Tseparator); | ||||||
|         if(sepIndex == -1) |         if (sepIndex == -1) { | ||||||
|         { |  | ||||||
|             auto found = children.find(path); |             auto found = children.find(path); | ||||||
|             if(found == children.end()) |             if (found == children.end()) { | ||||||
|             { |  | ||||||
|                 return false; |                 return false; | ||||||
|             } |             } | ||||||
|             return (*found).covers(QString()); |             return (*found).covers(QString()); | ||||||
|         } |         } else { | ||||||
|         else |  | ||||||
|         { |  | ||||||
|             auto prefix = path.left(sepIndex); |             auto prefix = path.left(sepIndex); | ||||||
|             auto found = children.find(prefix); |             auto found = children.find(prefix); | ||||||
|             if(found == children.end()) |             if (found == children.end()) { | ||||||
|             { |  | ||||||
|                 return false; |                 return false; | ||||||
|             } |             } | ||||||
|             return (*found).covers(path.mid(sepIndex + 1)); |             return (*found).covers(path.mid(sepIndex + 1)); | ||||||
| @@ -86,38 +68,30 @@ public: | |||||||
|     QString cover(QString path) const |     QString cover(QString path) const | ||||||
|     { |     { | ||||||
|         // if we found some valid node, it's good enough. the tree covers the path |         // if we found some valid node, it's good enough. the tree covers the path | ||||||
|         if(m_contained) |         if (m_contained) { | ||||||
|         { |  | ||||||
|             return QString(""); |             return QString(""); | ||||||
|         } |         } | ||||||
|         auto sepIndex = path.indexOf(Tseparator); |         auto sepIndex = path.indexOf(Tseparator); | ||||||
|         if(sepIndex == -1) |         if (sepIndex == -1) { | ||||||
|         { |  | ||||||
|             auto found = children.find(path); |             auto found = children.find(path); | ||||||
|             if(found == children.end()) |             if (found == children.end()) { | ||||||
|             { |  | ||||||
|                 return QString(); |                 return QString(); | ||||||
|             } |             } | ||||||
|             auto nested = (*found).cover(QString()); |             auto nested = (*found).cover(QString()); | ||||||
|             if(nested.isNull()) |             if (nested.isNull()) { | ||||||
|             { |  | ||||||
|                 return nested; |                 return nested; | ||||||
|             } |             } | ||||||
|             if (nested.isEmpty()) |             if (nested.isEmpty()) | ||||||
|                 return path; |                 return path; | ||||||
|             return path + Tseparator + nested; |             return path + Tseparator + nested; | ||||||
|         } |         } else { | ||||||
|         else |  | ||||||
|         { |  | ||||||
|             auto prefix = path.left(sepIndex); |             auto prefix = path.left(sepIndex); | ||||||
|             auto found = children.find(prefix); |             auto found = children.find(prefix); | ||||||
|             if(found == children.end()) |             if (found == children.end()) { | ||||||
|             { |  | ||||||
|                 return QString(); |                 return QString(); | ||||||
|             } |             } | ||||||
|             auto nested = (*found).cover(path.mid(sepIndex + 1)); |             auto nested = (*found).cover(path.mid(sepIndex + 1)); | ||||||
|             if(nested.isNull()) |             if (nested.isNull()) { | ||||||
|             { |  | ||||||
|                 return nested; |                 return nested; | ||||||
|             } |             } | ||||||
|             if (nested.isEmpty()) |             if (nested.isEmpty()) | ||||||
| @@ -130,21 +104,16 @@ public: | |||||||
|     bool exists(QString path) const |     bool exists(QString path) const | ||||||
|     { |     { | ||||||
|         auto sepIndex = path.indexOf(Tseparator); |         auto sepIndex = path.indexOf(Tseparator); | ||||||
|         if(sepIndex == -1) |         if (sepIndex == -1) { | ||||||
|         { |  | ||||||
|             auto found = children.find(path); |             auto found = children.find(path); | ||||||
|             if(found == children.end()) |             if (found == children.end()) { | ||||||
|             { |  | ||||||
|                 return false; |                 return false; | ||||||
|             } |             } | ||||||
|             return true; |             return true; | ||||||
|         } |         } else { | ||||||
|         else |  | ||||||
|         { |  | ||||||
|             auto prefix = path.left(sepIndex); |             auto prefix = path.left(sepIndex); | ||||||
|             auto found = children.find(prefix); |             auto found = children.find(prefix); | ||||||
|             if(found == children.end()) |             if (found == children.end()) { | ||||||
|             { |  | ||||||
|                 return false; |                 return false; | ||||||
|             } |             } | ||||||
|             return (*found).exists(path.mid(sepIndex + 1)); |             return (*found).exists(path.mid(sepIndex + 1)); | ||||||
| @@ -155,21 +124,16 @@ public: | |||||||
|     const SeparatorPrefixTree* find(QString path) const |     const SeparatorPrefixTree* find(QString path) const | ||||||
|     { |     { | ||||||
|         auto sepIndex = path.indexOf(Tseparator); |         auto sepIndex = path.indexOf(Tseparator); | ||||||
|         if(sepIndex == -1) |         if (sepIndex == -1) { | ||||||
|         { |  | ||||||
|             auto found = children.find(path); |             auto found = children.find(path); | ||||||
|             if(found == children.end()) |             if (found == children.end()) { | ||||||
|             { |  | ||||||
|                 return nullptr; |                 return nullptr; | ||||||
|             } |             } | ||||||
|             return &(*found); |             return &(*found); | ||||||
|         } |         } else { | ||||||
|         else |  | ||||||
|         { |  | ||||||
|             auto prefix = path.left(sepIndex); |             auto prefix = path.left(sepIndex); | ||||||
|             auto found = children.find(prefix); |             auto found = children.find(prefix); | ||||||
|             if(found == children.end()) |             if (found == children.end()) { | ||||||
|             { |  | ||||||
|                 return nullptr; |                 return nullptr; | ||||||
|             } |             } | ||||||
|             return (*found).find(path.mid(sepIndex + 1)); |             return (*found).find(path.mid(sepIndex + 1)); | ||||||
| @@ -177,70 +141,48 @@ public: | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     /// is this a leaf node? |     /// is this a leaf node? | ||||||
|     bool leaf() const |     bool leaf() const { return children.isEmpty(); } | ||||||
|     { |  | ||||||
|         return children.isEmpty(); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /// is this node actually contained in the tree, or is it purely structural? |     /// is this node actually contained in the tree, or is it purely structural? | ||||||
|     bool contained() const |     bool contained() const { return m_contained; } | ||||||
|     { |  | ||||||
|         return m_contained; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /// Remove a path from the tree |     /// Remove a path from the tree | ||||||
|     bool remove(QString path) |     bool remove(QString path) { return removeInternal(path) != Failed; } | ||||||
|     { |  | ||||||
|         return removeInternal(path) != Failed; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /// Clear all children of this node tree node |     /// Clear all children of this node tree node | ||||||
|     void clear() |     void clear() { children.clear(); } | ||||||
|     { |  | ||||||
|         children.clear(); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     QStringList toStringList() const |     QStringList toStringList() const | ||||||
|     { |     { | ||||||
|         QStringList collected; |         QStringList collected; | ||||||
|         // collecting these is more expensive. |         // collecting these is more expensive. | ||||||
|         auto iter = children.begin(); |         auto iter = children.begin(); | ||||||
|         while(iter != children.end()) |         while (iter != children.end()) { | ||||||
|         { |  | ||||||
|             QStringList list = iter.value().toStringList(); |             QStringList list = iter.value().toStringList(); | ||||||
|             for(int i = 0; i < list.size(); i++) |             for (int i = 0; i < list.size(); i++) { | ||||||
|             { |  | ||||||
|                 list[i] = iter.key() + Tseparator + list[i]; |                 list[i] = iter.key() + Tseparator + list[i]; | ||||||
|             } |             } | ||||||
|             collected.append(list); |             collected.append(list); | ||||||
|             if((*iter).m_contained) |             if ((*iter).m_contained) { | ||||||
|             { |  | ||||||
|                 collected.append(iter.key()); |                 collected.append(iter.key()); | ||||||
|             } |             } | ||||||
|             iter++; |             iter++; | ||||||
|         } |         } | ||||||
|         return collected; |         return collected; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|    private: |    private: | ||||||
|     enum Removal |     enum Removal { Failed, Succeeded, HasChildren }; | ||||||
|     { |  | ||||||
|         Failed, |  | ||||||
|         Succeeded, |  | ||||||
|         HasChildren |  | ||||||
|     }; |  | ||||||
|     Removal removeInternal(QString path = QString()) |     Removal removeInternal(QString path = QString()) | ||||||
|     { |     { | ||||||
|         if(path.isEmpty()) |         if (path.isEmpty()) { | ||||||
|         { |             if (!m_contained) { | ||||||
|             if(!m_contained) |  | ||||||
|             { |  | ||||||
|                 // remove all children - we are removing a prefix |                 // remove all children - we are removing a prefix | ||||||
|                 clear(); |                 clear(); | ||||||
|                 return Succeeded; |                 return Succeeded; | ||||||
|             } |             } | ||||||
|             m_contained = false; |             m_contained = false; | ||||||
|             if(children.size()) |             if (children.size()) { | ||||||
|             { |  | ||||||
|                 return HasChildren; |                 return HasChildren; | ||||||
|             } |             } | ||||||
|             return Succeeded; |             return Succeeded; | ||||||
| @@ -248,42 +190,32 @@ private: | |||||||
|         Removal remStatus = Failed; |         Removal remStatus = Failed; | ||||||
|         QString childToRemove; |         QString childToRemove; | ||||||
|         auto sepIndex = path.indexOf(Tseparator); |         auto sepIndex = path.indexOf(Tseparator); | ||||||
|         if(sepIndex == -1) |         if (sepIndex == -1) { | ||||||
|         { |  | ||||||
|             childToRemove = path; |             childToRemove = path; | ||||||
|             auto found = children.find(childToRemove); |             auto found = children.find(childToRemove); | ||||||
|             if(found == children.end()) |             if (found == children.end()) { | ||||||
|             { |  | ||||||
|                 return Failed; |                 return Failed; | ||||||
|             } |             } | ||||||
|             remStatus = (*found).removeInternal(); |             remStatus = (*found).removeInternal(); | ||||||
|         } |         } else { | ||||||
|         else |  | ||||||
|         { |  | ||||||
|             childToRemove = path.left(sepIndex); |             childToRemove = path.left(sepIndex); | ||||||
|             auto found = children.find(childToRemove); |             auto found = children.find(childToRemove); | ||||||
|             if(found == children.end()) |             if (found == children.end()) { | ||||||
|             { |  | ||||||
|                 return Failed; |                 return Failed; | ||||||
|             } |             } | ||||||
|             remStatus = (*found).removeInternal(path.mid(sepIndex + 1)); |             remStatus = (*found).removeInternal(path.mid(sepIndex + 1)); | ||||||
|         } |         } | ||||||
|         switch (remStatus) |         switch (remStatus) { | ||||||
|         { |  | ||||||
|             case Failed: |             case Failed: | ||||||
|             case HasChildren: |             case HasChildren: { | ||||||
|             { |  | ||||||
|                 return remStatus; |                 return remStatus; | ||||||
|             } |             } | ||||||
|             case Succeeded: |             case Succeeded: { | ||||||
|             { |  | ||||||
|                 children.remove(childToRemove); |                 children.remove(childToRemove); | ||||||
|                 if(m_contained) |                 if (m_contained) { | ||||||
|                 { |  | ||||||
|                     return HasChildren; |                     return HasChildren; | ||||||
|                 } |                 } | ||||||
|                 if(children.size()) |                 if (children.size()) { | ||||||
|                 { |  | ||||||
|                     return HasChildren; |                     return HasChildren; | ||||||
|                 } |                 } | ||||||
|                 return Succeeded; |                 return Succeeded; | ||||||
|   | |||||||
| @@ -14,17 +14,16 @@ | |||||||
|  */ |  */ | ||||||
|  |  | ||||||
| #include "SkinUtils.h" | #include "SkinUtils.h" | ||||||
| #include "net/HttpMetaCache.h" |  | ||||||
| #include "Application.h" | #include "Application.h" | ||||||
|  | #include "net/HttpMetaCache.h" | ||||||
|  |  | ||||||
| #include <QFile> | #include <QFile> | ||||||
| #include <QPainter> | #include <QJsonArray> | ||||||
| #include <QJsonDocument> | #include <QJsonDocument> | ||||||
| #include <QJsonObject> | #include <QJsonObject> | ||||||
| #include <QJsonArray> | #include <QPainter> | ||||||
|  |  | ||||||
| namespace SkinUtils | namespace SkinUtils { | ||||||
| { |  | ||||||
| /* | /* | ||||||
|  * Given a username, return a pixmap of the cached skin (if it exists), QPixmap() otherwise |  * Given a username, return a pixmap of the cached skin (if it exists), QPixmap() otherwise | ||||||
|  */ |  */ | ||||||
| @@ -32,11 +31,9 @@ QPixmap getFaceFromCache(QString username, int height, int width) | |||||||
| { | { | ||||||
|     QFile fskin(APPLICATION->metacache()->resolveEntry("skins", username + ".png")->getFullPath()); |     QFile fskin(APPLICATION->metacache()->resolveEntry("skins", username + ".png")->getFullPath()); | ||||||
|  |  | ||||||
|     if (fskin.exists()) |     if (fskin.exists()) { | ||||||
|     { |  | ||||||
|         QPixmap skinTexture(fskin.fileName()); |         QPixmap skinTexture(fskin.fileName()); | ||||||
|         if(!skinTexture.isNull()) |         if (!skinTexture.isNull()) { | ||||||
|         { |  | ||||||
|             QPixmap skin = QPixmap(8, 8); |             QPixmap skin = QPixmap(8, 8); | ||||||
|             QPainter painter(&skin); |             QPainter painter(&skin); | ||||||
|             painter.drawPixmap(0, 0, skinTexture.copy(8, 8, 8, 8)); |             painter.drawPixmap(0, 0, skinTexture.copy(8, 8, 8, 8)); | ||||||
| @@ -47,4 +44,4 @@ QPixmap getFaceFromCache(QString username, int height, int width) | |||||||
|  |  | ||||||
|     return QPixmap(); |     return QPixmap(); | ||||||
| } | } | ||||||
| } | }  // namespace SkinUtils | ||||||
|   | |||||||
| @@ -17,7 +17,6 @@ | |||||||
|  |  | ||||||
| #include <QPixmap> | #include <QPixmap> | ||||||
|  |  | ||||||
| namespace SkinUtils | namespace SkinUtils { | ||||||
| { |  | ||||||
| QPixmap getFaceFromCache(QString id, int height = 64, int width = 64); | QPixmap getFaceFromCache(QString id, int height = 64, int width = 64); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -77,6 +77,5 @@ QString truncateUrlHumanFriendly(QUrl &url, int max_len, bool hard_limit = false | |||||||
|  |  | ||||||
| QString humanReadableFileSize(double bytes, bool use_si = false, int decimal_points = 1); | QString humanReadableFileSize(double bytes, bool use_si = false, int decimal_points = 1); | ||||||
|  |  | ||||||
|  |  | ||||||
| QString getRandomAlphaNumeric(); | QString getRandomAlphaNumeric(); | ||||||
| }  // namespace StringUtils | }  // namespace StringUtils | ||||||
|   | |||||||
| @@ -12,27 +12,17 @@ class Usable; | |||||||
|  * |  * | ||||||
|  * @see UseLock |  * @see UseLock | ||||||
|  */ |  */ | ||||||
| class Usable | class Usable { | ||||||
| { |  | ||||||
|     friend class UseLock; |     friend class UseLock; | ||||||
|  |  | ||||||
|    public: |    public: | ||||||
|     std::size_t useCount() const |     std::size_t useCount() const { return m_useCount; } | ||||||
|     { |     bool isInUse() const { return m_useCount > 0; } | ||||||
|         return m_useCount; |  | ||||||
|     } |  | ||||||
|     bool isInUse() const |  | ||||||
|     { |  | ||||||
|         return m_useCount > 0; |  | ||||||
|     } |  | ||||||
|    protected: |    protected: | ||||||
|     virtual void decrementUses() |     virtual void decrementUses() { m_useCount--; } | ||||||
|     { |     virtual void incrementUses() { m_useCount++; } | ||||||
|         m_useCount--; |  | ||||||
|     } |  | ||||||
|     virtual void incrementUses() |  | ||||||
|     { |  | ||||||
|         m_useCount++; |  | ||||||
|     } |  | ||||||
|    private: |    private: | ||||||
|     std::size_t m_useCount = 0; |     std::size_t m_useCount = 0; | ||||||
| }; | }; | ||||||
| @@ -42,19 +32,15 @@ private: | |||||||
|  * |  * | ||||||
|  * @see Usable |  * @see Usable | ||||||
|  */ |  */ | ||||||
| class UseLock | class UseLock { | ||||||
| { |  | ||||||
|    public: |    public: | ||||||
|     UseLock(shared_qobject_ptr<Usable> usable) |     UseLock(shared_qobject_ptr<Usable> usable) : m_usable(usable) | ||||||
|         : m_usable(usable) |  | ||||||
|     { |     { | ||||||
|         // this doesn't use shared pointer use count, because that wouldn't be correct. this count is separate. |         // this doesn't use shared pointer use count, because that wouldn't be correct. this count is separate. | ||||||
|         m_usable->incrementUses(); |         m_usable->incrementUses(); | ||||||
|     } |     } | ||||||
|     ~UseLock() |     ~UseLock() { m_usable->decrementUses(); } | ||||||
|     { |  | ||||||
|         m_usable->decrementUses(); |  | ||||||
|     } |  | ||||||
|    private: |    private: | ||||||
|     shared_qobject_ptr<Usable> m_usable; |     shared_qobject_ptr<Usable> m_usable; | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -117,12 +117,14 @@ QDebug operator<<(QDebug debug, const Version& v) | |||||||
|  |  | ||||||
|     bool first = true; |     bool first = true; | ||||||
|     for (auto s : v.m_sections) { |     for (auto s : v.m_sections) { | ||||||
|         if (!first) debug.nospace() << ", "; |         if (!first) | ||||||
|  |             debug.nospace() << ", "; | ||||||
|         debug.nospace() << s.m_fullString; |         debug.nospace() << s.m_fullString; | ||||||
|         first = false; |         first = false; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     debug.nospace() << " ]" << " }"; |     debug.nospace() << " ]" | ||||||
|  |                     << " }"; | ||||||
|  |  | ||||||
|     return debug; |     return debug; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| // SPDX-License-Identifier: GPL-3.0-only | // SPDX-License-Identifier: GPL-3.0-only | ||||||
| /* | /* | ||||||
|  *  PolyMC - Minecraft Launcher |  *  Prism Launcher - Minecraft Launcher | ||||||
|  *  Copyright (C) 2023 flowln <flowlnlnln@gmail.com> |  *  Copyright (C) 2023 flowln <flowlnlnln@gmail.com> | ||||||
|  *  Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net> |  *  Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net> | ||||||
|  * |  * | ||||||
| @@ -103,8 +103,14 @@ class Version { | |||||||
|  |  | ||||||
|         QString m_fullString; |         QString m_fullString; | ||||||
|  |  | ||||||
|         [[nodiscard]] inline bool isAppendix() const { return m_stringPart.startsWith('+'); } |         [[nodiscard]] inline bool isAppendix() const | ||||||
|         [[nodiscard]] inline bool isPreRelease() const { return m_stringPart.startsWith('-') && m_stringPart.length() > 1; } |         { | ||||||
|  |             return m_stringPart.startsWith('+'); | ||||||
|  |         } | ||||||
|  |         [[nodiscard]] inline bool isPreRelease() const | ||||||
|  |         { | ||||||
|  |             return m_stringPart.startsWith('-') && m_stringPart.length() > 1; | ||||||
|  |         } | ||||||
|  |  | ||||||
|         inline bool operator==(const Section& other) const |         inline bool operator==(const Section& other) const | ||||||
|         { |         { | ||||||
| @@ -166,5 +172,3 @@ class Version { | |||||||
|  |  | ||||||
|     void parse(); |     void parse(); | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
| @@ -35,14 +35,13 @@ | |||||||
|  */ |  */ | ||||||
|  |  | ||||||
| #include "VersionProxyModel.h" | #include "VersionProxyModel.h" | ||||||
| #include "Application.h" |  | ||||||
| #include <QSortFilterProxyModel> |  | ||||||
| #include <QPixmapCache> |  | ||||||
| #include <Version.h> | #include <Version.h> | ||||||
| #include <meta/VersionList.h> | #include <meta/VersionList.h> | ||||||
|  | #include <QPixmapCache> | ||||||
|  | #include <QSortFilterProxyModel> | ||||||
|  | #include "Application.h" | ||||||
|  |  | ||||||
| class VersionFilterModel : public QSortFilterProxyModel | class VersionFilterModel : public QSortFilterProxyModel { | ||||||
| { |  | ||||||
|     Q_OBJECT |     Q_OBJECT | ||||||
|    public: |    public: | ||||||
|     VersionFilterModel(VersionProxyModel* parent) : QSortFilterProxyModel(parent) |     VersionFilterModel(VersionProxyModel* parent) : QSortFilterProxyModel(parent) | ||||||
| @@ -61,22 +60,18 @@ public: | |||||||
|         if (!search.isEmpty() && !sourceModel()->data(idx, BaseVersionList::VersionRole).toString().contains(search, Qt::CaseInsensitive)) |         if (!search.isEmpty() && !sourceModel()->data(idx, BaseVersionList::VersionRole).toString().contains(search, Qt::CaseInsensitive)) | ||||||
|             return false; |             return false; | ||||||
|  |  | ||||||
|         for (auto it = filters.begin(); it != filters.end(); ++it) |         for (auto it = filters.begin(); it != filters.end(); ++it) { | ||||||
|         { |  | ||||||
|             auto data = sourceModel()->data(idx, it.key()); |             auto data = sourceModel()->data(idx, it.key()); | ||||||
|             auto match = data.toString(); |             auto match = data.toString(); | ||||||
|             if(!it.value()->accepts(match)) |             if (!it.value()->accepts(match)) { | ||||||
|             { |  | ||||||
|                 return false; |                 return false; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         return true; |         return true; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     void filterChanged() |     void filterChanged() { invalidateFilter(); } | ||||||
|     { |  | ||||||
|         invalidateFilter(); |  | ||||||
|     } |  | ||||||
|    private: |    private: | ||||||
|     VersionProxyModel* m_parent; |     VersionProxyModel* m_parent; | ||||||
| }; | }; | ||||||
| @@ -109,10 +104,8 @@ QVariant VersionProxyModel::headerData(int section, Qt::Orientation orientation, | |||||||
|     if (orientation != Qt::Horizontal) |     if (orientation != Qt::Horizontal) | ||||||
|         return QVariant(); |         return QVariant(); | ||||||
|     auto column = m_columns[section]; |     auto column = m_columns[section]; | ||||||
|     if(role == Qt::DisplayRole) |     if (role == Qt::DisplayRole) { | ||||||
|     { |         switch (column) { | ||||||
|         switch(column) |  | ||||||
|         { |  | ||||||
|             case Name: |             case Name: | ||||||
|                 return tr("Version"); |                 return tr("Version"); | ||||||
|             case ParentVersion: |             case ParentVersion: | ||||||
| @@ -128,11 +121,8 @@ QVariant VersionProxyModel::headerData(int section, Qt::Orientation orientation, | |||||||
|             case Time: |             case Time: | ||||||
|                 return tr("Released"); |                 return tr("Released"); | ||||||
|         } |         } | ||||||
|     } |     } else if (role == Qt::ToolTipRole) { | ||||||
|     else if(role == Qt::ToolTipRole) |         switch (column) { | ||||||
|     { |  | ||||||
|         switch(column) |  | ||||||
|         { |  | ||||||
|             case Name: |             case Name: | ||||||
|                 return tr("The name of the version."); |                 return tr("The name of the version."); | ||||||
|             case ParentVersion: |             case ParentVersion: | ||||||
| @@ -154,23 +144,17 @@ QVariant VersionProxyModel::headerData(int section, Qt::Orientation orientation, | |||||||
|  |  | ||||||
| QVariant VersionProxyModel::data(const QModelIndex& index, int role) const | QVariant VersionProxyModel::data(const QModelIndex& index, int role) const | ||||||
| { | { | ||||||
|     if(!index.isValid()) |     if (!index.isValid()) { | ||||||
|     { |  | ||||||
|         return QVariant(); |         return QVariant(); | ||||||
|     } |     } | ||||||
|     auto column = m_columns[index.column()]; |     auto column = m_columns[index.column()]; | ||||||
|     auto parentIndex = mapToSource(index); |     auto parentIndex = mapToSource(index); | ||||||
|     switch(role) |     switch (role) { | ||||||
|     { |         case Qt::DisplayRole: { | ||||||
|         case Qt::DisplayRole: |             switch (column) { | ||||||
|         { |                 case Name: { | ||||||
|             switch(column) |  | ||||||
|             { |  | ||||||
|                 case Name: |  | ||||||
|                 { |  | ||||||
|                     QString version = sourceModel()->data(parentIndex, BaseVersionList::VersionRole).toString(); |                     QString version = sourceModel()->data(parentIndex, BaseVersionList::VersionRole).toString(); | ||||||
|                     if(version == m_currentVersion) |                     if (version == m_currentVersion) { | ||||||
|                     { |  | ||||||
|                         return tr("%1 (installed)").arg(version); |                         return tr("%1 (installed)").arg(version); | ||||||
|                     } |                     } | ||||||
|                     return version; |                     return version; | ||||||
| @@ -191,18 +175,14 @@ QVariant VersionProxyModel::data(const QModelIndex &index, int role) const | |||||||
|                     return QVariant(); |                     return QVariant(); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         case Qt::ToolTipRole: |         case Qt::ToolTipRole: { | ||||||
|         { |             if (column == Name && hasRecommended) { | ||||||
|             if(column == Name && hasRecommended)  |  | ||||||
|             { |  | ||||||
|                 auto value = sourceModel()->data(parentIndex, BaseVersionList::RecommendedRole); |                 auto value = sourceModel()->data(parentIndex, BaseVersionList::RecommendedRole); | ||||||
|                 if(value.toBool()) |                 if (value.toBool()) { | ||||||
|                 { |  | ||||||
|                     return tr("Recommended"); |                     return tr("Recommended"); | ||||||
|                 } else if (hasLatest) { |                 } else if (hasLatest) { | ||||||
|                     auto value = sourceModel()->data(parentIndex, BaseVersionList::LatestRole); |                     auto value = sourceModel()->data(parentIndex, BaseVersionList::LatestRole); | ||||||
|                     if(value.toBool()) |                     if (value.toBool()) { | ||||||
|                     { |  | ||||||
|                         return tr("Latest"); |                         return tr("Latest"); | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
| @@ -210,31 +190,22 @@ QVariant VersionProxyModel::data(const QModelIndex &index, int role) const | |||||||
|                 return sourceModel()->data(parentIndex, BaseVersionList::VersionIdRole); |                 return sourceModel()->data(parentIndex, BaseVersionList::VersionIdRole); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         case Qt::DecorationRole: |         case Qt::DecorationRole: { | ||||||
|         { |             switch (column) { | ||||||
|             switch(column) |                 case Name: { | ||||||
|             { |                     if (hasRecommended) { | ||||||
|                 case Name: |  | ||||||
|                 { |  | ||||||
|                     if(hasRecommended) |  | ||||||
|                     { |  | ||||||
|                         auto value = sourceModel()->data(parentIndex, BaseVersionList::RecommendedRole); |                         auto value = sourceModel()->data(parentIndex, BaseVersionList::RecommendedRole); | ||||||
|                         if(value.toBool()) |                         if (value.toBool()) { | ||||||
|                         { |  | ||||||
|                             return APPLICATION->getThemedIcon("star"); |                             return APPLICATION->getThemedIcon("star"); | ||||||
|                         } |                         } else if (hasLatest) { | ||||||
|                         else if(hasLatest) |  | ||||||
|                         { |  | ||||||
|                             auto value = sourceModel()->data(parentIndex, BaseVersionList::LatestRole); |                             auto value = sourceModel()->data(parentIndex, BaseVersionList::LatestRole); | ||||||
|                             if(value.toBool()) |                             if (value.toBool()) { | ||||||
|                             { |  | ||||||
|                                 return APPLICATION->getThemedIcon("bug"); |                                 return APPLICATION->getThemedIcon("bug"); | ||||||
|                             } |                             } | ||||||
|                         } |                         } | ||||||
|                         QPixmap pixmap; |                         QPixmap pixmap; | ||||||
|                         QPixmapCache::find("placeholder", &pixmap); |                         QPixmapCache::find("placeholder", &pixmap); | ||||||
|                         if(!pixmap) |                         if (!pixmap) { | ||||||
|                         { |  | ||||||
|                             QPixmap px(16, 16); |                             QPixmap px(16, 16); | ||||||
|                             px.fill(Qt::transparent); |                             px.fill(Qt::transparent); | ||||||
|                             QPixmapCache::insert("placeholder", px); |                             QPixmapCache::insert("placeholder", px); | ||||||
| @@ -243,16 +214,13 @@ QVariant VersionProxyModel::data(const QModelIndex &index, int role) const | |||||||
|                         return pixmap; |                         return pixmap; | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|                 default: |                 default: { | ||||||
|                 { |  | ||||||
|                     return QVariant(); |                     return QVariant(); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         default: |         default: { | ||||||
|         { |             if (roles.contains((BaseVersionList::ModelRoles)role)) { | ||||||
|             if(roles.contains((BaseVersionList::ModelRoles)role)) |  | ||||||
|             { |  | ||||||
|                 return sourceModel()->data(parentIndex, role); |                 return sourceModel()->data(parentIndex, role); | ||||||
|             } |             } | ||||||
|             return QVariant(); |             return QVariant(); | ||||||
| @@ -267,8 +235,7 @@ QModelIndex VersionProxyModel::parent(const QModelIndex &child) const | |||||||
|  |  | ||||||
| QModelIndex VersionProxyModel::mapFromSource(const QModelIndex& sourceIndex) const | QModelIndex VersionProxyModel::mapFromSource(const QModelIndex& sourceIndex) const | ||||||
| { | { | ||||||
|     if(sourceIndex.isValid()) |     if (sourceIndex.isValid()) { | ||||||
|     { |  | ||||||
|         return index(sourceIndex.row(), 0); |         return index(sourceIndex.row(), 0); | ||||||
|     } |     } | ||||||
|     return QModelIndex(); |     return QModelIndex(); | ||||||
| @@ -276,8 +243,7 @@ QModelIndex VersionProxyModel::mapFromSource(const QModelIndex &sourceIndex) con | |||||||
|  |  | ||||||
| QModelIndex VersionProxyModel::mapToSource(const QModelIndex& proxyIndex) const | QModelIndex VersionProxyModel::mapToSource(const QModelIndex& proxyIndex) const | ||||||
| { | { | ||||||
|     if(proxyIndex.isValid()) |     if (proxyIndex.isValid()) { | ||||||
|     { |  | ||||||
|         return sourceModel()->index(proxyIndex.row(), 0); |         return sourceModel()->index(proxyIndex.row(), 0); | ||||||
|     } |     } | ||||||
|     return QModelIndex(); |     return QModelIndex(); | ||||||
| @@ -286,8 +252,7 @@ QModelIndex VersionProxyModel::mapToSource(const QModelIndex &proxyIndex) const | |||||||
| QModelIndex VersionProxyModel::index(int row, int column, const QModelIndex& parent) const | QModelIndex VersionProxyModel::index(int row, int column, const QModelIndex& parent) const | ||||||
| { | { | ||||||
|     // no trees here... shoo |     // no trees here... shoo | ||||||
|     if(parent.isValid()) |     if (parent.isValid()) { | ||||||
|     { |  | ||||||
|         return QModelIndex(); |         return QModelIndex(); | ||||||
|     } |     } | ||||||
|     if (row < 0 || row >= sourceModel()->rowCount()) |     if (row < 0 || row >= sourceModel()->rowCount()) | ||||||
| @@ -304,15 +269,13 @@ int VersionProxyModel::columnCount(const QModelIndex &parent) const | |||||||
|  |  | ||||||
| int VersionProxyModel::rowCount(const QModelIndex& parent) const | int VersionProxyModel::rowCount(const QModelIndex& parent) const | ||||||
| { | { | ||||||
|     if(sourceModel()) |     if (sourceModel()) { | ||||||
|     { |  | ||||||
|         return sourceModel()->rowCount(parent); |         return sourceModel()->rowCount(parent); | ||||||
|     } |     } | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| void VersionProxyModel::sourceDataChanged(const QModelIndex &source_top_left, | void VersionProxyModel::sourceDataChanged(const QModelIndex& source_top_left, const QModelIndex& source_bottom_right) | ||||||
|                                           const QModelIndex &source_bottom_right) |  | ||||||
| { | { | ||||||
|     if (source_top_left.parent() != source_bottom_right.parent()) |     if (source_top_left.parent() != source_bottom_right.parent()) | ||||||
|         return; |         return; | ||||||
| @@ -329,16 +292,14 @@ void VersionProxyModel::setSourceModel(QAbstractItemModel *replacingRaw) | |||||||
|     beginResetModel(); |     beginResetModel(); | ||||||
|  |  | ||||||
|     m_columns.clear(); |     m_columns.clear(); | ||||||
|     if(!replacing) |     if (!replacing) { | ||||||
|     { |  | ||||||
|         roles.clear(); |         roles.clear(); | ||||||
|         filterModel->setSourceModel(replacing); |         filterModel->setSourceModel(replacing); | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     roles = replacing->providesRoles(); |     roles = replacing->providesRoles(); | ||||||
|     if(roles.contains(BaseVersionList::VersionRole)) |     if (roles.contains(BaseVersionList::VersionRole)) { | ||||||
|     { |  | ||||||
|         m_columns.push_back(Name); |         m_columns.push_back(Name); | ||||||
|     } |     } | ||||||
|     /* |     /* | ||||||
| @@ -347,32 +308,25 @@ void VersionProxyModel::setSourceModel(QAbstractItemModel *replacingRaw) | |||||||
|         m_columns.push_back(ParentVersion); |         m_columns.push_back(ParentVersion); | ||||||
|     } |     } | ||||||
|     */ |     */ | ||||||
|     if(roles.contains(BaseVersionList::ArchitectureRole)) |     if (roles.contains(BaseVersionList::ArchitectureRole)) { | ||||||
|     { |  | ||||||
|         m_columns.push_back(Architecture); |         m_columns.push_back(Architecture); | ||||||
|     } |     } | ||||||
|     if(roles.contains(BaseVersionList::PathRole)) |     if (roles.contains(BaseVersionList::PathRole)) { | ||||||
|     { |  | ||||||
|         m_columns.push_back(Path); |         m_columns.push_back(Path); | ||||||
|     } |     } | ||||||
|     if(roles.contains(Meta::VersionList::TimeRole)) |     if (roles.contains(Meta::VersionList::TimeRole)) { | ||||||
|     { |  | ||||||
|         m_columns.push_back(Time); |         m_columns.push_back(Time); | ||||||
|     } |     } | ||||||
|     if(roles.contains(BaseVersionList::BranchRole)) |     if (roles.contains(BaseVersionList::BranchRole)) { | ||||||
|     { |  | ||||||
|         m_columns.push_back(Branch); |         m_columns.push_back(Branch); | ||||||
|     } |     } | ||||||
|     if(roles.contains(BaseVersionList::TypeRole)) |     if (roles.contains(BaseVersionList::TypeRole)) { | ||||||
|     { |  | ||||||
|         m_columns.push_back(Type); |         m_columns.push_back(Type); | ||||||
|     } |     } | ||||||
|     if(roles.contains(BaseVersionList::RecommendedRole)) |     if (roles.contains(BaseVersionList::RecommendedRole)) { | ||||||
|     { |  | ||||||
|         hasRecommended = true; |         hasRecommended = true; | ||||||
|     } |     } | ||||||
|     if(roles.contains(BaseVersionList::LatestRole)) |     if (roles.contains(BaseVersionList::LatestRole)) { | ||||||
|     { |  | ||||||
|         hasLatest = true; |         hasLatest = true; | ||||||
|     } |     } | ||||||
|     filterModel->setSourceModel(replacing); |     filterModel->setSourceModel(replacing); | ||||||
| @@ -382,16 +336,13 @@ void VersionProxyModel::setSourceModel(QAbstractItemModel *replacingRaw) | |||||||
|  |  | ||||||
| QModelIndex VersionProxyModel::getRecommended() const | QModelIndex VersionProxyModel::getRecommended() const | ||||||
| { | { | ||||||
|     if(!roles.contains(BaseVersionList::RecommendedRole)) |     if (!roles.contains(BaseVersionList::RecommendedRole)) { | ||||||
|     { |  | ||||||
|         return index(0, 0); |         return index(0, 0); | ||||||
|     } |     } | ||||||
|     int recommended = 0; |     int recommended = 0; | ||||||
|     for (int i = 0; i < rowCount(); i++) |     for (int i = 0; i < rowCount(); i++) { | ||||||
|     { |  | ||||||
|         auto value = sourceModel()->data(mapToSource(index(i, 0)), BaseVersionList::RecommendedRole); |         auto value = sourceModel()->data(mapToSource(index(i, 0)), BaseVersionList::RecommendedRole); | ||||||
|         if (value.toBool()) |         if (value.toBool()) { | ||||||
|         { |  | ||||||
|             recommended = i; |             recommended = i; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @@ -401,16 +352,13 @@ QModelIndex VersionProxyModel::getRecommended() const | |||||||
| QModelIndex VersionProxyModel::getVersion(const QString& version) const | QModelIndex VersionProxyModel::getVersion(const QString& version) const | ||||||
| { | { | ||||||
|     int found = -1; |     int found = -1; | ||||||
|     for (int i = 0; i < rowCount(); i++) |     for (int i = 0; i < rowCount(); i++) { | ||||||
|     { |  | ||||||
|         auto value = sourceModel()->data(mapToSource(index(i, 0)), BaseVersionList::VersionRole); |         auto value = sourceModel()->data(mapToSource(index(i, 0)), BaseVersionList::VersionRole); | ||||||
|         if (value.toString() == version) |         if (value.toString() == version) { | ||||||
|         { |  | ||||||
|             found = i; |             found = i; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     if(found == -1) |     if (found == -1) { | ||||||
|     { |  | ||||||
|         return QModelIndex(); |         return QModelIndex(); | ||||||
|     } |     } | ||||||
|     return index(found, 0); |     return index(found, 0); | ||||||
| @@ -429,7 +377,8 @@ void VersionProxyModel::setFilter(const BaseVersionList::ModelRoles column, Filt | |||||||
|     filterModel->filterChanged(); |     filterModel->filterChanged(); | ||||||
| } | } | ||||||
|  |  | ||||||
| void VersionProxyModel::setSearch(const QString &search) { | void VersionProxyModel::setSearch(const QString& search) | ||||||
|  | { | ||||||
|     m_search = search; |     m_search = search; | ||||||
|     filterModel->filterChanged(); |     filterModel->filterChanged(); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -6,21 +6,10 @@ | |||||||
|  |  | ||||||
| class VersionFilterModel; | class VersionFilterModel; | ||||||
|  |  | ||||||
| class VersionProxyModel: public QAbstractProxyModel | class VersionProxyModel : public QAbstractProxyModel { | ||||||
| { |  | ||||||
|     Q_OBJECT |     Q_OBJECT | ||||||
|    public: |    public: | ||||||
|  |     enum Column { Name, ParentVersion, Branch, Type, Architecture, Path, Time }; | ||||||
|     enum Column |  | ||||||
|     { |  | ||||||
|         Name, |  | ||||||
|         ParentVersion, |  | ||||||
|         Branch, |  | ||||||
|         Type, |  | ||||||
|         Architecture, |  | ||||||
|         Path, |  | ||||||
|         Time |  | ||||||
|     }; |  | ||||||
|     typedef QHash<BaseVersionList::ModelRoles, std::shared_ptr<Filter>> FilterMap; |     typedef QHash<BaseVersionList::ModelRoles, std::shared_ptr<Filter>> FilterMap; | ||||||
|  |  | ||||||
|    public: |    public: | ||||||
|   | |||||||
| @@ -1,20 +1,15 @@ | |||||||
|  |  | ||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
| #include <QString> |  | ||||||
| #include <QFileSystemWatcher> | #include <QFileSystemWatcher> | ||||||
|  | #include <QString> | ||||||
|  |  | ||||||
| struct WatchLock | struct WatchLock { | ||||||
| { |     WatchLock(QFileSystemWatcher* watcher, const QString& directory) : m_watcher(watcher), m_directory(directory) | ||||||
|     WatchLock(QFileSystemWatcher * watcher, const QString& directory) |  | ||||||
|         : m_watcher(watcher), m_directory(directory) |  | ||||||
|     { |     { | ||||||
|         m_watcher->removePath(m_directory); |         m_watcher->removePath(m_directory); | ||||||
|     } |     } | ||||||
|     ~WatchLock() |     ~WatchLock() { m_watcher->addPath(m_directory); } | ||||||
|     { |  | ||||||
|         m_watcher->addPath(m_directory); |  | ||||||
|     } |  | ||||||
|     QFileSystemWatcher* m_watcher; |     QFileSystemWatcher* m_watcher; | ||||||
|     QString m_directory; |     QString m_directory; | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| // SPDX-License-Identifier: GPL-3.0-only | // SPDX-License-Identifier: GPL-3.0-only | ||||||
| /* | /* | ||||||
|  *  PolyMC - Minecraft Launcher |  *  Prism Launcher - Minecraft Launcher | ||||||
|  *  Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net> |  *  Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net> | ||||||
|  * |  * | ||||||
|  *  This program is free software: you can redistribute it and/or modify |  *  This program is free software: you can redistribute it and/or modify | ||||||
| @@ -35,13 +35,13 @@ | |||||||
|  |  | ||||||
| #include "IconList.h" | #include "IconList.h" | ||||||
| #include <FileSystem.h> | #include <FileSystem.h> | ||||||
| #include <QMap> |  | ||||||
| #include <QEventLoop> |  | ||||||
| #include <QMimeData> |  | ||||||
| #include <QUrl> |  | ||||||
| #include <QFileSystemWatcher> |  | ||||||
| #include <QSet> |  | ||||||
| #include <QDebug> | #include <QDebug> | ||||||
|  | #include <QEventLoop> | ||||||
|  | #include <QFileSystemWatcher> | ||||||
|  | #include <QMap> | ||||||
|  | #include <QMimeData> | ||||||
|  | #include <QSet> | ||||||
|  | #include <QUrl> | ||||||
|  |  | ||||||
| #define MAX_SIZE 1024 | #define MAX_SIZE 1024 | ||||||
|  |  | ||||||
| @@ -50,17 +50,14 @@ IconList::IconList(const QStringList &builtinPaths, QString path, QObject *paren | |||||||
|     QSet<QString> builtinNames; |     QSet<QString> builtinNames; | ||||||
|  |  | ||||||
|     // add builtin icons |     // add builtin icons | ||||||
|     for(auto & builtinPath: builtinPaths) |     for (auto& builtinPath : builtinPaths) { | ||||||
|     { |  | ||||||
|         QDir instance_icons(builtinPath); |         QDir instance_icons(builtinPath); | ||||||
|         auto file_info_list = instance_icons.entryInfoList(QDir::Files, QDir::Name); |         auto file_info_list = instance_icons.entryInfoList(QDir::Files, QDir::Name); | ||||||
|         for (auto file_info : file_info_list) |         for (auto file_info : file_info_list) { | ||||||
|         { |  | ||||||
|             builtinNames.insert(file_info.completeBaseName()); |             builtinNames.insert(file_info.completeBaseName()); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     for(auto & builtinName : builtinNames) |     for (auto& builtinName : builtinNames) { | ||||||
|     { |  | ||||||
|         addThemeIcon(builtinName); |         addThemeIcon(builtinName); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -78,17 +75,14 @@ IconList::IconList(const QStringList &builtinPaths, QString path, QObject *paren | |||||||
| void IconList::sortIconList() | void IconList::sortIconList() | ||||||
| { | { | ||||||
|     qDebug() << "Sorting icon list..."; |     qDebug() << "Sorting icon list..."; | ||||||
|     std::sort(icons.begin(), icons.end(), [](const MMCIcon& a, const MMCIcon& b) { |     std::sort(icons.begin(), icons.end(), [](const MMCIcon& a, const MMCIcon& b) { return a.m_key.localeAwareCompare(b.m_key) < 0; }); | ||||||
|         return a.m_key.localeAwareCompare(b.m_key) < 0; |  | ||||||
|     }); |  | ||||||
|     reindex(); |     reindex(); | ||||||
| } | } | ||||||
|  |  | ||||||
| void IconList::directoryChanged(const QString& path) | void IconList::directoryChanged(const QString& path) | ||||||
| { | { | ||||||
|     QDir new_dir(path); |     QDir new_dir(path); | ||||||
|     if(m_dir.absolutePath() != new_dir.absolutePath()) |     if (m_dir.absolutePath() != new_dir.absolutePath()) { | ||||||
|     { |  | ||||||
|         m_dir.setPath(path); |         m_dir.setPath(path); | ||||||
|         m_dir.refresh(); |         m_dir.refresh(); | ||||||
|         if (is_watching) |         if (is_watching) | ||||||
| @@ -100,8 +94,7 @@ void IconList::directoryChanged(const QString &path) | |||||||
|             return; |             return; | ||||||
|     m_dir.refresh(); |     m_dir.refresh(); | ||||||
|     auto new_list = m_dir.entryList(QDir::Files, QDir::Name); |     auto new_list = m_dir.entryList(QDir::Files, QDir::Name); | ||||||
|     for (auto it = new_list.begin(); it != new_list.end(); it++) |     for (auto it = new_list.begin(); it != new_list.end(); it++) { | ||||||
|     { |  | ||||||
|         QString& foo = (*it); |         QString& foo = (*it); | ||||||
|         foo = m_dir.filePath(foo); |         foo = m_dir.filePath(foo); | ||||||
|     } |     } | ||||||
| @@ -111,8 +104,7 @@ void IconList::directoryChanged(const QString &path) | |||||||
|     auto new_set = new_list.toSet(); |     auto new_set = new_list.toSet(); | ||||||
| #endif | #endif | ||||||
|     QList<QString> current_list; |     QList<QString> current_list; | ||||||
|     for (auto &it : icons) |     for (auto& it : icons) { | ||||||
|     { |  | ||||||
|         if (!it.has(IconType::FileBased)) |         if (!it.has(IconType::FileBased)) | ||||||
|             continue; |             continue; | ||||||
|         current_list.push_back(it.m_images[IconType::FileBased].filename); |         current_list.push_back(it.m_images[IconType::FileBased].filename); | ||||||
| @@ -129,8 +121,7 @@ void IconList::directoryChanged(const QString &path) | |||||||
|     QSet<QString> to_add = new_set; |     QSet<QString> to_add = new_set; | ||||||
|     to_add -= current_set; |     to_add -= current_set; | ||||||
|  |  | ||||||
|     for (auto remove : to_remove) |     for (auto remove : to_remove) { | ||||||
|     { |  | ||||||
|         qDebug() << "Removing " << remove; |         qDebug() << "Removing " << remove; | ||||||
|         QFileInfo rmfile(remove); |         QFileInfo rmfile(remove); | ||||||
|         QString key = rmfile.completeBaseName(); |         QString key = rmfile.completeBaseName(); | ||||||
| @@ -144,23 +135,19 @@ void IconList::directoryChanged(const QString &path) | |||||||
|         if (idx == -1) |         if (idx == -1) | ||||||
|             continue; |             continue; | ||||||
|         icons[idx].remove(IconType::FileBased); |         icons[idx].remove(IconType::FileBased); | ||||||
|         if (icons[idx].type() == IconType::ToBeDeleted) |         if (icons[idx].type() == IconType::ToBeDeleted) { | ||||||
|         { |  | ||||||
|             beginRemoveRows(QModelIndex(), idx, idx); |             beginRemoveRows(QModelIndex(), idx, idx); | ||||||
|             icons.remove(idx); |             icons.remove(idx); | ||||||
|             reindex(); |             reindex(); | ||||||
|             endRemoveRows(); |             endRemoveRows(); | ||||||
|         } |         } else { | ||||||
|         else |  | ||||||
|         { |  | ||||||
|             dataChanged(index(idx), index(idx)); |             dataChanged(index(idx), index(idx)); | ||||||
|         } |         } | ||||||
|         m_watcher->removePath(remove); |         m_watcher->removePath(remove); | ||||||
|         emit iconUpdated(key); |         emit iconUpdated(key); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     for (auto add : to_add) |     for (auto add : to_add) { | ||||||
|     { |  | ||||||
|         qDebug() << "Adding " << add; |         qDebug() << "Adding " << add; | ||||||
|  |  | ||||||
|         QFileInfo addfile(add); |         QFileInfo addfile(add); | ||||||
| @@ -171,8 +158,7 @@ void IconList::directoryChanged(const QString &path) | |||||||
|         if (suffix != "jpeg" && suffix != "png" && suffix != "jpg" && suffix != "ico" && suffix != "svg" && suffix != "gif") |         if (suffix != "jpeg" && suffix != "png" && suffix != "jpg" && suffix != "ico" && suffix != "svg" && suffix != "gif") | ||||||
|             key = addfile.fileName(); |             key = addfile.fileName(); | ||||||
|  |  | ||||||
|         if (addIcon(key, QString(), addfile.filePath(), IconType::FileBased)) |         if (addIcon(key, QString(), addfile.filePath(), IconType::FileBased)) { | ||||||
|         { |  | ||||||
|             m_watcher->addPath(add); |             m_watcher->addPath(add); | ||||||
|             emit iconUpdated(key); |             emit iconUpdated(key); | ||||||
|         } |         } | ||||||
| @@ -213,12 +199,9 @@ void IconList::startWatching() | |||||||
|     auto abs_path = m_dir.absolutePath(); |     auto abs_path = m_dir.absolutePath(); | ||||||
|     FS::ensureFolderPathExists(abs_path); |     FS::ensureFolderPathExists(abs_path); | ||||||
|     is_watching = m_watcher->addPath(abs_path); |     is_watching = m_watcher->addPath(abs_path); | ||||||
|     if (is_watching) |     if (is_watching) { | ||||||
|     { |  | ||||||
|         qDebug() << "Started watching " << abs_path; |         qDebug() << "Started watching " << abs_path; | ||||||
|     } |     } else { | ||||||
|     else |  | ||||||
|     { |  | ||||||
|         qDebug() << "Failed to start watching " << abs_path; |         qDebug() << "Failed to start watching " << abs_path; | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -241,7 +224,11 @@ Qt::DropActions IconList::supportedDropActions() const | |||||||
|     return Qt::CopyAction; |     return Qt::CopyAction; | ||||||
| } | } | ||||||
|  |  | ||||||
| bool IconList::dropMimeData(const QMimeData *data, Qt::DropAction action, [[maybe_unused]] int row, [[maybe_unused]] int column, [[maybe_unused]] const QModelIndex &parent) | bool IconList::dropMimeData(const QMimeData* data, | ||||||
|  |                             Qt::DropAction action, | ||||||
|  |                             [[maybe_unused]] int row, | ||||||
|  |                             [[maybe_unused]] int column, | ||||||
|  |                             [[maybe_unused]] const QModelIndex& parent) | ||||||
| { | { | ||||||
|     if (action == Qt::IgnoreAction) |     if (action == Qt::IgnoreAction) | ||||||
|         return true; |         return true; | ||||||
| @@ -250,12 +237,10 @@ bool IconList::dropMimeData(const QMimeData *data, Qt::DropAction action, [[mayb | |||||||
|         return false; |         return false; | ||||||
|  |  | ||||||
|     // files dropped from outside? |     // files dropped from outside? | ||||||
|     if (data->hasUrls()) |     if (data->hasUrls()) { | ||||||
|     { |  | ||||||
|         auto urls = data->urls(); |         auto urls = data->urls(); | ||||||
|         QStringList iconFiles; |         QStringList iconFiles; | ||||||
|         for (auto url : urls) |         for (auto url : urls) { | ||||||
|         { |  | ||||||
|             // only local files may be dropped... |             // only local files may be dropped... | ||||||
|             if (!url.isLocalFile()) |             if (!url.isLocalFile()) | ||||||
|                 continue; |                 continue; | ||||||
| @@ -286,8 +271,7 @@ QVariant IconList::data(const QModelIndex &index, int role) const | |||||||
|     if (row < 0 || row >= icons.size()) |     if (row < 0 || row >= icons.size()) | ||||||
|         return QVariant(); |         return QVariant(); | ||||||
|  |  | ||||||
|     switch (role) |     switch (role) { | ||||||
|     { |  | ||||||
|         case Qt::DecorationRole: |         case Qt::DecorationRole: | ||||||
|             return icons[row].icon(); |             return icons[row].icon(); | ||||||
|         case Qt::DisplayRole: |         case Qt::DisplayRole: | ||||||
| @@ -306,8 +290,7 @@ int IconList::rowCount(const QModelIndex &parent) const | |||||||
|  |  | ||||||
| void IconList::installIcons(const QStringList& iconFiles) | void IconList::installIcons(const QStringList& iconFiles) | ||||||
| { | { | ||||||
|     for (QString file : iconFiles) |     for (QString file : iconFiles) { | ||||||
|     { |  | ||||||
|         QFileInfo fileinfo(file); |         QFileInfo fileinfo(file); | ||||||
|         if (!fileinfo.isReadable() || !fileinfo.isFile()) |         if (!fileinfo.isReadable() || !fileinfo.isFile()) | ||||||
|             continue; |             continue; | ||||||
| @@ -336,8 +319,7 @@ void IconList::installIcon(const QString &file, const QString &name) | |||||||
| bool IconList::iconFileExists(const QString& key) const | bool IconList::iconFileExists(const QString& key) const | ||||||
| { | { | ||||||
|     auto iconEntry = icon(key); |     auto iconEntry = icon(key); | ||||||
|     if(!iconEntry) |     if (!iconEntry) { | ||||||
|     { |  | ||||||
|         return false; |         return false; | ||||||
|     } |     } | ||||||
|     return iconEntry->has(IconType::FileBased); |     return iconEntry->has(IconType::FileBased); | ||||||
| @@ -370,15 +352,12 @@ bool IconList::trashIcon(const QString &key) | |||||||
| bool IconList::addThemeIcon(const QString& key) | bool IconList::addThemeIcon(const QString& key) | ||||||
| { | { | ||||||
|     auto iter = name_index.find(key); |     auto iter = name_index.find(key); | ||||||
|     if (iter != name_index.end()) |     if (iter != name_index.end()) { | ||||||
|     { |  | ||||||
|         auto& oldOne = icons[*iter]; |         auto& oldOne = icons[*iter]; | ||||||
|         oldOne.replace(Builtin, key); |         oldOne.replace(Builtin, key); | ||||||
|         dataChanged(index(*iter), index(*iter)); |         dataChanged(index(*iter), index(*iter)); | ||||||
|         return true; |         return true; | ||||||
|     } |     } else { | ||||||
|     else |  | ||||||
|     { |  | ||||||
|         // add a new icon |         // add a new icon | ||||||
|         beginInsertRows(QModelIndex(), icons.size(), icons.size()); |         beginInsertRows(QModelIndex(), icons.size(), icons.size()); | ||||||
|         { |         { | ||||||
| @@ -401,15 +380,12 @@ bool IconList::addIcon(const QString &key, const QString &name, const QString &p | |||||||
|     if (icon.isNull()) |     if (icon.isNull()) | ||||||
|         return false; |         return false; | ||||||
|     auto iter = name_index.find(key); |     auto iter = name_index.find(key); | ||||||
|     if (iter != name_index.end()) |     if (iter != name_index.end()) { | ||||||
|     { |  | ||||||
|         auto& oldOne = icons[*iter]; |         auto& oldOne = icons[*iter]; | ||||||
|         oldOne.replace(type, icon, path); |         oldOne.replace(type, icon, path); | ||||||
|         dataChanged(index(*iter), index(*iter)); |         dataChanged(index(*iter), index(*iter)); | ||||||
|         return true; |         return true; | ||||||
|     } |     } else { | ||||||
|     else |  | ||||||
|     { |  | ||||||
|         // add a new icon |         // add a new icon | ||||||
|         beginInsertRows(QModelIndex(), icons.size(), icons.size()); |         beginInsertRows(QModelIndex(), icons.size(), icons.size()); | ||||||
|         { |         { | ||||||
| @@ -432,13 +408,11 @@ void IconList::saveIcon(const QString &key, const QString &path, const char * fo | |||||||
|     pixmap.save(path, format); |     pixmap.save(path, format); | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| void IconList::reindex() | void IconList::reindex() | ||||||
| { | { | ||||||
|     name_index.clear(); |     name_index.clear(); | ||||||
|     int i = 0; |     int i = 0; | ||||||
|     for (auto &iter : icons) |     for (auto& iter : icons) { | ||||||
|     { |  | ||||||
|         name_index[iter.m_key] = i; |         name_index[iter.m_key] = i; | ||||||
|         i++; |         i++; | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -15,10 +15,10 @@ | |||||||
|  |  | ||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
| #include <QMutex> |  | ||||||
| #include <QAbstractListModel> | #include <QAbstractListModel> | ||||||
| #include <QFile> |  | ||||||
| #include <QDir> | #include <QDir> | ||||||
|  | #include <QFile> | ||||||
|  | #include <QMutex> | ||||||
| #include <QtGui/QIcon> | #include <QtGui/QIcon> | ||||||
| #include <memory> | #include <memory> | ||||||
|  |  | ||||||
| @@ -29,8 +29,7 @@ | |||||||
|  |  | ||||||
| class QFileSystemWatcher; | class QFileSystemWatcher; | ||||||
|  |  | ||||||
| class IconList : public QAbstractListModel | class IconList : public QAbstractListModel { | ||||||
| { |  | ||||||
|     Q_OBJECT |     Q_OBJECT | ||||||
|    public: |    public: | ||||||
|     explicit IconList(const QStringList& builtinPaths, QString path, QObject* parent = 0); |     explicit IconList(const QStringList& builtinPaths, QString path, QObject* parent = 0); | ||||||
| @@ -80,6 +79,7 @@ public slots: | |||||||
|    protected slots: |    protected slots: | ||||||
|     void fileChanged(const QString& path); |     void fileChanged(const QString& path); | ||||||
|     void SettingChanged(const Setting& setting, QVariant value); |     void SettingChanged(const Setting& setting, QVariant value); | ||||||
|  |  | ||||||
|    private: |    private: | ||||||
|     shared_qobject_ptr<QFileSystemWatcher> m_watcher; |     shared_qobject_ptr<QFileSystemWatcher> m_watcher; | ||||||
|     bool is_watching; |     bool is_watching; | ||||||
|   | |||||||
| @@ -1,24 +1,18 @@ | |||||||
| #include "IconUtils.h" | #include "IconUtils.h" | ||||||
|  |  | ||||||
| #include "FileSystem.h" |  | ||||||
| #include <QDirIterator> | #include <QDirIterator> | ||||||
|  | #include "FileSystem.h" | ||||||
|  |  | ||||||
| #include <array> | #include <array> | ||||||
|  |  | ||||||
| namespace { | namespace { | ||||||
| std::array<const char *, 6> validIconExtensions = {{ | std::array<const char*, 6> validIconExtensions = { { "svg", "png", "ico", "gif", "jpg", "jpeg" } }; | ||||||
|     "svg", |  | ||||||
|     "png", |  | ||||||
|     "ico", |  | ||||||
|     "gif", |  | ||||||
|     "jpg", |  | ||||||
|     "jpeg" |  | ||||||
| }}; |  | ||||||
| } | } | ||||||
|  |  | ||||||
| namespace IconUtils { | namespace IconUtils { | ||||||
|  |  | ||||||
| QString findBestIconIn(const QString &folder, const QString & iconKey) { | QString findBestIconIn(const QString& folder, const QString& iconKey) | ||||||
|  | { | ||||||
|     int best_found = validIconExtensions.size(); |     int best_found = validIconExtensions.size(); | ||||||
|     QString best_filename; |     QString best_filename; | ||||||
|  |  | ||||||
| @@ -43,7 +37,8 @@ QString findBestIconIn(const QString &folder, const QString & iconKey) { | |||||||
|     return FS::PathCombine(folder, best_filename); |     return FS::PathCombine(folder, best_filename); | ||||||
| } | } | ||||||
|  |  | ||||||
| QString getIconFilter() { | QString getIconFilter() | ||||||
|  | { | ||||||
|     QString out; |     QString out; | ||||||
|     QTextStream stream(&out); |     QTextStream stream(&out); | ||||||
|     stream << '('; |     stream << '('; | ||||||
| @@ -58,5 +53,4 @@ QString getIconFilter() { | |||||||
|     return out; |     return out; | ||||||
| } | } | ||||||
|  |  | ||||||
| } | }  // namespace IconUtils | ||||||
|  |  | ||||||
|   | |||||||
| @@ -10,4 +10,4 @@ QString findBestIconIn(const QString &folder, const QString & iconKey); | |||||||
| // Get icon file type filter for file browser dialogs | // Get icon file type filter for file browser dialogs | ||||||
| QString getIconFilter(); | QString getIconFilter(); | ||||||
|  |  | ||||||
| } | }  // namespace IconUtils | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| // SPDX-License-Identifier: GPL-3.0-only | // SPDX-License-Identifier: GPL-3.0-only | ||||||
| /* | /* | ||||||
|  *  PolyMC - Minecraft Launcher |  *  Prism Launcher - Minecraft Launcher | ||||||
|  *  Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net> |  *  Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net> | ||||||
|  * |  * | ||||||
|  *  This program is free software: you can redistribute it and/or modify |  *  This program is free software: you can redistribute it and/or modify | ||||||
| @@ -40,8 +40,7 @@ | |||||||
| IconType operator--(IconType& t, int) | IconType operator--(IconType& t, int) | ||||||
| { | { | ||||||
|     IconType temp = t; |     IconType temp = t; | ||||||
|     switch (t) |     switch (t) { | ||||||
|     { |  | ||||||
|         case IconType::Builtin: |         case IconType::Builtin: | ||||||
|             t = IconType::ToBeDeleted; |             t = IconType::ToBeDeleted; | ||||||
|             break; |             break; | ||||||
| @@ -51,8 +50,7 @@ IconType operator--(IconType &t, int) | |||||||
|         case IconType::FileBased: |         case IconType::FileBased: | ||||||
|             t = IconType::Transient; |             t = IconType::Transient; | ||||||
|             break; |             break; | ||||||
|     default: |         default: { | ||||||
|     { |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     return temp; |     return temp; | ||||||
| @@ -90,10 +88,8 @@ void MMCIcon::remove(IconType rm_type) | |||||||
| { | { | ||||||
|     m_images[rm_type].filename = QString(); |     m_images[rm_type].filename = QString(); | ||||||
|     m_images[rm_type].icon = QIcon(); |     m_images[rm_type].icon = QIcon(); | ||||||
|     for (auto iter = rm_type; iter != IconType::ToBeDeleted; iter--) |     for (auto iter = rm_type; iter != IconType::ToBeDeleted; iter--) { | ||||||
|     { |         if (m_images[iter].present()) { | ||||||
|         if (m_images[iter].present()) |  | ||||||
|         { |  | ||||||
|             m_current_type = iter; |             m_current_type = iter; | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
| @@ -103,8 +99,7 @@ void MMCIcon::remove(IconType rm_type) | |||||||
|  |  | ||||||
| void MMCIcon::replace(IconType new_type, QIcon icon, QString path) | void MMCIcon::replace(IconType new_type, QIcon icon, QString path) | ||||||
| { | { | ||||||
|     if (new_type > m_current_type || m_current_type == IconType::ToBeDeleted) |     if (new_type > m_current_type || m_current_type == IconType::ToBeDeleted) { | ||||||
|     { |  | ||||||
|         m_current_type = new_type; |         m_current_type = new_type; | ||||||
|     } |     } | ||||||
|     m_images[new_type].icon = icon; |     m_images[new_type].icon = icon; | ||||||
| @@ -114,8 +109,7 @@ void MMCIcon::replace(IconType new_type, QIcon icon, QString path) | |||||||
|  |  | ||||||
| void MMCIcon::replace(IconType new_type, const QString& key) | void MMCIcon::replace(IconType new_type, const QString& key) | ||||||
| { | { | ||||||
|     if (new_type > m_current_type || m_current_type == IconType::ToBeDeleted) |     if (new_type > m_current_type || m_current_type == IconType::ToBeDeleted) { | ||||||
|     { |  | ||||||
|         m_current_type = new_type; |         m_current_type = new_type; | ||||||
|     } |     } | ||||||
|     m_images[new_type].icon = QIcon(); |     m_images[new_type].icon = QIcon(); | ||||||
| @@ -131,7 +125,6 @@ QString MMCIcon::getFilePath() const | |||||||
|     return m_images[m_current_type].filename; |     return m_images[m_current_type].filename; | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| bool MMCIcon::isBuiltIn() const | bool MMCIcon::isBuiltIn() const | ||||||
| { | { | ||||||
|     return m_current_type == IconType::Builtin; |     return m_current_type == IconType::Builtin; | ||||||
|   | |||||||
| @@ -14,32 +14,20 @@ | |||||||
|  */ |  */ | ||||||
|  |  | ||||||
| #pragma once | #pragma once | ||||||
| #include <QString> |  | ||||||
| #include <QDateTime> | #include <QDateTime> | ||||||
| #include <QIcon> | #include <QIcon> | ||||||
|  | #include <QString> | ||||||
|  |  | ||||||
| enum IconType : unsigned | enum IconType : unsigned { Builtin, Transient, FileBased, ICONS_TOTAL, ToBeDeleted }; | ||||||
| { |  | ||||||
|     Builtin, |  | ||||||
|     Transient, |  | ||||||
|     FileBased, |  | ||||||
|     ICONS_TOTAL, |  | ||||||
|     ToBeDeleted |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| struct MMCImage | struct MMCImage { | ||||||
| { |  | ||||||
|     QIcon icon; |     QIcon icon; | ||||||
|     QString key; |     QString key; | ||||||
|     QString filename; |     QString filename; | ||||||
|     bool present() const |     bool present() const { return !icon.isNull() || !key.isEmpty(); } | ||||||
|     { |  | ||||||
|         return !icon.isNull() || !key.isEmpty(); |  | ||||||
|     } |  | ||||||
| }; | }; | ||||||
|  |  | ||||||
| struct MMCIcon | struct MMCIcon { | ||||||
| { |  | ||||||
|     QString m_key; |     QString m_key; | ||||||
|     QString m_name; |     QString m_name; | ||||||
|     MMCImage m_images[ICONS_TOTAL]; |     MMCImage m_images[ICONS_TOTAL]; | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| // SPDX-License-Identifier: GPL-3.0-only | // SPDX-License-Identifier: GPL-3.0-only | ||||||
| /* | /* | ||||||
|  *  PolyMC - Minecraft Launcher |  *  Prism Launcher - Minecraft Launcher | ||||||
|  *  Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net> |  *  Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net> | ||||||
|  * |  * | ||||||
|  *  This program is free software: you can redistribute it and/or modify |  *  This program is free software: you can redistribute it and/or modify | ||||||
| @@ -35,26 +35,23 @@ | |||||||
|  |  | ||||||
| #include "JavaChecker.h" | #include "JavaChecker.h" | ||||||
|  |  | ||||||
| #include <QFile> |  | ||||||
| #include <QProcess> |  | ||||||
| #include <QMap> |  | ||||||
| #include <QDebug> | #include <QDebug> | ||||||
|  | #include <QFile> | ||||||
|  | #include <QMap> | ||||||
|  | #include <QProcess> | ||||||
|  |  | ||||||
| #include "JavaUtils.h" |  | ||||||
| #include "FileSystem.h" |  | ||||||
| #include "Commandline.h" |  | ||||||
| #include "Application.h" | #include "Application.h" | ||||||
|  | #include "Commandline.h" | ||||||
|  | #include "FileSystem.h" | ||||||
|  | #include "JavaUtils.h" | ||||||
|  |  | ||||||
| JavaChecker::JavaChecker(QObject *parent) : QObject(parent) | JavaChecker::JavaChecker(QObject* parent) : QObject(parent) {} | ||||||
| { |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void JavaChecker::performCheck() | void JavaChecker::performCheck() | ||||||
| { | { | ||||||
|     QString checkerJar = JavaUtils::getJavaCheckPath(); |     QString checkerJar = JavaUtils::getJavaCheckPath(); | ||||||
|  |  | ||||||
|     if (checkerJar.isEmpty()) |     if (checkerJar.isEmpty()) { | ||||||
|     { |  | ||||||
|         qDebug() << "Java checker library could not be found. Please check your installation."; |         qDebug() << "Java checker library could not be found. Please check your installation."; | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
| @@ -62,21 +59,17 @@ void JavaChecker::performCheck() | |||||||
|     QStringList args; |     QStringList args; | ||||||
|  |  | ||||||
|     process.reset(new QProcess()); |     process.reset(new QProcess()); | ||||||
|     if(m_args.size()) |     if (m_args.size()) { | ||||||
|     { |  | ||||||
|         auto extraArgs = Commandline::splitArgs(m_args); |         auto extraArgs = Commandline::splitArgs(m_args); | ||||||
|         args.append(extraArgs); |         args.append(extraArgs); | ||||||
|     } |     } | ||||||
|     if(m_minMem != 0) |     if (m_minMem != 0) { | ||||||
|     { |  | ||||||
|         args << QString("-Xms%1m").arg(m_minMem); |         args << QString("-Xms%1m").arg(m_minMem); | ||||||
|     } |     } | ||||||
|     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) { | ||||||
|     { |  | ||||||
|         args << QString("-XX:PermSize=%1m").arg(m_permGen); |         args << QString("-XX:PermSize=%1m").arg(m_permGen); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -130,8 +123,7 @@ void JavaChecker::finished(int exitcode, QProcess::ExitStatus status) | |||||||
|     qWarning() << "STDERR" << m_stderr; |     qWarning() << "STDERR" << m_stderr; | ||||||
|     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 = JavaCheckResult::Validity::Errored; | ||||||
|         emit checkFinished(result); |         emit checkFinished(result); | ||||||
|         return; |         return; | ||||||
| @@ -146,8 +138,7 @@ void JavaChecker::finished(int exitcode, QProcess::ExitStatus status) | |||||||
| #else | #else | ||||||
|     QStringList lines = m_stdout.split("\n", QString::SkipEmptyParts); |     QStringList lines = m_stdout.split("\n", QString::SkipEmptyParts); | ||||||
| #endif | #endif | ||||||
|     for(QString line : lines) |     for (QString line : lines) { | ||||||
|     { |  | ||||||
|         line = line.trimmed(); |         line = line.trimmed(); | ||||||
|         // NOTE: workaround for GH-4125, where garbage is getting printed into stdout on bedrock linux |         // NOTE: workaround for GH-4125, where garbage is getting printed into stdout on bedrock linux | ||||||
|         if (line.contains("/bedrock/strata")) { |         if (line.contains("/bedrock/strata")) { | ||||||
| @@ -159,18 +150,14 @@ void JavaChecker::finished(int exitcode, QProcess::ExitStatus status) | |||||||
| #else | #else | ||||||
|         auto parts = line.split('=', QString::SkipEmptyParts); |         auto parts = line.split('=', QString::SkipEmptyParts); | ||||||
| #endif | #endif | ||||||
|         if(parts.size() != 2 || parts[0].isEmpty() || parts[1].isEmpty()) |         if (parts.size() != 2 || parts[0].isEmpty() || parts[1].isEmpty()) { | ||||||
|         { |  | ||||||
|             continue; |             continue; | ||||||
|         } |         } else { | ||||||
|         else |  | ||||||
|         { |  | ||||||
|             results.insert(parts[0], parts[1]); |             results.insert(parts[0], parts[1]); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     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 = JavaCheckResult::Validity::ReturnedInvalidData; | ||||||
|         emit checkFinished(result); |         emit checkFinished(result); | ||||||
|         return; |         return; | ||||||
| @@ -181,7 +168,6 @@ 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 = JavaCheckResult::Validity::Valid; | ||||||
|     result.is_64bit = is_64; |     result.is_64bit = is_64; | ||||||
|     result.mojangPlatform = is_64 ? "64" : "32"; |     result.mojangPlatform = is_64 ? "64" : "32"; | ||||||
| @@ -194,8 +180,7 @@ void JavaChecker::finished(int exitcode, QProcess::ExitStatus status) | |||||||
|  |  | ||||||
| void JavaChecker::error(QProcess::ProcessError err) | void JavaChecker::error(QProcess::ProcessError err) | ||||||
| { | { | ||||||
|     if(err == QProcess::FailedToStart) |     if (err == QProcess::FailedToStart) { | ||||||
|     { |  | ||||||
|         qDebug() << "Java checker has failed to start."; |         qDebug() << "Java checker has failed to start."; | ||||||
|         qDebug() << "Process environment:"; |         qDebug() << "Process environment:"; | ||||||
|         qDebug() << process->environment(); |         qDebug() << process->environment(); | ||||||
| @@ -216,8 +201,7 @@ void JavaChecker::error(QProcess::ProcessError err) | |||||||
| void JavaChecker::timeout() | void JavaChecker::timeout() | ||||||
| { | { | ||||||
|     // NO MERCY. NO ABUSE. |     // NO MERCY. NO ABUSE. | ||||||
|     if(process) |     if (process) { | ||||||
|     { |  | ||||||
|         qDebug() << "Java checker has been killed by timeout."; |         qDebug() << "Java checker has been killed by timeout."; | ||||||
|         process->kill(); |         process->kill(); | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -9,8 +9,7 @@ | |||||||
|  |  | ||||||
| class JavaChecker; | class JavaChecker; | ||||||
|  |  | ||||||
| struct JavaCheckResult | struct JavaCheckResult { | ||||||
| { |  | ||||||
|     QString path; |     QString path; | ||||||
|     QString mojangPlatform; |     QString mojangPlatform; | ||||||
|     QString realPlatform; |     QString realPlatform; | ||||||
| @@ -20,18 +19,12 @@ struct JavaCheckResult | |||||||
|     QString errorLog; |     QString errorLog; | ||||||
|     bool is_64bit = false; |     bool is_64bit = false; | ||||||
|     int id; |     int id; | ||||||
|     enum class Validity |     enum class Validity { Errored, ReturnedInvalidData, Valid } validity = Validity::Errored; | ||||||
|     { |  | ||||||
|         Errored, |  | ||||||
|         ReturnedInvalidData, |  | ||||||
|         Valid |  | ||||||
|     } validity = Validity::Errored; |  | ||||||
| }; | }; | ||||||
|  |  | ||||||
| typedef shared_qobject_ptr<QProcess> QProcessPtr; | typedef shared_qobject_ptr<QProcess> QProcessPtr; | ||||||
| typedef shared_qobject_ptr<JavaChecker> JavaCheckerPtr; | typedef shared_qobject_ptr<JavaChecker> JavaCheckerPtr; | ||||||
| class JavaChecker : public QObject | class JavaChecker : public QObject { | ||||||
| { |  | ||||||
|     Q_OBJECT |     Q_OBJECT | ||||||
|    public: |    public: | ||||||
|     explicit JavaChecker(QObject* parent = 0); |     explicit JavaChecker(QObject* parent = 0); | ||||||
| @@ -46,13 +39,13 @@ public: | |||||||
|  |  | ||||||
|    signals: |    signals: | ||||||
|     void checkFinished(JavaCheckResult result); |     void checkFinished(JavaCheckResult result); | ||||||
|  |  | ||||||
|    private: |    private: | ||||||
|     QProcessPtr process; |     QProcessPtr process; | ||||||
|     QTimer killTimer; |     QTimer killTimer; | ||||||
|     QString m_stdout; |     QString m_stdout; | ||||||
|     QString m_stderr; |     QString m_stderr; | ||||||
| public |    public slots: | ||||||
| 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); | ||||||
|   | |||||||
| @@ -20,14 +20,12 @@ | |||||||
| void JavaCheckerJob::partFinished(JavaCheckResult result) | void JavaCheckerJob::partFinished(JavaCheckResult result) | ||||||
| { | { | ||||||
|     num_finished++; |     num_finished++; | ||||||
|     qDebug() << m_job_name.toLocal8Bit() << "progress:" << num_finished << "/" |     qDebug() << m_job_name.toLocal8Bit() << "progress:" << num_finished << "/" << javacheckers.size(); | ||||||
|                 << javacheckers.size(); |  | ||||||
|     setProgress(num_finished, javacheckers.size()); |     setProgress(num_finished, javacheckers.size()); | ||||||
|  |  | ||||||
|     javaresults.replace(result.id, result); |     javaresults.replace(result.id, result); | ||||||
|  |  | ||||||
|     if (num_finished == javacheckers.size()) |     if (num_finished == javacheckers.size()) { | ||||||
|     { |  | ||||||
|         emitSucceeded(); |         emitSucceeded(); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -35,8 +33,7 @@ void JavaCheckerJob::partFinished(JavaCheckResult result) | |||||||
| void JavaCheckerJob::executeTask() | void JavaCheckerJob::executeTask() | ||||||
| { | { | ||||||
|     qDebug() << m_job_name.toLocal8Bit() << " started."; |     qDebug() << m_job_name.toLocal8Bit() << " started."; | ||||||
|     for (auto iter : javacheckers) |     for (auto iter : javacheckers) { | ||||||
|     { |  | ||||||
|         javaresults.append(JavaCheckResult()); |         javaresults.append(JavaCheckResult()); | ||||||
|         connect(iter.get(), &JavaChecker::checkFinished, this, &JavaCheckerJob::partFinished); |         connect(iter.get(), &JavaChecker::checkFinished, this, &JavaCheckerJob::partFinished); | ||||||
|         iter->performCheck(); |         iter->performCheck(); | ||||||
|   | |||||||
| @@ -23,8 +23,7 @@ class JavaCheckerJob; | |||||||
| typedef shared_qobject_ptr<JavaCheckerJob> JavaCheckerJobPtr; | typedef shared_qobject_ptr<JavaCheckerJob> JavaCheckerJobPtr; | ||||||
|  |  | ||||||
| // FIXME: this just seems horribly redundant | // FIXME: this just seems horribly redundant | ||||||
| class JavaCheckerJob : public Task | class JavaCheckerJob : public Task { | ||||||
| { |  | ||||||
|     Q_OBJECT |     Q_OBJECT | ||||||
|    public: |    public: | ||||||
|     explicit JavaCheckerJob(QString job_name) : Task(), m_job_name(job_name){}; |     explicit JavaCheckerJob(QString job_name) : Task(), m_job_name(job_name){}; | ||||||
| @@ -34,18 +33,14 @@ public: | |||||||
|     { |     { | ||||||
|         javacheckers.append(base); |         javacheckers.append(base); | ||||||
|         // if this is already running, the action needs to be started right away! |         // if this is already running, the action needs to be started right away! | ||||||
|         if (isRunning()) |         if (isRunning()) { | ||||||
|         { |  | ||||||
|             setProgress(num_finished, javacheckers.size()); |             setProgress(num_finished, javacheckers.size()); | ||||||
|             connect(base.get(), &JavaChecker::checkFinished, this, &JavaCheckerJob::partFinished); |             connect(base.get(), &JavaChecker::checkFinished, this, &JavaCheckerJob::partFinished); | ||||||
|             base->performCheck(); |             base->performCheck(); | ||||||
|         } |         } | ||||||
|         return true; |         return true; | ||||||
|     } |     } | ||||||
|     QList<JavaCheckResult> getResults() |     QList<JavaCheckResult> getResults() { return javaresults; } | ||||||
|     { |  | ||||||
|         return javaresults; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|    private slots: |    private slots: | ||||||
|     void partFinished(JavaCheckResult result); |     void partFinished(JavaCheckResult result); | ||||||
|   | |||||||
| @@ -39,14 +39,12 @@ | |||||||
|  |  | ||||||
| #include <QDebug> | #include <QDebug> | ||||||
|  |  | ||||||
| #include "java/JavaInstallList.h" |  | ||||||
| #include "java/JavaCheckerJob.h" | #include "java/JavaCheckerJob.h" | ||||||
|  | #include "java/JavaInstallList.h" | ||||||
| #include "java/JavaUtils.h" | #include "java/JavaUtils.h" | ||||||
| #include "minecraft/VersionFilterData.h" | #include "minecraft/VersionFilterData.h" | ||||||
|  |  | ||||||
| JavaInstallList::JavaInstallList(QObject *parent) : BaseVersionList(parent) | JavaInstallList::JavaInstallList(QObject* parent) : BaseVersionList(parent) {} | ||||||
| { |  | ||||||
| } |  | ||||||
|  |  | ||||||
| Task::Ptr JavaInstallList::getLoadTask() | Task::Ptr JavaInstallList::getLoadTask() | ||||||
| { | { | ||||||
| @@ -56,8 +54,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_loadTask; | ||||||
|     } |     } | ||||||
|     return nullptr; |     return nullptr; | ||||||
| @@ -65,8 +62,7 @@ Task::Ptr JavaInstallList::getCurrentTask() | |||||||
|  |  | ||||||
| void JavaInstallList::load() | 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_loadTask.reset(new JavaListLoadTask(this)); | ||||||
|         m_loadTask->start(); |         m_loadTask->start(); | ||||||
| @@ -97,8 +93,7 @@ QVariant JavaInstallList::data(const QModelIndex &index, int role) const | |||||||
|         return QVariant(); |         return QVariant(); | ||||||
|  |  | ||||||
|     auto version = std::dynamic_pointer_cast<JavaInstall>(m_vlist[index.row()]); |     auto version = std::dynamic_pointer_cast<JavaInstall>(m_vlist[index.row()]); | ||||||
|     switch (role) |     switch (role) { | ||||||
|     { |  | ||||||
|         case SortRole: |         case SortRole: | ||||||
|             return -index.row(); |             return -index.row(); | ||||||
|         case VersionPointerRole: |         case VersionPointerRole: | ||||||
| @@ -123,14 +118,12 @@ BaseVersionList::RoleList JavaInstallList::providesRoles() const | |||||||
|     return { VersionPointerRole, VersionIdRole, VersionRole, RecommendedRole, PathRole, ArchitectureRole }; |     return { VersionPointerRole, VersionIdRole, VersionRole, RecommendedRole, PathRole, ArchitectureRole }; | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| void JavaInstallList::updateListData(QList<BaseVersion::Ptr> versions) | void JavaInstallList::updateListData(QList<BaseVersion::Ptr> versions) | ||||||
| { | { | ||||||
|     beginResetModel(); |     beginResetModel(); | ||||||
|     m_vlist = versions; |     m_vlist = versions; | ||||||
|     sortVersions(); |     sortVersions(); | ||||||
|     if(m_vlist.size()) |     if (m_vlist.size()) { | ||||||
|     { |  | ||||||
|         auto best = std::dynamic_pointer_cast<JavaInstall>(m_vlist[0]); |         auto best = std::dynamic_pointer_cast<JavaInstall>(m_vlist[0]); | ||||||
|         best->recommended = true; |         best->recommended = true; | ||||||
|     } |     } | ||||||
| @@ -159,9 +152,7 @@ JavaListLoadTask::JavaListLoadTask(JavaInstallList *vlist) : Task() | |||||||
|     m_currentRecommended = NULL; |     m_currentRecommended = NULL; | ||||||
| } | } | ||||||
|  |  | ||||||
| JavaListLoadTask::~JavaListLoadTask() | JavaListLoadTask::~JavaListLoadTask() {} | ||||||
| { |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void JavaListLoadTask::executeTask() | void JavaListLoadTask::executeTask() | ||||||
| { | { | ||||||
| @@ -176,8 +167,7 @@ void JavaListLoadTask::executeTask() | |||||||
|  |  | ||||||
|     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; |         qDebug() << " " << candidate; | ||||||
|  |  | ||||||
|         auto candidate_checker = new JavaChecker(); |         auto candidate_checker = new JavaChecker(); | ||||||
| @@ -197,10 +187,8 @@ void JavaListLoadTask::javaCheckerFinished() | |||||||
|     auto results = m_job->getResults(); |     auto results = m_job->getResults(); | ||||||
|  |  | ||||||
|     qDebug() << "Found the following valid Java installations:"; |     qDebug() << "Found the following valid Java installations:"; | ||||||
|     for(JavaCheckResult result : results) |     for (JavaCheckResult result : results) { | ||||||
|     { |         if (result.validity == JavaCheckResult::Validity::Valid) { | ||||||
|         if(result.validity == JavaCheckResult::Validity::Valid) |  | ||||||
|         { |  | ||||||
|             JavaInstallPtr javaVersion(new JavaInstall()); |             JavaInstallPtr javaVersion(new JavaInstall()); | ||||||
|  |  | ||||||
|             javaVersion->id = result.javaVersion; |             javaVersion->id = result.javaVersion; | ||||||
| @@ -213,13 +201,11 @@ void JavaListLoadTask::javaCheckerFinished() | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     QList<BaseVersion::Ptr> javas_bvp; |     QList<BaseVersion::Ptr> javas_bvp; | ||||||
|     for (auto java : candidates) |     for (auto java : candidates) { | ||||||
|     { |  | ||||||
|         // qDebug() << java->id << java->arch << " at " << java->path; |         // qDebug() << java->id << java->arch << " at " << java->path; | ||||||
|         BaseVersion::Ptr bp_java = std::dynamic_pointer_cast<BaseVersion>(java); |         BaseVersion::Ptr bp_java = std::dynamic_pointer_cast<BaseVersion>(java); | ||||||
|  |  | ||||||
|         if (bp_java) |         if (bp_java) { | ||||||
|         { |  | ||||||
|             javas_bvp.append(java); |             javas_bvp.append(java); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -15,8 +15,8 @@ | |||||||
|  |  | ||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
| #include <QObject> |  | ||||||
| #include <QAbstractListModel> | #include <QAbstractListModel> | ||||||
|  | #include <QObject> | ||||||
|  |  | ||||||
| #include "BaseVersionList.h" | #include "BaseVersionList.h" | ||||||
| #include "tasks/Task.h" | #include "tasks/Task.h" | ||||||
| @@ -28,15 +28,10 @@ | |||||||
|  |  | ||||||
| class JavaListLoadTask; | class JavaListLoadTask; | ||||||
|  |  | ||||||
| class JavaInstallList : public BaseVersionList | class JavaInstallList : public BaseVersionList { | ||||||
| { |  | ||||||
|     Q_OBJECT |     Q_OBJECT | ||||||
|     enum class Status |     enum class Status { NotDone, InProgress, Done }; | ||||||
|     { |  | ||||||
|         NotDone, |  | ||||||
|         InProgress, |  | ||||||
|         Done |  | ||||||
|     }; |  | ||||||
|    public: |    public: | ||||||
|     explicit JavaInstallList(QObject* parent = 0); |     explicit JavaInstallList(QObject* parent = 0); | ||||||
|  |  | ||||||
| @@ -62,8 +57,7 @@ protected: | |||||||
|     QList<BaseVersion::Ptr> m_vlist; |     QList<BaseVersion::Ptr> m_vlist; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| class JavaListLoadTask : public Task | class JavaListLoadTask : public Task { | ||||||
| { |  | ||||||
|     Q_OBJECT |     Q_OBJECT | ||||||
|  |  | ||||||
|    public: |    public: | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| // SPDX-License-Identifier: GPL-3.0-only | // SPDX-License-Identifier: GPL-3.0-only | ||||||
| /* | /* | ||||||
|  *  PolyMC - Minecraft Launcher |  *  Prism Launcher - Minecraft Launcher | ||||||
|  *  Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net> |  *  Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net> | ||||||
|  * |  * | ||||||
|  *  This program is free software: you can redistribute it and/or modify |  *  This program is free software: you can redistribute it and/or modify | ||||||
| @@ -33,24 +33,21 @@ | |||||||
|  *      limitations under the License. |  *      limitations under the License. | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| #include <QStringList> |  | ||||||
| #include <QString> |  | ||||||
| #include <QDir> | #include <QDir> | ||||||
|  | #include <QString> | ||||||
| #include <QStringList> | #include <QStringList> | ||||||
|  |  | ||||||
| #include <settings/Setting.h> | #include <settings/Setting.h> | ||||||
|  |  | ||||||
| #include <QDebug> | #include <QDebug> | ||||||
| #include "java/JavaUtils.h" |  | ||||||
| #include "java/JavaInstallList.h" |  | ||||||
| #include "FileSystem.h" |  | ||||||
| #include "Application.h" | #include "Application.h" | ||||||
|  | #include "FileSystem.h" | ||||||
|  | #include "java/JavaInstallList.h" | ||||||
|  | #include "java/JavaUtils.h" | ||||||
|  |  | ||||||
| #define IBUS "@im=ibus" | #define IBUS "@im=ibus" | ||||||
|  |  | ||||||
| JavaUtils::JavaUtils() | JavaUtils::JavaUtils() {} | ||||||
| { |  | ||||||
| } |  | ||||||
|  |  | ||||||
| QString stripVariableEntries(QString name, QString target, QString remove) | QString stripVariableEntries(QString name, QString target, QString remove) | ||||||
| { | { | ||||||
| @@ -65,8 +62,7 @@ QString stripVariableEntries(QString name, QString target, QString remove) | |||||||
|     for (QString item : toRemove) { |     for (QString item : toRemove) { | ||||||
|         bool removed = targetItems.removeOne(item); |         bool removed = targetItems.removeOne(item); | ||||||
|         if (!removed) |         if (!removed) | ||||||
|             qWarning() << "Entry" << item |             qWarning() << "Entry" << item << "could not be stripped from variable" << name; | ||||||
|                 << "could not be stripped from variable" << name; |  | ||||||
|     } |     } | ||||||
|     return targetItems.join(delimiter); |     return targetItems.join(delimiter); | ||||||
| } | } | ||||||
| @@ -77,20 +73,10 @@ QProcessEnvironment CleanEnviroment() | |||||||
|     QProcessEnvironment rawenv = QProcessEnvironment::systemEnvironment(); |     QProcessEnvironment rawenv = QProcessEnvironment::systemEnvironment(); | ||||||
|     QProcessEnvironment env; |     QProcessEnvironment env; | ||||||
|  |  | ||||||
|     QStringList ignored = |     QStringList ignored = { "JAVA_ARGS", "CLASSPATH",     "CONFIGPATH",   "JAVA_HOME", | ||||||
|     { |                             "JRE_HOME",  "_JAVA_OPTIONS", "JAVA_OPTIONS", "JAVA_TOOL_OPTIONS" }; | ||||||
|         "JAVA_ARGS", |  | ||||||
|         "CLASSPATH", |  | ||||||
|         "CONFIGPATH", |  | ||||||
|         "JAVA_HOME", |  | ||||||
|         "JRE_HOME", |  | ||||||
|         "_JAVA_OPTIONS", |  | ||||||
|         "JAVA_OPTIONS", |  | ||||||
|         "JAVA_TOOL_OPTIONS" |  | ||||||
|     }; |  | ||||||
|  |  | ||||||
|     QStringList stripped = |     QStringList stripped = { | ||||||
|     { |  | ||||||
| #if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) || defined(Q_OS_OPENBSD) | #if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) || defined(Q_OS_OPENBSD) | ||||||
|         "LD_LIBRARY_PATH", |         "LD_LIBRARY_PATH", | ||||||
|         "LD_PRELOAD", |         "LD_PRELOAD", | ||||||
| @@ -98,12 +84,10 @@ QProcessEnvironment CleanEnviroment() | |||||||
|         "QT_PLUGIN_PATH", |         "QT_PLUGIN_PATH", | ||||||
|         "QT_FONTPATH" |         "QT_FONTPATH" | ||||||
|     }; |     }; | ||||||
|     for(auto key: rawenv.keys()) |     for (auto key : rawenv.keys()) { | ||||||
|     { |  | ||||||
|         auto value = rawenv.value(key); |         auto value = rawenv.value(key); | ||||||
|         // filter out dangerous java crap |         // filter out dangerous java crap | ||||||
|         if(ignored.contains(key)) |         if (ignored.contains(key)) { | ||||||
|         { |  | ||||||
|             qDebug() << "Env: ignoring" << key << value; |             qDebug() << "Env: ignoring" << key << value; | ||||||
|             continue; |             continue; | ||||||
|         } |         } | ||||||
| @@ -111,13 +95,11 @@ QProcessEnvironment CleanEnviroment() | |||||||
|         // These are used to strip the original variables |         // These are used to strip the original variables | ||||||
|         // If there is "LD_LIBRARY_PATH" and "LAUNCHER_LD_LIBRARY_PATH", we want to |         // If there is "LD_LIBRARY_PATH" and "LAUNCHER_LD_LIBRARY_PATH", we want to | ||||||
|         // remove all values in "LAUNCHER_LD_LIBRARY_PATH" from "LD_LIBRARY_PATH" |         // remove all values in "LAUNCHER_LD_LIBRARY_PATH" from "LD_LIBRARY_PATH" | ||||||
|         if(key.startsWith("LAUNCHER_")) |         if (key.startsWith("LAUNCHER_")) { | ||||||
|         { |  | ||||||
|             qDebug() << "Env: ignoring" << key << value; |             qDebug() << "Env: ignoring" << key << value; | ||||||
|             continue; |             continue; | ||||||
|         } |         } | ||||||
|         if(stripped.contains(key)) |         if (stripped.contains(key)) { | ||||||
|         { |  | ||||||
|             QString newValue = stripVariableEntries(key, value, rawenv.value("LAUNCHER_" + key)); |             QString newValue = stripVariableEntries(key, value, rawenv.value("LAUNCHER_" + key)); | ||||||
|  |  | ||||||
|             qDebug() << "Env: stripped" << key << value << "to" << newValue; |             qDebug() << "Env: stripped" << key << value << "to" << newValue; | ||||||
| @@ -125,8 +107,7 @@ QProcessEnvironment CleanEnviroment() | |||||||
| #if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) || defined(Q_OS_OPENBSD) | #if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) || defined(Q_OS_OPENBSD) | ||||||
|         // Strip IBus |         // Strip IBus | ||||||
|         // IBus is a Linux IME framework. For some reason, it breaks MC? |         // IBus is a Linux IME framework. For some reason, it breaks MC? | ||||||
|         if (key == "XMODIFIERS" && value.contains(IBUS)) |         if (key == "XMODIFIERS" && value.contains(IBUS)) { | ||||||
|         { |  | ||||||
|             QString save = value; |             QString save = value; | ||||||
|             value.replace(IBUS, ""); |             value.replace(IBUS, ""); | ||||||
|             qDebug() << "Env: stripped" << IBUS << "from" << save << ":" << value; |             qDebug() << "Env: stripped" << IBUS << "from" << save << ":" << value; | ||||||
| @@ -137,8 +118,7 @@ QProcessEnvironment CleanEnviroment() | |||||||
|     } |     } | ||||||
| #ifdef Q_OS_LINUX | #ifdef Q_OS_LINUX | ||||||
|     // HACK: Workaround for QTBUG-42500 |     // HACK: Workaround for QTBUG-42500 | ||||||
|     if(!env.contains("LD_LIBRARY_PATH")) |     if (!env.contains("LD_LIBRARY_PATH")) { | ||||||
|     { |  | ||||||
|         env.insert("LD_LIBRARY_PATH", ""); |         env.insert("LD_LIBRARY_PATH", ""); | ||||||
|     } |     } | ||||||
| #endif | #endif | ||||||
| @@ -186,8 +166,7 @@ QStringList addJavasFromEnv(QList<QString> javas) | |||||||
| #else | #else | ||||||
|     QList<QString> javaPaths = env.split(QLatin1String(":")); |     QList<QString> javaPaths = env.split(QLatin1String(":")); | ||||||
| #endif | #endif | ||||||
|     for(QString i : javaPaths) |     for (QString i : javaPaths) { | ||||||
|     { |  | ||||||
|         javas.append(i); |         javas.append(i); | ||||||
|     }; |     }; | ||||||
|     return javas; |     return javas; | ||||||
| @@ -205,9 +184,8 @@ QList<JavaInstallPtr> JavaUtils::FindJavaFromRegistryKey(DWORD keyType, QString | |||||||
|         archType = "32"; |         archType = "32"; | ||||||
|  |  | ||||||
|     HKEY jreKey; |     HKEY jreKey; | ||||||
|     if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, keyName.toStdWString().c_str(), 0, |     if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, keyName.toStdWString().c_str(), 0, KEY_READ | keyType | KEY_ENUMERATE_SUB_KEYS, &jreKey) == | ||||||
|                       KEY_READ | keyType | KEY_ENUMERATE_SUB_KEYS, &jreKey) == ERROR_SUCCESS) |         ERROR_SUCCESS) { | ||||||
|     { |  | ||||||
|         // Read the current type version from the registry. |         // Read the current type version from the registry. | ||||||
|         // This will be used to find any key that contains the JavaHome value. |         // This will be used to find any key that contains the JavaHome value. | ||||||
|  |  | ||||||
| @@ -215,35 +193,26 @@ QList<JavaInstallPtr> JavaUtils::FindJavaFromRegistryKey(DWORD keyType, QString | |||||||
|         DWORD subKeyNameSize, numSubKeys, retCode; |         DWORD subKeyNameSize, numSubKeys, retCode; | ||||||
|  |  | ||||||
|         // Get the number of subkeys |         // Get the number of subkeys | ||||||
|         RegQueryInfoKeyW(jreKey, NULL, NULL, NULL, &numSubKeys, NULL, NULL, NULL, NULL, NULL, |         RegQueryInfoKeyW(jreKey, NULL, NULL, NULL, &numSubKeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL); | ||||||
|                         NULL, NULL); |  | ||||||
|  |  | ||||||
|         // Iterate until RegEnumKeyEx fails |         // Iterate until RegEnumKeyEx fails | ||||||
|         if (numSubKeys > 0) |         if (numSubKeys > 0) { | ||||||
|         { |             for (DWORD i = 0; i < numSubKeys; i++) { | ||||||
|             for (DWORD i = 0; i < numSubKeys; i++) |  | ||||||
|             { |  | ||||||
|                 subKeyNameSize = 255; |                 subKeyNameSize = 255; | ||||||
|                 retCode = RegEnumKeyExW(jreKey, i, subKeyName, &subKeyNameSize, NULL, NULL, NULL, |                 retCode = RegEnumKeyExW(jreKey, i, subKeyName, &subKeyNameSize, NULL, NULL, NULL, NULL); | ||||||
|                                         NULL); |  | ||||||
|                 QString newSubkeyName = QString::fromWCharArray(subKeyName); |                 QString newSubkeyName = QString::fromWCharArray(subKeyName); | ||||||
|                 if (retCode == ERROR_SUCCESS) |                 if (retCode == ERROR_SUCCESS) { | ||||||
|                 { |  | ||||||
|                     // Now open the registry key for the version that we just got. |                     // Now open the registry key for the version that we just got. | ||||||
|                     QString newKeyName = keyName + "\\" + newSubkeyName + subkeySuffix; |                     QString newKeyName = keyName + "\\" + newSubkeyName + subkeySuffix; | ||||||
|  |  | ||||||
|                     HKEY newKey; |                     HKEY newKey; | ||||||
|                     if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, newKeyName.toStdWString().c_str(), 0, |                     if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, newKeyName.toStdWString().c_str(), 0, KEY_READ | KEY_WOW64_64KEY, &newKey) == | ||||||
|                                       KEY_READ | KEY_WOW64_64KEY, &newKey) == ERROR_SUCCESS) |                         ERROR_SUCCESS) { | ||||||
|                     { |  | ||||||
|                         // Read the JavaHome value to find where Java is installed. |                         // Read the JavaHome value to find where Java is installed. | ||||||
|                         DWORD valueSz = 0; |                         DWORD valueSz = 0; | ||||||
|                         if (RegQueryValueExW(newKey, keyJavaDir.toStdWString().c_str(), NULL, NULL, NULL, |                         if (RegQueryValueExW(newKey, keyJavaDir.toStdWString().c_str(), NULL, NULL, NULL, &valueSz) == ERROR_SUCCESS) { | ||||||
|                                              &valueSz) == ERROR_SUCCESS) |  | ||||||
|                         { |  | ||||||
|                             WCHAR* value = new WCHAR[valueSz]; |                             WCHAR* value = new WCHAR[valueSz]; | ||||||
|                             RegQueryValueExW(newKey, keyJavaDir.toStdWString().c_str(), NULL, NULL, (BYTE *)value, |                             RegQueryValueExW(newKey, keyJavaDir.toStdWString().c_str(), NULL, NULL, (BYTE*)value, &valueSz); | ||||||
|                                              &valueSz); |  | ||||||
|  |  | ||||||
|                             QString newValue = QString::fromWCharArray(value); |                             QString newValue = QString::fromWCharArray(value); | ||||||
|                             delete[] value; |                             delete[] value; | ||||||
| @@ -253,8 +222,7 @@ QList<JavaInstallPtr> JavaUtils::FindJavaFromRegistryKey(DWORD keyType, QString | |||||||
|  |  | ||||||
|                             javaVersion->id = newSubkeyName; |                             javaVersion->id = newSubkeyName; | ||||||
|                             javaVersion->arch = archType; |                             javaVersion->arch = archType; | ||||||
|                             javaVersion->path = |                             javaVersion->path = QDir(FS::PathCombine(newValue, "bin")).absoluteFilePath("javaw.exe"); | ||||||
|                                 QDir(FS::PathCombine(newValue, "bin")).absoluteFilePath("javaw.exe"); |  | ||||||
|                             javas.append(javaVersion); |                             javas.append(javaVersion); | ||||||
|                         } |                         } | ||||||
|  |  | ||||||
| @@ -275,66 +243,56 @@ QList<QString> JavaUtils::FindJavaPaths() | |||||||
|     QList<JavaInstallPtr> java_candidates; |     QList<JavaInstallPtr> java_candidates; | ||||||
|  |  | ||||||
|     // Oracle |     // Oracle | ||||||
|     QList<JavaInstallPtr> JRE64s = this->FindJavaFromRegistryKey( |     QList<JavaInstallPtr> JRE64s = | ||||||
|         KEY_WOW64_64KEY, "SOFTWARE\\JavaSoft\\Java Runtime Environment", "JavaHome"); |         this->FindJavaFromRegistryKey(KEY_WOW64_64KEY, "SOFTWARE\\JavaSoft\\Java Runtime Environment", "JavaHome"); | ||||||
|     QList<JavaInstallPtr> JDK64s = this->FindJavaFromRegistryKey( |     QList<JavaInstallPtr> JDK64s = this->FindJavaFromRegistryKey(KEY_WOW64_64KEY, "SOFTWARE\\JavaSoft\\Java Development Kit", "JavaHome"); | ||||||
|         KEY_WOW64_64KEY, "SOFTWARE\\JavaSoft\\Java Development Kit", "JavaHome"); |     QList<JavaInstallPtr> JRE32s = | ||||||
|     QList<JavaInstallPtr> JRE32s = this->FindJavaFromRegistryKey( |         this->FindJavaFromRegistryKey(KEY_WOW64_32KEY, "SOFTWARE\\JavaSoft\\Java Runtime Environment", "JavaHome"); | ||||||
|         KEY_WOW64_32KEY, "SOFTWARE\\JavaSoft\\Java Runtime Environment", "JavaHome"); |     QList<JavaInstallPtr> JDK32s = this->FindJavaFromRegistryKey(KEY_WOW64_32KEY, "SOFTWARE\\JavaSoft\\Java Development Kit", "JavaHome"); | ||||||
|     QList<JavaInstallPtr> JDK32s = this->FindJavaFromRegistryKey( |  | ||||||
|         KEY_WOW64_32KEY, "SOFTWARE\\JavaSoft\\Java Development Kit", "JavaHome"); |  | ||||||
|  |  | ||||||
|     // Oracle for Java 9 and newer |     // Oracle for Java 9 and newer | ||||||
|     QList<JavaInstallPtr> NEWJRE64s = this->FindJavaFromRegistryKey( |     QList<JavaInstallPtr> NEWJRE64s = this->FindJavaFromRegistryKey(KEY_WOW64_64KEY, "SOFTWARE\\JavaSoft\\JRE", "JavaHome"); | ||||||
|         KEY_WOW64_64KEY, "SOFTWARE\\JavaSoft\\JRE", "JavaHome"); |     QList<JavaInstallPtr> NEWJDK64s = this->FindJavaFromRegistryKey(KEY_WOW64_64KEY, "SOFTWARE\\JavaSoft\\JDK", "JavaHome"); | ||||||
|     QList<JavaInstallPtr> NEWJDK64s = this->FindJavaFromRegistryKey( |     QList<JavaInstallPtr> NEWJRE32s = this->FindJavaFromRegistryKey(KEY_WOW64_32KEY, "SOFTWARE\\JavaSoft\\JRE", "JavaHome"); | ||||||
|         KEY_WOW64_64KEY, "SOFTWARE\\JavaSoft\\JDK", "JavaHome"); |     QList<JavaInstallPtr> NEWJDK32s = this->FindJavaFromRegistryKey(KEY_WOW64_32KEY, "SOFTWARE\\JavaSoft\\JDK", "JavaHome"); | ||||||
|     QList<JavaInstallPtr> NEWJRE32s = this->FindJavaFromRegistryKey( |  | ||||||
|         KEY_WOW64_32KEY, "SOFTWARE\\JavaSoft\\JRE", "JavaHome"); |  | ||||||
|     QList<JavaInstallPtr> NEWJDK32s = this->FindJavaFromRegistryKey( |  | ||||||
|         KEY_WOW64_32KEY, "SOFTWARE\\JavaSoft\\JDK", "JavaHome"); |  | ||||||
|  |  | ||||||
|     // AdoptOpenJDK |     // AdoptOpenJDK | ||||||
|     QList<JavaInstallPtr> ADOPTOPENJRE32s = this->FindJavaFromRegistryKey( |     QList<JavaInstallPtr> ADOPTOPENJRE32s = | ||||||
|         KEY_WOW64_32KEY, "SOFTWARE\\AdoptOpenJDK\\JRE", "Path", "\\hotspot\\MSI"); |         this->FindJavaFromRegistryKey(KEY_WOW64_32KEY, "SOFTWARE\\AdoptOpenJDK\\JRE", "Path", "\\hotspot\\MSI"); | ||||||
|     QList<JavaInstallPtr> ADOPTOPENJRE64s = this->FindJavaFromRegistryKey( |     QList<JavaInstallPtr> ADOPTOPENJRE64s = | ||||||
|         KEY_WOW64_64KEY, "SOFTWARE\\AdoptOpenJDK\\JRE", "Path", "\\hotspot\\MSI"); |         this->FindJavaFromRegistryKey(KEY_WOW64_64KEY, "SOFTWARE\\AdoptOpenJDK\\JRE", "Path", "\\hotspot\\MSI"); | ||||||
|     QList<JavaInstallPtr> ADOPTOPENJDK32s = this->FindJavaFromRegistryKey( |     QList<JavaInstallPtr> ADOPTOPENJDK32s = | ||||||
|         KEY_WOW64_32KEY, "SOFTWARE\\AdoptOpenJDK\\JDK", "Path", "\\hotspot\\MSI"); |         this->FindJavaFromRegistryKey(KEY_WOW64_32KEY, "SOFTWARE\\AdoptOpenJDK\\JDK", "Path", "\\hotspot\\MSI"); | ||||||
|     QList<JavaInstallPtr> ADOPTOPENJDK64s = this->FindJavaFromRegistryKey( |     QList<JavaInstallPtr> ADOPTOPENJDK64s = | ||||||
|         KEY_WOW64_64KEY, "SOFTWARE\\AdoptOpenJDK\\JDK", "Path", "\\hotspot\\MSI"); |         this->FindJavaFromRegistryKey(KEY_WOW64_64KEY, "SOFTWARE\\AdoptOpenJDK\\JDK", "Path", "\\hotspot\\MSI"); | ||||||
|  |  | ||||||
|     // Eclipse Foundation |     // Eclipse Foundation | ||||||
|     QList<JavaInstallPtr> FOUNDATIONJDK32s = this->FindJavaFromRegistryKey( |     QList<JavaInstallPtr> FOUNDATIONJDK32s = | ||||||
|         KEY_WOW64_32KEY, "SOFTWARE\\Eclipse Foundation\\JDK", "Path", "\\hotspot\\MSI"); |         this->FindJavaFromRegistryKey(KEY_WOW64_32KEY, "SOFTWARE\\Eclipse Foundation\\JDK", "Path", "\\hotspot\\MSI"); | ||||||
|     QList<JavaInstallPtr> FOUNDATIONJDK64s = this->FindJavaFromRegistryKey( |     QList<JavaInstallPtr> FOUNDATIONJDK64s = | ||||||
|         KEY_WOW64_64KEY, "SOFTWARE\\Eclipse Foundation\\JDK", "Path", "\\hotspot\\MSI"); |         this->FindJavaFromRegistryKey(KEY_WOW64_64KEY, "SOFTWARE\\Eclipse Foundation\\JDK", "Path", "\\hotspot\\MSI"); | ||||||
|  |  | ||||||
|     // Eclipse Adoptium |     // Eclipse Adoptium | ||||||
|     QList<JavaInstallPtr> ADOPTIUMJRE32s = this->FindJavaFromRegistryKey( |     QList<JavaInstallPtr> ADOPTIUMJRE32s = | ||||||
|         KEY_WOW64_32KEY, "SOFTWARE\\Eclipse Adoptium\\JRE", "Path", "\\hotspot\\MSI"); |         this->FindJavaFromRegistryKey(KEY_WOW64_32KEY, "SOFTWARE\\Eclipse Adoptium\\JRE", "Path", "\\hotspot\\MSI"); | ||||||
|     QList<JavaInstallPtr> ADOPTIUMJRE64s = this->FindJavaFromRegistryKey( |     QList<JavaInstallPtr> ADOPTIUMJRE64s = | ||||||
|         KEY_WOW64_64KEY, "SOFTWARE\\Eclipse Adoptium\\JRE", "Path", "\\hotspot\\MSI"); |         this->FindJavaFromRegistryKey(KEY_WOW64_64KEY, "SOFTWARE\\Eclipse Adoptium\\JRE", "Path", "\\hotspot\\MSI"); | ||||||
|     QList<JavaInstallPtr> ADOPTIUMJDK32s = this->FindJavaFromRegistryKey( |     QList<JavaInstallPtr> ADOPTIUMJDK32s = | ||||||
|         KEY_WOW64_32KEY, "SOFTWARE\\Eclipse Adoptium\\JDK", "Path", "\\hotspot\\MSI"); |         this->FindJavaFromRegistryKey(KEY_WOW64_32KEY, "SOFTWARE\\Eclipse Adoptium\\JDK", "Path", "\\hotspot\\MSI"); | ||||||
|     QList<JavaInstallPtr> ADOPTIUMJDK64s = this->FindJavaFromRegistryKey( |     QList<JavaInstallPtr> ADOPTIUMJDK64s = | ||||||
|         KEY_WOW64_64KEY, "SOFTWARE\\Eclipse Adoptium\\JDK", "Path", "\\hotspot\\MSI"); |         this->FindJavaFromRegistryKey(KEY_WOW64_64KEY, "SOFTWARE\\Eclipse Adoptium\\JDK", "Path", "\\hotspot\\MSI"); | ||||||
|  |  | ||||||
|     // Microsoft |     // Microsoft | ||||||
|     QList<JavaInstallPtr> MICROSOFTJDK64s = this->FindJavaFromRegistryKey( |     QList<JavaInstallPtr> MICROSOFTJDK64s = | ||||||
|         KEY_WOW64_64KEY, "SOFTWARE\\Microsoft\\JDK", "Path", "\\hotspot\\MSI"); |         this->FindJavaFromRegistryKey(KEY_WOW64_64KEY, "SOFTWARE\\Microsoft\\JDK", "Path", "\\hotspot\\MSI"); | ||||||
|  |  | ||||||
|     // Azul Zulu |     // Azul Zulu | ||||||
|     QList<JavaInstallPtr> ZULU64s = this->FindJavaFromRegistryKey( |     QList<JavaInstallPtr> ZULU64s = this->FindJavaFromRegistryKey(KEY_WOW64_64KEY, "SOFTWARE\\Azul Systems\\Zulu", "InstallationPath"); | ||||||
|         KEY_WOW64_64KEY, "SOFTWARE\\Azul Systems\\Zulu", "InstallationPath"); |     QList<JavaInstallPtr> ZULU32s = this->FindJavaFromRegistryKey(KEY_WOW64_32KEY, "SOFTWARE\\Azul Systems\\Zulu", "InstallationPath"); | ||||||
|     QList<JavaInstallPtr> ZULU32s = this->FindJavaFromRegistryKey( |  | ||||||
|         KEY_WOW64_32KEY, "SOFTWARE\\Azul Systems\\Zulu", "InstallationPath"); |  | ||||||
|  |  | ||||||
|     // BellSoft Liberica |     // BellSoft Liberica | ||||||
|     QList<JavaInstallPtr> LIBERICA64s = this->FindJavaFromRegistryKey( |     QList<JavaInstallPtr> LIBERICA64s = this->FindJavaFromRegistryKey(KEY_WOW64_64KEY, "SOFTWARE\\BellSoft\\Liberica", "InstallationPath"); | ||||||
|         KEY_WOW64_64KEY, "SOFTWARE\\BellSoft\\Liberica", "InstallationPath"); |     QList<JavaInstallPtr> LIBERICA32s = this->FindJavaFromRegistryKey(KEY_WOW64_32KEY, "SOFTWARE\\BellSoft\\Liberica", "InstallationPath"); | ||||||
|     QList<JavaInstallPtr> LIBERICA32s = this->FindJavaFromRegistryKey( |  | ||||||
|         KEY_WOW64_32KEY, "SOFTWARE\\BellSoft\\Liberica", "InstallationPath"); |  | ||||||
|  |  | ||||||
|     // List x64 before x86 |     // List x64 before x86 | ||||||
|     java_candidates.append(JRE64s); |     java_candidates.append(JRE64s); | ||||||
| @@ -371,10 +329,8 @@ QList<QString> JavaUtils::FindJavaPaths() | |||||||
|     java_candidates.append(MakeJavaPtr(this->GetDefaultJava()->path)); |     java_candidates.append(MakeJavaPtr(this->GetDefaultJava()->path)); | ||||||
|  |  | ||||||
|     QList<QString> candidates; |     QList<QString> candidates; | ||||||
|     for(JavaInstallPtr java_candidate : java_candidates) |     for (JavaInstallPtr java_candidate : java_candidates) { | ||||||
|     { |         if (!candidates.contains(java_candidate->path)) { | ||||||
|         if(!candidates.contains(java_candidate->path)) |  | ||||||
|         { |  | ||||||
|             candidates.append(java_candidate->path); |             candidates.append(java_candidate->path); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @@ -414,14 +370,12 @@ QList<QString> JavaUtils::FindJavaPaths() | |||||||
| { | { | ||||||
|     QList<QString> javas; |     QList<QString> javas; | ||||||
|     javas.append(this->GetDefaultJava()->path); |     javas.append(this->GetDefaultJava()->path); | ||||||
|     auto scanJavaDir = [&](const QString & dirPath) |     auto scanJavaDir = [&](const QString& dirPath) { | ||||||
|     { |  | ||||||
|         QDir dir(dirPath); |         QDir dir(dirPath); | ||||||
|         if (!dir.exists()) |         if (!dir.exists()) | ||||||
|             return; |             return; | ||||||
|         auto entries = dir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot); |         auto entries = dir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot); | ||||||
|         for(auto & entry: entries) |         for (auto& entry : entries) { | ||||||
|         { |  | ||||||
|             QString prefix; |             QString prefix; | ||||||
|             prefix = entry.canonicalFilePath(); |             prefix = entry.canonicalFilePath(); | ||||||
|             javas.append(FS::PathCombine(prefix, "jre/bin/java")); |             javas.append(FS::PathCombine(prefix, "jre/bin/java")); | ||||||
| @@ -430,8 +384,7 @@ QList<QString> JavaUtils::FindJavaPaths() | |||||||
|     }; |     }; | ||||||
|     // java installed in a snap is installed in the standard directory, but underneath $SNAP |     // java installed in a snap is installed in the standard directory, but underneath $SNAP | ||||||
|     auto snap = qEnvironmentVariable("SNAP"); |     auto snap = qEnvironmentVariable("SNAP"); | ||||||
|     auto scanJavaDirs = [&](const QString & dirPath) |     auto scanJavaDirs = [&](const QString& dirPath) { | ||||||
|     { |  | ||||||
|         scanJavaDir(dirPath); |         scanJavaDir(dirPath); | ||||||
|         if (!snap.isNull()) { |         if (!snap.isNull()) { | ||||||
|             scanJavaDir(snap + dirPath); |             scanJavaDir(snap + dirPath); | ||||||
|   | |||||||
| @@ -27,8 +27,7 @@ | |||||||
| QString stripVariableEntries(QString name, QString target, QString remove); | QString stripVariableEntries(QString name, QString target, QString remove); | ||||||
| QProcessEnvironment CleanEnviroment(); | QProcessEnvironment CleanEnviroment(); | ||||||
|  |  | ||||||
| class JavaUtils : public QObject | class JavaUtils : public QObject { | ||||||
| { |  | ||||||
|     Q_OBJECT |     Q_OBJECT | ||||||
|    public: |    public: | ||||||
|     JavaUtils(); |     JavaUtils(); | ||||||
|   | |||||||
| @@ -9,23 +9,18 @@ JavaVersion & JavaVersion::operator=(const QString & javaVersionString) | |||||||
| { | { | ||||||
|     m_string = javaVersionString; |     m_string = javaVersionString; | ||||||
|  |  | ||||||
|     auto getCapturedInteger = [](const QRegularExpressionMatch & match, const QString &what) -> int |     auto getCapturedInteger = [](const QRegularExpressionMatch& match, const QString& what) -> int { | ||||||
|     { |  | ||||||
|         auto str = match.captured(what); |         auto str = match.captured(what); | ||||||
|         if(str.isEmpty()) |         if (str.isEmpty()) { | ||||||
|         { |  | ||||||
|             return 0; |             return 0; | ||||||
|         } |         } | ||||||
|         return str.toInt(); |         return str.toInt(); | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     QRegularExpression pattern; |     QRegularExpression pattern; | ||||||
|     if(javaVersionString.startsWith("1.")) |     if (javaVersionString.startsWith("1.")) { | ||||||
|     { |  | ||||||
|         pattern = QRegularExpression("1[.](?<major>[0-9]+)([.](?<minor>[0-9]+))?(_(?<security>[0-9]+)?)?(-(?<prerelease>[a-zA-Z0-9]+))?"); |         pattern = QRegularExpression("1[.](?<major>[0-9]+)([.](?<minor>[0-9]+))?(_(?<security>[0-9]+)?)?(-(?<prerelease>[a-zA-Z0-9]+))?"); | ||||||
|     } |     } else { | ||||||
|     else |  | ||||||
|     { |  | ||||||
|         pattern = QRegularExpression("(?<major>[0-9]+)([.](?<minor>[0-9]+))?([.](?<security>[0-9]+))?(-(?<prerelease>[a-zA-Z0-9]+))?"); |         pattern = QRegularExpression("(?<major>[0-9]+)([.](?<minor>[0-9]+))?([.](?<security>[0-9]+))?(-(?<prerelease>[a-zA-Z0-9]+))?"); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -43,15 +38,14 @@ JavaVersion::JavaVersion(const QString &rhs) | |||||||
|     operator=(rhs); |     operator=(rhs); | ||||||
| } | } | ||||||
|  |  | ||||||
| QString JavaVersion::toString() | QString JavaVersion::toString() const | ||||||
| { | { | ||||||
|     return m_string; |     return m_string; | ||||||
| } | } | ||||||
|  |  | ||||||
| bool JavaVersion::requiresPermGen() | bool JavaVersion::requiresPermGen() | ||||||
| { | { | ||||||
|     if(m_parseable) |     if (m_parseable) { | ||||||
|     { |  | ||||||
|         return m_major < 8; |         return m_major < 8; | ||||||
|     } |     } | ||||||
|     return true; |     return true; | ||||||
| @@ -59,8 +53,7 @@ bool JavaVersion::requiresPermGen() | |||||||
|  |  | ||||||
| bool JavaVersion::operator<(const JavaVersion& rhs) | bool JavaVersion::operator<(const JavaVersion& rhs) | ||||||
| { | { | ||||||
|     if(m_parseable && rhs.m_parseable) |     if (m_parseable && rhs.m_parseable) { | ||||||
|     { |  | ||||||
|         auto major = m_major; |         auto major = m_major; | ||||||
|         auto rmajor = rhs.m_major; |         auto rmajor = rhs.m_major; | ||||||
|  |  | ||||||
| @@ -86,31 +79,25 @@ bool JavaVersion::operator<(const JavaVersion &rhs) | |||||||
|         // everything else being equal, consider prerelease status |         // everything else being equal, consider prerelease status | ||||||
|         bool thisPre = !m_prerelease.isEmpty(); |         bool thisPre = !m_prerelease.isEmpty(); | ||||||
|         bool rhsPre = !rhs.m_prerelease.isEmpty(); |         bool rhsPre = !rhs.m_prerelease.isEmpty(); | ||||||
|         if(thisPre && !rhsPre) |         if (thisPre && !rhsPre) { | ||||||
|         { |  | ||||||
|             // this is a prerelease and the other one isn't -> lesser |             // this is a prerelease and the other one isn't -> lesser | ||||||
|             return true; |             return true; | ||||||
|         } |         } else if (!thisPre && rhsPre) { | ||||||
|         else if(!thisPre && rhsPre) |  | ||||||
|         { |  | ||||||
|             // this isn't a prerelease and the other one is -> greater |             // this isn't a prerelease and the other one is -> greater | ||||||
|             return false; |             return false; | ||||||
|         } |         } else if (thisPre && rhsPre) { | ||||||
|         else if(thisPre && rhsPre) |  | ||||||
|         { |  | ||||||
|             // both are prereleases - use natural compare... |             // both are prereleases - use natural compare... | ||||||
|             return StringUtils::naturalCompare(m_prerelease, rhs.m_prerelease, Qt::CaseSensitive) < 0; |             return StringUtils::naturalCompare(m_prerelease, rhs.m_prerelease, Qt::CaseSensitive) < 0; | ||||||
|         } |         } | ||||||
|         // neither is prerelease, so they are the same -> this cannot be less than rhs |         // neither is prerelease, so they are the same -> this cannot be less than rhs | ||||||
|         return false; |         return false; | ||||||
|     } |     } else | ||||||
|     else return StringUtils::naturalCompare(m_string, rhs.m_string, Qt::CaseSensitive) < 0; |         return StringUtils::naturalCompare(m_string, rhs.m_string, Qt::CaseSensitive) < 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| bool JavaVersion::operator==(const JavaVersion& rhs) | bool JavaVersion::operator==(const JavaVersion& rhs) | ||||||
| { | { | ||||||
|     if(m_parseable && rhs.m_parseable) |     if (m_parseable && rhs.m_parseable) { | ||||||
|     { |  | ||||||
|         return m_major == rhs.m_major && m_minor == rhs.m_minor && m_security == rhs.m_security && m_prerelease == rhs.m_prerelease; |         return m_major == rhs.m_major && m_minor == rhs.m_minor && m_security == rhs.m_security && m_prerelease == rhs.m_prerelease; | ||||||
|     } |     } | ||||||
|     return m_string == rhs.m_string; |     return m_string == rhs.m_string; | ||||||
|   | |||||||
| @@ -10,9 +10,9 @@ | |||||||
| #undef minor | #undef minor | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| class JavaVersion | class JavaVersion { | ||||||
| { |  | ||||||
|     friend class JavaVersionTest; |     friend class JavaVersionTest; | ||||||
|  |  | ||||||
|    public: |    public: | ||||||
|     JavaVersion(){}; |     JavaVersion(){}; | ||||||
|     JavaVersion(const QString& rhs); |     JavaVersion(const QString& rhs); | ||||||
| @@ -25,20 +25,12 @@ public: | |||||||
|  |  | ||||||
|     bool requiresPermGen(); |     bool requiresPermGen(); | ||||||
|  |  | ||||||
|     QString toString(); |     QString toString() const; | ||||||
|  |  | ||||||
|  |     int major() { return m_major; } | ||||||
|  |     int minor() { return m_minor; } | ||||||
|  |     int security() { return m_security; } | ||||||
|  |  | ||||||
|     int major() |  | ||||||
|     { |  | ||||||
|         return m_major; |  | ||||||
|     } |  | ||||||
|     int minor() |  | ||||||
|     { |  | ||||||
|         return m_minor; |  | ||||||
|     } |  | ||||||
|     int security() |  | ||||||
|     { |  | ||||||
|         return m_security; |  | ||||||
|     } |  | ||||||
|    private: |    private: | ||||||
|     QString m_string; |     QString m_string; | ||||||
|     int m_major = 0; |     int m_major = 0; | ||||||
|   | |||||||
| @@ -15,20 +15,16 @@ | |||||||
|  |  | ||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
| #include "tasks/Task.h" |  | ||||||
| #include "MessageLevel.h" | #include "MessageLevel.h" | ||||||
|  | #include "tasks/Task.h" | ||||||
|  |  | ||||||
| #include <QStringList> | #include <QStringList> | ||||||
|  |  | ||||||
| class LaunchTask; | class LaunchTask; | ||||||
| class LaunchStep: public Task | class LaunchStep : public Task { | ||||||
| { |  | ||||||
|     Q_OBJECT |     Q_OBJECT | ||||||
|    public: /* methods */ |    public: /* methods */ | ||||||
|     explicit LaunchStep(LaunchTask *parent):Task(nullptr), m_parent(parent) |     explicit LaunchStep(LaunchTask* parent) : Task(nullptr), m_parent(parent) { bind(parent); }; | ||||||
|     { |  | ||||||
|         bind(parent); |  | ||||||
|     }; |  | ||||||
|     virtual ~LaunchStep(){}; |     virtual ~LaunchStep(){}; | ||||||
|  |  | ||||||
|    private: /* methods */ |    private: /* methods */ | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| // SPDX-License-Identifier: GPL-3.0-only | // SPDX-License-Identifier: GPL-3.0-only | ||||||
| /* | /* | ||||||
|  *  PolyMC - Minecraft Launcher |  *  Prism Launcher - Minecraft Launcher | ||||||
|  *  Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net> |  *  Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net> | ||||||
|  * |  * | ||||||
|  *  This program is free software: you can redistribute it and/or modify |  *  This program is free software: you can redistribute it and/or modify | ||||||
| @@ -36,16 +36,16 @@ | |||||||
|  */ |  */ | ||||||
|  |  | ||||||
| #include "launch/LaunchTask.h" | #include "launch/LaunchTask.h" | ||||||
| #include "MessageLevel.h" | #include <assert.h> | ||||||
| #include "java/JavaChecker.h" | #include <QCoreApplication> | ||||||
| #include "tasks/Task.h" |  | ||||||
| #include <QDebug> | #include <QDebug> | ||||||
| #include <QDir> | #include <QDir> | ||||||
| #include <QEventLoop> | #include <QEventLoop> | ||||||
| #include <QRegularExpression> | #include <QRegularExpression> | ||||||
| #include <QCoreApplication> |  | ||||||
| #include <QStandardPaths> | #include <QStandardPaths> | ||||||
| #include <assert.h> | #include "MessageLevel.h" | ||||||
|  | #include "java/JavaChecker.h" | ||||||
|  | #include "tasks/Task.h" | ||||||
|  |  | ||||||
| void LaunchTask::init() | void LaunchTask::init() | ||||||
| { | { | ||||||
| @@ -59,9 +59,7 @@ shared_qobject_ptr<LaunchTask> LaunchTask::create(InstancePtr inst) | |||||||
|     return proc; |     return proc; | ||||||
| } | } | ||||||
|  |  | ||||||
| LaunchTask::LaunchTask(InstancePtr instance): m_instance(instance) | LaunchTask::LaunchTask(InstancePtr instance) : m_instance(instance) {} | ||||||
| { |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void LaunchTask::appendStep(shared_qobject_ptr<LaunchStep> step) | void LaunchTask::appendStep(shared_qobject_ptr<LaunchStep> step) | ||||||
| { | { | ||||||
| @@ -76,8 +74,7 @@ void LaunchTask::prependStep(shared_qobject_ptr<LaunchStep> step) | |||||||
| void LaunchTask::executeTask() | void LaunchTask::executeTask() | ||||||
| { | { | ||||||
|     m_instance->setCrashed(false); |     m_instance->setCrashed(false); | ||||||
|     if(!m_steps.size()) |     if (!m_steps.size()) { | ||||||
|     { |  | ||||||
|         state = LaunchTask::Finished; |         state = LaunchTask::Finished; | ||||||
|         emitSucceeded(); |         emitSucceeded(); | ||||||
|     } |     } | ||||||
| @@ -94,46 +91,35 @@ void LaunchTask::onReadyForLaunch() | |||||||
| void LaunchTask::onStepFinished() | void LaunchTask::onStepFinished() | ||||||
| { | { | ||||||
|     // initial -> just start the first step |     // initial -> just start the first step | ||||||
|     if(currentStep == -1) |     if (currentStep == -1) { | ||||||
|     { |  | ||||||
|         currentStep++; |         currentStep++; | ||||||
|         m_steps[currentStep]->start(); |         m_steps[currentStep]->start(); | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     auto step = m_steps[currentStep]; |     auto step = m_steps[currentStep]; | ||||||
|     if(step->wasSuccessful()) |     if (step->wasSuccessful()) { | ||||||
|     { |  | ||||||
|         // end? |         // end? | ||||||
|         if(currentStep == m_steps.size() - 1) |         if (currentStep == m_steps.size() - 1) { | ||||||
|         { |  | ||||||
|             finalizeSteps(true, QString()); |             finalizeSteps(true, QString()); | ||||||
|         } |         } else { | ||||||
|         else |  | ||||||
|         { |  | ||||||
|             currentStep++; |             currentStep++; | ||||||
|             step = m_steps[currentStep]; |             step = m_steps[currentStep]; | ||||||
|             step->start(); |             step->start(); | ||||||
|         } |         } | ||||||
|     } |     } else { | ||||||
|     else |  | ||||||
|     { |  | ||||||
|         finalizeSteps(false, step->failReason()); |         finalizeSteps(false, step->failReason()); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| void LaunchTask::finalizeSteps(bool successful, const QString& error) | void LaunchTask::finalizeSteps(bool successful, const QString& error) | ||||||
| { | { | ||||||
|     for(auto step = currentStep; step >= 0; step--) |     for (auto step = currentStep; step >= 0; step--) { | ||||||
|     { |  | ||||||
|         m_steps[step]->finalize(); |         m_steps[step]->finalize(); | ||||||
|     } |     } | ||||||
|     if(successful) |     if (successful) { | ||||||
|     { |  | ||||||
|         emitSucceeded(); |         emitSucceeded(); | ||||||
|     } |     } else { | ||||||
|     else |  | ||||||
|     { |  | ||||||
|         emitFailed(error); |         emitFailed(error); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -152,8 +138,7 @@ void LaunchTask::setCensorFilter(QMap<QString, QString> filter) | |||||||
| QString LaunchTask::censorPrivateInfo(QString in) | QString LaunchTask::censorPrivateInfo(QString in) | ||||||
| { | { | ||||||
|     auto iter = m_censorFilter.begin(); |     auto iter = m_censorFilter.begin(); | ||||||
|     while (iter != m_censorFilter.end()) |     while (iter != m_censorFilter.end()) { | ||||||
|     { |  | ||||||
|         in.replace(iter.key(), iter.value()); |         in.replace(iter.key(), iter.value()); | ||||||
|         iter++; |         iter++; | ||||||
|     } |     } | ||||||
| @@ -162,8 +147,7 @@ QString LaunchTask::censorPrivateInfo(QString in) | |||||||
|  |  | ||||||
| void LaunchTask::proceed() | void LaunchTask::proceed() | ||||||
| { | { | ||||||
|     if(state != LaunchTask::Waiting) |     if (state != LaunchTask::Waiting) { | ||||||
|     { |  | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|     m_steps[currentStep]->proceed(); |     m_steps[currentStep]->proceed(); | ||||||
| @@ -171,8 +155,7 @@ void LaunchTask::proceed() | |||||||
|  |  | ||||||
| bool LaunchTask::canAbort() const | bool LaunchTask::canAbort() const | ||||||
| { | { | ||||||
|     switch(state) |     switch (state) { | ||||||
|     { |  | ||||||
|         case LaunchTask::Aborted: |         case LaunchTask::Aborted: | ||||||
|         case LaunchTask::Failed: |         case LaunchTask::Failed: | ||||||
|         case LaunchTask::Finished: |         case LaunchTask::Finished: | ||||||
| @@ -180,8 +163,7 @@ bool LaunchTask::canAbort() const | |||||||
|         case LaunchTask::NotStarted: |         case LaunchTask::NotStarted: | ||||||
|             return true; |             return true; | ||||||
|         case LaunchTask::Running: |         case LaunchTask::Running: | ||||||
|         case LaunchTask::Waiting: |         case LaunchTask::Waiting: { | ||||||
|         { |  | ||||||
|             auto step = m_steps[currentStep]; |             auto step = m_steps[currentStep]; | ||||||
|             return step->canAbort(); |             return step->canAbort(); | ||||||
|         } |         } | ||||||
| @@ -191,28 +173,23 @@ bool LaunchTask::canAbort() const | |||||||
|  |  | ||||||
| bool LaunchTask::abort() | bool LaunchTask::abort() | ||||||
| { | { | ||||||
|     switch(state) |     switch (state) { | ||||||
|     { |  | ||||||
|         case LaunchTask::Aborted: |         case LaunchTask::Aborted: | ||||||
|         case LaunchTask::Failed: |         case LaunchTask::Failed: | ||||||
|         case LaunchTask::Finished: |         case LaunchTask::Finished: | ||||||
|             return true; |             return true; | ||||||
|         case LaunchTask::NotStarted: |         case LaunchTask::NotStarted: { | ||||||
|         { |  | ||||||
|             state = LaunchTask::Aborted; |             state = LaunchTask::Aborted; | ||||||
|             emitFailed("Aborted"); |             emitFailed("Aborted"); | ||||||
|             return true; |             return true; | ||||||
|         } |         } | ||||||
|         case LaunchTask::Running: |         case LaunchTask::Running: | ||||||
|         case LaunchTask::Waiting: |         case LaunchTask::Waiting: { | ||||||
|         { |  | ||||||
|             auto step = m_steps[currentStep]; |             auto step = m_steps[currentStep]; | ||||||
|             if(!step->canAbort()) |             if (!step->canAbort()) { | ||||||
|             { |  | ||||||
|                 return false; |                 return false; | ||||||
|             } |             } | ||||||
|             if(step->abort()) |             if (step->abort()) { | ||||||
|             { |  | ||||||
|                 state = LaunchTask::Aborted; |                 state = LaunchTask::Aborted; | ||||||
|                 return true; |                 return true; | ||||||
|             } |             } | ||||||
| @@ -225,23 +202,22 @@ bool LaunchTask::abort() | |||||||
|  |  | ||||||
| shared_qobject_ptr<LogModel> LaunchTask::getLogModel() | shared_qobject_ptr<LogModel> LaunchTask::getLogModel() | ||||||
| { | { | ||||||
|     if(!m_logModel) |     if (!m_logModel) { | ||||||
|     { |  | ||||||
|         m_logModel.reset(new LogModel()); |         m_logModel.reset(new LogModel()); | ||||||
|         m_logModel->setMaxLines(m_instance->getConsoleMaxLines()); |         m_logModel->setMaxLines(m_instance->getConsoleMaxLines()); | ||||||
|         m_logModel->setStopOnOverflow(m_instance->shouldStopOnConsoleOverflow()); |         m_logModel->setStopOnOverflow(m_instance->shouldStopOnConsoleOverflow()); | ||||||
|         // FIXME: should this really be here? |         // FIXME: should this really be here? | ||||||
|         m_logModel->setOverflowMessage(tr("Stopped watching the game log because the log length surpassed %1 lines.\n" |         m_logModel->setOverflowMessage(tr("Stopped watching the game log because the log length surpassed %1 lines.\n" | ||||||
|                                           "You may have to fix your mods because the game is still logging to files and" |                                           "You may have to fix your mods because the game is still logging to files and" | ||||||
|             " likely wasting harddrive space at an alarming rate!").arg(m_logModel->getMaxLines())); |                                           " likely wasting harddrive space at an alarming rate!") | ||||||
|  |                                            .arg(m_logModel->getMaxLines())); | ||||||
|     } |     } | ||||||
|     return m_logModel; |     return m_logModel; | ||||||
| } | } | ||||||
|  |  | ||||||
| void LaunchTask::onLogLines(const QStringList& lines, MessageLevel::Enum defaultLevel) | void LaunchTask::onLogLines(const QStringList& lines, MessageLevel::Enum defaultLevel) | ||||||
| { | { | ||||||
|     for (auto & line: lines) |     for (auto& line : lines) { | ||||||
|     { |  | ||||||
|         onLogLine(line, defaultLevel); |         onLogLine(line, defaultLevel); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -250,14 +226,12 @@ void LaunchTask::onLogLine(QString line, MessageLevel::Enum level) | |||||||
| { | { | ||||||
|     // if the launcher part set a log level, use it |     // if the launcher part set a log level, use it | ||||||
|     auto innerLevel = MessageLevel::fromLine(line); |     auto innerLevel = MessageLevel::fromLine(line); | ||||||
|     if(innerLevel != MessageLevel::Unknown) |     if (innerLevel != MessageLevel::Unknown) { | ||||||
|     { |  | ||||||
|         level = innerLevel; |         level = innerLevel; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // If the level is still undetermined, guess level |     // If the level is still undetermined, guess level | ||||||
|     if (level == MessageLevel::StdErr || level == MessageLevel::StdOut || level == MessageLevel::Unknown) |     if (level == MessageLevel::StdErr || level == MessageLevel::StdOut || level == MessageLevel::Unknown) { | ||||||
|     { |  | ||||||
|         level = m_instance->guessLevel(line, level); |         level = m_instance->guessLevel(line, level); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -285,8 +259,7 @@ void LaunchTask::substituteVariables(QStringList &args) const | |||||||
| { | { | ||||||
|     auto env = m_instance->createEnvironment(); |     auto env = m_instance->createEnvironment(); | ||||||
|  |  | ||||||
|     for (auto key : env.keys()) |     for (auto key : env.keys()) { | ||||||
|     { |  | ||||||
|         args.replaceInStrings("$" + key, env.value(key)); |         args.replaceInStrings("$" + key, env.value(key)); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -295,8 +268,7 @@ void LaunchTask::substituteVariables(QString &cmd) const | |||||||
| { | { | ||||||
|     auto env = m_instance->createEnvironment(); |     auto env = m_instance->createEnvironment(); | ||||||
|  |  | ||||||
|     for (auto key : env.keys()) |     for (auto key : env.keys()) { | ||||||
|     { |  | ||||||
|         cmd.replace("$" + key, env.value(key)); |         cmd.replace("$" + key, env.value(key)); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| // SPDX-License-Identifier: GPL-3.0-only | // SPDX-License-Identifier: GPL-3.0-only | ||||||
| /* | /* | ||||||
|  *  PolyMC - Minecraft Launcher |  *  Prism Launcher - Minecraft Launcher | ||||||
|  *  Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net> |  *  Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net> | ||||||
|  * |  * | ||||||
|  *  This program is free software: you can redistribute it and/or modify |  *  This program is free software: you can redistribute it and/or modify | ||||||
| @@ -36,31 +36,22 @@ | |||||||
|  */ |  */ | ||||||
|  |  | ||||||
| #pragma once | #pragma once | ||||||
| #include <QProcess> |  | ||||||
| #include <QObjectPtr.h> | #include <QObjectPtr.h> | ||||||
| #include "LogModel.h" | #include <QProcess> | ||||||
| #include "BaseInstance.h" | #include "BaseInstance.h" | ||||||
| #include "MessageLevel.h" |  | ||||||
| #include "LoggedProcess.h" |  | ||||||
| #include "LaunchStep.h" | #include "LaunchStep.h" | ||||||
|  | #include "LogModel.h" | ||||||
|  | #include "LoggedProcess.h" | ||||||
|  | #include "MessageLevel.h" | ||||||
|  |  | ||||||
| class LaunchTask: public Task | class LaunchTask : public Task { | ||||||
| { |  | ||||||
|     Q_OBJECT |     Q_OBJECT | ||||||
|    protected: |    protected: | ||||||
|     explicit LaunchTask(InstancePtr instance); |     explicit LaunchTask(InstancePtr instance); | ||||||
|     void init(); |     void init(); | ||||||
|  |  | ||||||
|    public: |    public: | ||||||
|     enum State |     enum State { NotStarted, Running, Waiting, Failed, Aborted, Finished }; | ||||||
|     { |  | ||||||
|         NotStarted, |  | ||||||
|         Running, |  | ||||||
|         Waiting, |  | ||||||
|         Failed, |  | ||||||
|         Aborted, |  | ||||||
|         Finished |  | ||||||
|     }; |  | ||||||
|  |  | ||||||
|    public: /* methods */ |    public: /* methods */ | ||||||
|     static shared_qobject_ptr<LaunchTask> create(InstancePtr inst); |     static shared_qobject_ptr<LaunchTask> create(InstancePtr inst); | ||||||
| @@ -70,20 +61,11 @@ public: /* methods */ | |||||||
|     void prependStep(shared_qobject_ptr<LaunchStep> step); |     void prependStep(shared_qobject_ptr<LaunchStep> step); | ||||||
|     void setCensorFilter(QMap<QString, QString> filter); |     void setCensorFilter(QMap<QString, QString> filter); | ||||||
|  |  | ||||||
|     InstancePtr instance() |     InstancePtr instance() { return m_instance; } | ||||||
|     { |  | ||||||
|         return m_instance; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     void setPid(qint64 pid) |     void setPid(qint64 pid) { m_pid = pid; } | ||||||
|     { |  | ||||||
|         m_pid = pid; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     qint64 pid() |     qint64 pid() { return m_pid; } | ||||||
|     { |  | ||||||
|         return m_pid; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * @brief prepare the process for launch (for multi-stage launch) |      * @brief prepare the process for launch (for multi-stage launch) | ||||||
|   | |||||||
| @@ -20,12 +20,10 @@ QVariant LogModel::data(const QModelIndex &index, int role) const | |||||||
|  |  | ||||||
|     auto row = index.row(); |     auto row = index.row(); | ||||||
|     auto realRow = (row + m_firstLine) % m_maxLines; |     auto realRow = (row + m_firstLine) % m_maxLines; | ||||||
|     if (role == Qt::DisplayRole || role == Qt::EditRole) |     if (role == Qt::DisplayRole || role == Qt::EditRole) { | ||||||
|     { |  | ||||||
|         return m_content[realRow].line; |         return m_content[realRow].line; | ||||||
|     } |     } | ||||||
|     if(role == LevelRole) |     if (role == LevelRole) { | ||||||
|     { |  | ||||||
|         return m_content[realRow].level; |         return m_content[realRow].level; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -34,16 +32,13 @@ QVariant LogModel::data(const QModelIndex &index, int role) const | |||||||
|  |  | ||||||
| void LogModel::append(MessageLevel::Enum level, QString line) | void LogModel::append(MessageLevel::Enum level, QString line) | ||||||
| { | { | ||||||
|     if(m_suspended) |     if (m_suspended) { | ||||||
|     { |  | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|     int lineNum = (m_firstLine + m_numLines) % m_maxLines; |     int lineNum = (m_firstLine + m_numLines) % m_maxLines; | ||||||
|     // overflow |     // overflow | ||||||
|     if(m_numLines == m_maxLines) |     if (m_numLines == m_maxLines) { | ||||||
|     { |         if (m_stopOnOverflow) { | ||||||
|         if(m_stopOnOverflow) |  | ||||||
|         { |  | ||||||
|             // nothing more to do, the buffer is full |             // nothing more to do, the buffer is full | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
| @@ -51,9 +46,7 @@ void LogModel::append(MessageLevel::Enum level, QString line) | |||||||
|         m_firstLine = (m_firstLine + 1) % m_maxLines; |         m_firstLine = (m_firstLine + 1) % m_maxLines; | ||||||
|         m_numLines--; |         m_numLines--; | ||||||
|         endRemoveRows(); |         endRemoveRows(); | ||||||
|     } |     } else if (m_numLines == m_maxLines - 1 && m_stopOnOverflow) { | ||||||
|     else if (m_numLines == m_maxLines - 1 && m_stopOnOverflow) |  | ||||||
|     { |  | ||||||
|         level = MessageLevel::Fatal; |         level = MessageLevel::Fatal; | ||||||
|         line = m_overflowMessage; |         line = m_overflowMessage; | ||||||
|     } |     } | ||||||
| @@ -86,8 +79,7 @@ QString LogModel::toPlainText() | |||||||
| { | { | ||||||
|     QString out; |     QString out; | ||||||
|     out.reserve(m_numLines * 80); |     out.reserve(m_numLines * 80); | ||||||
|     for(int i = 0; i < m_numLines; i++) |     for (int i = 0; i < m_numLines; i++) { | ||||||
|     { |  | ||||||
|         QString& line = m_content[(m_firstLine + i) % m_maxLines].line; |         QString& line = m_content[(m_firstLine + i) % m_maxLines].line; | ||||||
|         out.append(line + '\n'); |         out.append(line + '\n'); | ||||||
|     } |     } | ||||||
| @@ -98,13 +90,11 @@ QString LogModel::toPlainText() | |||||||
| void LogModel::setMaxLines(int maxLines) | void LogModel::setMaxLines(int maxLines) | ||||||
| { | { | ||||||
|     // no-op |     // no-op | ||||||
|     if(maxLines == m_maxLines) |     if (maxLines == m_maxLines) { | ||||||
|     { |  | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|     // if it all still fits in the buffer, just resize it |     // if it all still fits in the buffer, just resize it | ||||||
|     if(m_firstLine + m_numLines < m_maxLines) |     if (m_firstLine + m_numLines < m_maxLines) { | ||||||
|     { |  | ||||||
|         m_maxLines = maxLines; |         m_maxLines = maxLines; | ||||||
|         m_content.resize(maxLines); |         m_content.resize(maxLines); | ||||||
|         return; |         return; | ||||||
| @@ -112,22 +102,17 @@ void LogModel::setMaxLines(int maxLines) | |||||||
|     // otherwise, we need to reorganize the data because it crosses the wrap boundary |     // otherwise, we need to reorganize the data because it crosses the wrap boundary | ||||||
|     QVector<entry> newContent; |     QVector<entry> newContent; | ||||||
|     newContent.resize(maxLines); |     newContent.resize(maxLines); | ||||||
|     if(m_numLines <= maxLines) |     if (m_numLines <= maxLines) { | ||||||
|     { |  | ||||||
|         // if it all fits in the new buffer, just copy it over |         // if it all fits in the new buffer, just copy it over | ||||||
|         for(int i = 0; i < m_numLines; i++) |         for (int i = 0; i < m_numLines; i++) { | ||||||
|         { |  | ||||||
|             newContent[i] = m_content[(m_firstLine + i) % m_maxLines]; |             newContent[i] = m_content[(m_firstLine + i) % m_maxLines]; | ||||||
|         } |         } | ||||||
|         m_content.swap(newContent); |         m_content.swap(newContent); | ||||||
|     } |     } else { | ||||||
|     else |  | ||||||
|     { |  | ||||||
|         // if it doesn't fit, part of the data needs to be thrown away (the oldest log messages) |         // if it doesn't fit, part of the data needs to be thrown away (the oldest log messages) | ||||||
|         int lead = m_numLines - maxLines; |         int lead = m_numLines - maxLines; | ||||||
|         beginRemoveRows(QModelIndex(), 0, lead - 1); |         beginRemoveRows(QModelIndex(), 0, lead - 1); | ||||||
|         for(int i = 0; i < maxLines; i++) |         for (int i = 0; i < maxLines; i++) { | ||||||
|         { |  | ||||||
|             newContent[i] = m_content[(m_firstLine + lead + i) % m_maxLines]; |             newContent[i] = m_content[(m_firstLine + lead + i) % m_maxLines]; | ||||||
|         } |         } | ||||||
|         m_numLines = m_maxLines; |         m_numLines = m_maxLines; | ||||||
| @@ -155,8 +140,7 @@ void LogModel::setOverflowMessage(const QString& overflowMessage) | |||||||
|  |  | ||||||
| void LogModel::setLineWrap(bool state) | void LogModel::setLineWrap(bool state) | ||||||
| { | { | ||||||
|     if(m_lineWrap != state) |     if (m_lineWrap != state) { | ||||||
|     { |  | ||||||
|         m_lineWrap = state; |         m_lineWrap = state; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -4,8 +4,7 @@ | |||||||
| #include <QString> | #include <QString> | ||||||
| #include "MessageLevel.h" | #include "MessageLevel.h" | ||||||
|  |  | ||||||
| class LogModel : public QAbstractListModel | class LogModel : public QAbstractListModel { | ||||||
| { |  | ||||||
|     Q_OBJECT |     Q_OBJECT | ||||||
|    public: |    public: | ||||||
|     explicit LogModel(QObject* parent = 0); |     explicit LogModel(QObject* parent = 0); | ||||||
| @@ -29,14 +28,10 @@ public: | |||||||
|     void setLineWrap(bool state); |     void setLineWrap(bool state); | ||||||
|     bool wrapLines() const; |     bool wrapLines() const; | ||||||
|  |  | ||||||
|     enum Roles |     enum Roles { LevelRole = Qt::UserRole }; | ||||||
|     { |  | ||||||
|         LevelRole = Qt::UserRole |  | ||||||
|     }; |  | ||||||
|  |  | ||||||
|     private /* types */: |     private /* types */: | ||||||
|     struct entry |     struct entry { | ||||||
|     { |  | ||||||
|         MessageLevel::Enum level; |         MessageLevel::Enum level; | ||||||
|         QString line; |         QString line; | ||||||
|     }; |     }; | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| // SPDX-License-Identifier: GPL-3.0-only | // SPDX-License-Identifier: GPL-3.0-only | ||||||
| /* | /* | ||||||
|  *  PolyMC - Minecraft Launcher |  *  Prism Launcher - Minecraft Launcher | ||||||
|  *  Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net> |  *  Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net> | ||||||
|  * |  * | ||||||
|  *  This program is free software: you can redistribute it and/or modify |  *  This program is free software: you can redistribute it and/or modify | ||||||
| @@ -34,12 +34,12 @@ | |||||||
|  */ |  */ | ||||||
|  |  | ||||||
| #include "CheckJava.h" | #include "CheckJava.h" | ||||||
| #include "java/JavaUtils.h" |  | ||||||
| #include <launch/LaunchTask.h> |  | ||||||
| #include <FileSystem.h> | #include <FileSystem.h> | ||||||
| #include <QStandardPaths> | #include <launch/LaunchTask.h> | ||||||
| #include <QFileInfo> |  | ||||||
| #include <sys.h> | #include <sys.h> | ||||||
|  | #include <QFileInfo> | ||||||
|  | #include <QStandardPaths> | ||||||
|  | #include "java/JavaUtils.h" | ||||||
|  |  | ||||||
| void CheckJava::executeTask() | void CheckJava::executeTask() | ||||||
| { | { | ||||||
| @@ -49,31 +49,25 @@ void CheckJava::executeTask() | |||||||
|     bool perInstance = settings->get("OverrideJava").toBool() || settings->get("OverrideJavaLocation").toBool(); |     bool perInstance = settings->get("OverrideJava").toBool() || settings->get("OverrideJavaLocation").toBool(); | ||||||
|  |  | ||||||
|     auto realJavaPath = QStandardPaths::findExecutable(m_javaPath); |     auto realJavaPath = QStandardPaths::findExecutable(m_javaPath); | ||||||
|     if (realJavaPath.isEmpty()) |     if (realJavaPath.isEmpty()) { | ||||||
|     { |         if (perInstance) { | ||||||
|         if (perInstance) |             emit logLine(QString("The java binary \"%1\" couldn't be found. Please fix the java path " | ||||||
|         { |                                  "override in the instance's settings or disable it.") | ||||||
|             emit logLine( |                              .arg(m_javaPath), | ||||||
|                 QString("The java binary \"%1\" couldn't be found. Please fix the java path " |  | ||||||
|                    "override in the instance's settings or disable it.").arg(m_javaPath), |  | ||||||
|                          MessageLevel::Warning); |                          MessageLevel::Warning); | ||||||
|         } |         } else { | ||||||
|         else |  | ||||||
|         { |  | ||||||
|             emit logLine(QString("The java binary \"%1\" couldn't be found. Please set up java in " |             emit logLine(QString("The java binary \"%1\" couldn't be found. Please set up java in " | ||||||
|                             "the settings.").arg(m_javaPath), |                                  "the settings.") | ||||||
|  |                              .arg(m_javaPath), | ||||||
|                          MessageLevel::Warning); |                          MessageLevel::Warning); | ||||||
|         } |         } | ||||||
|         emitFailed(QString("Java path is not valid.")); |         emitFailed(QString("Java path is not valid.")); | ||||||
|         return; |         return; | ||||||
|     } |     } else { | ||||||
|     else |  | ||||||
|     { |  | ||||||
|         emit logLine("Java path is:\n" + m_javaPath + "\n\n", MessageLevel::Launcher); |         emit logLine("Java path is:\n" + m_javaPath + "\n\n", MessageLevel::Launcher); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (JavaUtils::getJavaCheckPath().isEmpty()) |     if (JavaUtils::getJavaCheckPath().isEmpty()) { | ||||||
|     { |  | ||||||
|         const char* reason = QT_TR_NOOP("Java checker library could not be found. Please check your installation."); |         const char* reason = QT_TR_NOOP("Java checker library could not be found. Please check your installation."); | ||||||
|         emit logLine(tr(reason), MessageLevel::Fatal); |         emit logLine(tr(reason), MessageLevel::Fatal); | ||||||
|         emitFailed(tr(reason)); |         emitFailed(tr(reason)); | ||||||
| @@ -94,19 +88,15 @@ void CheckJava::executeTask() | |||||||
|     m_javaSignature = hash.result().toHex(); |     m_javaSignature = hash.result().toHex(); | ||||||
|  |  | ||||||
|     // 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 |     if (m_javaSignature != storedSignature || storedVersion.size() == 0 || storedArchitecture.size() == 0 || | ||||||
|         || storedArchitecture.size() == 0 || storedRealArchitecture.size() == 0 |         storedRealArchitecture.size() == 0 || storedVendor.size() == 0) { | ||||||
|         || storedVendor.size() == 0) |  | ||||||
|     { |  | ||||||
|         m_JavaChecker.reset(new JavaChecker); |         m_JavaChecker.reset(new JavaChecker); | ||||||
|         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->m_path = realJavaPath; | ||||||
|         m_JavaChecker->performCheck(); |         m_JavaChecker->performCheck(); | ||||||
|         return; |         return; | ||||||
|     } |     } else { | ||||||
|     else |  | ||||||
|     { |  | ||||||
|         auto verString = instance->settings()->get("JavaVersion").toString(); |         auto verString = instance->settings()->get("JavaVersion").toString(); | ||||||
|         auto archString = instance->settings()->get("JavaArchitecture").toString(); |         auto archString = instance->settings()->get("JavaArchitecture").toString(); | ||||||
|         auto realArchString = settings->get("JavaRealArchitecture").toString(); |         auto realArchString = settings->get("JavaRealArchitecture").toString(); | ||||||
| @@ -118,10 +108,8 @@ void CheckJava::executeTask() | |||||||
|  |  | ||||||
| void CheckJava::checkJavaFinished(JavaCheckResult result) | void CheckJava::checkJavaFinished(JavaCheckResult result) | ||||||
| { | { | ||||||
|     switch (result.validity) |     switch (result.validity) { | ||||||
|     { |         case JavaCheckResult::Validity::Errored: { | ||||||
|         case JavaCheckResult::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); | ||||||
| @@ -129,16 +117,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 JavaCheckResult::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 JavaCheckResult::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()); | ||||||
| @@ -154,6 +140,7 @@ void CheckJava::checkJavaFinished(JavaCheckResult result) | |||||||
|  |  | ||||||
| void CheckJava::printJavaInfo(const QString& version, const QString& architecture, const QString& realArchitecture, const QString& vendor) | void CheckJava::printJavaInfo(const QString& version, const QString& architecture, const QString& realArchitecture, const QString& vendor) | ||||||
| { | { | ||||||
|     emit logLine(QString("Java is version %1, using %2 (%3) architecture, from %4.\n\n") |     emit logLine( | ||||||
|                     .arg(version, architecture, realArchitecture, vendor), MessageLevel::Launcher); |         QString("Java is version %1, using %2 (%3) architecture, from %4.\n\n").arg(version, architecture, realArchitecture, vendor), | ||||||
|  |         MessageLevel::Launcher); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -15,22 +15,18 @@ | |||||||
|  |  | ||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
| #include <launch/LaunchStep.h> |  | ||||||
| #include <LoggedProcess.h> | #include <LoggedProcess.h> | ||||||
| #include <java/JavaChecker.h> | #include <java/JavaChecker.h> | ||||||
|  | #include <launch/LaunchStep.h> | ||||||
|  |  | ||||||
| class CheckJava: public LaunchStep | class CheckJava : public LaunchStep { | ||||||
| { |  | ||||||
|     Q_OBJECT |     Q_OBJECT | ||||||
|    public: |    public: | ||||||
|     explicit CheckJava(LaunchTask* parent) : LaunchStep(parent){}; |     explicit CheckJava(LaunchTask* parent) : LaunchStep(parent){}; | ||||||
|     virtual ~CheckJava(){}; |     virtual ~CheckJava(){}; | ||||||
|  |  | ||||||
|     virtual void executeTask(); |     virtual void executeTask(); | ||||||
|     virtual bool canAbort() const |     virtual bool canAbort() const { return false; } | ||||||
|     { |  | ||||||
|         return false; |  | ||||||
|     } |  | ||||||
|    private slots: |    private slots: | ||||||
|     void checkJavaFinished(JavaCheckResult result); |     void checkJavaFinished(JavaCheckResult result); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -13,13 +13,11 @@ | |||||||
|  * limitations under the License. |  * limitations under the License. | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
|  |  | ||||||
| #include "LookupServerAddress.h" | #include "LookupServerAddress.h" | ||||||
|  |  | ||||||
| #include <launch/LaunchTask.h> | #include <launch/LaunchTask.h> | ||||||
|  |  | ||||||
| LookupServerAddress::LookupServerAddress(LaunchTask *parent) : | LookupServerAddress::LookupServerAddress(LaunchTask* parent) : LaunchStep(parent), m_dnsLookup(new QDnsLookup(this)) | ||||||
|     LaunchStep(parent), m_dnsLookup(new QDnsLookup(this)) |  | ||||||
| { | { | ||||||
|     connect(m_dnsLookup, &QDnsLookup::finished, this, &LookupServerAddress::on_dnsLookupFinished); |     connect(m_dnsLookup, &QDnsLookup::finished, this, &LookupServerAddress::on_dnsLookupFinished); | ||||||
|  |  | ||||||
| @@ -51,27 +49,25 @@ void LookupServerAddress::executeTask() | |||||||
|  |  | ||||||
| void LookupServerAddress::on_dnsLookupFinished() | void LookupServerAddress::on_dnsLookupFinished() | ||||||
| { | { | ||||||
|     if (isFinished()) |     if (isFinished()) { | ||||||
|     { |  | ||||||
|         // Aborted |         // Aborted | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (m_dnsLookup->error() != QDnsLookup::NoError) |     if (m_dnsLookup->error() != QDnsLookup::NoError) { | ||||||
|     { |  | ||||||
|         emit logLine(QString("Failed to resolve server address (this is NOT an error!) %1: %2\n") |         emit logLine(QString("Failed to resolve server address (this is NOT an error!) %1: %2\n") | ||||||
|             .arg(m_dnsLookup->name(), m_dnsLookup->errorString()), MessageLevel::Launcher); |                          .arg(m_dnsLookup->name(), m_dnsLookup->errorString()), | ||||||
|  |                      MessageLevel::Launcher); | ||||||
|         resolve(m_lookupAddress, 25565);  // Technically the task failed, however, we don't abort the launch |         resolve(m_lookupAddress, 25565);  // Technically the task failed, however, we don't abort the launch | ||||||
|                                           // and leave it up to minecraft to fail (or maybe not) when connecting |                                           // and leave it up to minecraft to fail (or maybe not) when connecting | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     const auto records = m_dnsLookup->serviceRecords(); |     const auto records = m_dnsLookup->serviceRecords(); | ||||||
|     if (records.empty()) |     if (records.empty()) { | ||||||
|     { |         emit logLine(QString("Failed to resolve server address %1: the DNS lookup succeeded, but no records were returned.\n") | ||||||
|         emit logLine( |                          .arg(m_dnsLookup->name()), | ||||||
|                 QString("Failed to resolve server address %1: the DNS lookup succeeded, but no records were returned.\n") |                      MessageLevel::Warning); | ||||||
|                 .arg(m_dnsLookup->name()), MessageLevel::Warning); |  | ||||||
|         resolve(m_lookupAddress, 25565);  // Technically the task failed, however, we don't abort the launch |         resolve(m_lookupAddress, 25565);  // Technically the task failed, however, we don't abort the launch | ||||||
|                                           // and leave it up to minecraft to fail (or maybe not) when connecting |                                           // and leave it up to minecraft to fail (or maybe not) when connecting | ||||||
|         return; |         return; | ||||||
| @@ -80,8 +76,9 @@ void LookupServerAddress::on_dnsLookupFinished() | |||||||
|     const auto& firstRecord = records.at(0); |     const auto& firstRecord = records.at(0); | ||||||
|     quint16 port = firstRecord.port(); |     quint16 port = firstRecord.port(); | ||||||
|  |  | ||||||
|     emit logLine(QString("Resolved server address %1 to %2 with port %3\n").arg( |     emit logLine( | ||||||
|             m_dnsLookup->name(), firstRecord.target(), QString::number(port)),MessageLevel::Launcher); |         QString("Resolved server address %1 to %2 with port %3\n").arg(m_dnsLookup->name(), firstRecord.target(), QString::number(port)), | ||||||
|  |         MessageLevel::Launcher); | ||||||
|     resolve(firstRecord.target(), port); |     resolve(firstRecord.target(), port); | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -15,8 +15,8 @@ | |||||||
|  |  | ||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
| #include <launch/LaunchStep.h> |  | ||||||
| #include <QObjectPtr.h> | #include <QObjectPtr.h> | ||||||
|  | #include <launch/LaunchStep.h> | ||||||
| #include <QDnsLookup> | #include <QDnsLookup> | ||||||
|  |  | ||||||
| #include "minecraft/launch/MinecraftServerTarget.h" | #include "minecraft/launch/MinecraftServerTarget.h" | ||||||
| @@ -29,10 +29,7 @@ public: | |||||||
|  |  | ||||||
|     virtual void executeTask(); |     virtual void executeTask(); | ||||||
|     virtual bool abort(); |     virtual bool abort(); | ||||||
|     virtual bool canAbort() const |     virtual bool canAbort() const { return true; } | ||||||
|     { |  | ||||||
|         return true; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     void setLookupAddress(const QString& lookupAddress); |     void setLookupAddress(const QString& lookupAddress); | ||||||
|     void setOutputAddressPtr(MinecraftServerTargetPtr output); |     void setOutputAddressPtr(MinecraftServerTargetPtr output); | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| // SPDX-License-Identifier: GPL-3.0-only | // SPDX-License-Identifier: GPL-3.0-only | ||||||
| /* | /* | ||||||
|  *  PolyMC - Minecraft Launcher |  *  Prism Launcher - Minecraft Launcher | ||||||
|  *  Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net> |  *  Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net> | ||||||
|  * |  * | ||||||
|  *  This program is free software: you can redistribute it and/or modify |  *  This program is free software: you can redistribute it and/or modify | ||||||
| @@ -65,31 +65,22 @@ void PostLaunchCommand::executeTask() | |||||||
|  |  | ||||||
| void PostLaunchCommand::on_state(LoggedProcess::State state) | void PostLaunchCommand::on_state(LoggedProcess::State state) | ||||||
| { | { | ||||||
|     auto getError = [&]() |     auto getError = [&]() { return tr("Post-Launch command failed with code %1.\n\n").arg(m_process.exitCode()); }; | ||||||
|     { |     switch (state) { | ||||||
|         return tr("Post-Launch command failed with code %1.\n\n").arg(m_process.exitCode()); |  | ||||||
|     }; |  | ||||||
|     switch(state) |  | ||||||
|     { |  | ||||||
|         case LoggedProcess::Aborted: |         case LoggedProcess::Aborted: | ||||||
|         case LoggedProcess::Crashed: |         case LoggedProcess::Crashed: | ||||||
|         case LoggedProcess::FailedToStart: |         case LoggedProcess::FailedToStart: { | ||||||
|         { |  | ||||||
|             auto error = getError(); |             auto error = getError(); | ||||||
|             emit logLine(error, MessageLevel::Fatal); |             emit logLine(error, MessageLevel::Fatal); | ||||||
|             emitFailed(error); |             emitFailed(error); | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|         case LoggedProcess::Finished: |         case LoggedProcess::Finished: { | ||||||
|         { |             if (m_process.exitCode() != 0) { | ||||||
|             if(m_process.exitCode() != 0) |  | ||||||
|             { |  | ||||||
|                 auto error = getError(); |                 auto error = getError(); | ||||||
|                 emit logLine(error, MessageLevel::Fatal); |                 emit logLine(error, MessageLevel::Fatal); | ||||||
|                 emitFailed(error); |                 emitFailed(error); | ||||||
|             } |             } else { | ||||||
|             else |  | ||||||
|             { |  | ||||||
|                 emit logLine(tr("Post-Launch command ran successfully.\n\n"), MessageLevel::Launcher); |                 emit logLine(tr("Post-Launch command ran successfully.\n\n"), MessageLevel::Launcher); | ||||||
|                 emitSucceeded(); |                 emitSucceeded(); | ||||||
|             } |             } | ||||||
| @@ -107,8 +98,7 @@ void PostLaunchCommand::setWorkingDirectory(const QString &wd) | |||||||
| bool PostLaunchCommand::abort() | bool PostLaunchCommand::abort() | ||||||
| { | { | ||||||
|     auto state = m_process.state(); |     auto state = m_process.state(); | ||||||
|     if (state == LoggedProcess::Running || state == LoggedProcess::Starting) |     if (state == LoggedProcess::Running || state == LoggedProcess::Starting) { | ||||||
|     { |  | ||||||
|         m_process.kill(); |         m_process.kill(); | ||||||
|     } |     } | ||||||
|     return true; |     return true; | ||||||
|   | |||||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user
	 Tayou
					Tayou