diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 3574bf20d..4ea328301 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -23,14 +23,14 @@ body: - macOS - Linux - Other -- type: input +- type: textarea attributes: label: Version of Prism Launcher description: The version of Prism Launcher used in the bug report. placeholder: Prism Launcher 5.0 validations: required: true -- type: input +- type: textarea attributes: label: Version of Qt description: The version of Qt used in the bug report. You can find it in Help -> About Prism Launcher -> About Qt. diff --git a/.github/actions/package/windows/action.yml b/.github/actions/package/windows/action.yml index 532f3db44..cd0eb7d91 100644 --- a/.github/actions/package/windows/action.yml +++ b/.github/actions/package/windows/action.yml @@ -69,7 +69,7 @@ runs: - name: Sign executables if: ${{ env.CI_HAS_ACCESS_TO_AZURE != '' && inputs.azure-client-id != '' }} - uses: azure/artifact-signing-action@v2 + uses: azure/artifact-signing-action@v1 with: endpoint: https://eus.codesigning.azure.net/ trusted-signing-account-name: PrismLauncher @@ -142,7 +142,7 @@ runs: - name: Sign installer if: ${{ env.CI_HAS_ACCESS_TO_AZURE != '' && inputs.azure-client-id != '' }} - uses: azure/artifact-signing-action@v2 + uses: azure/artifact-signing-action@v1 with: endpoint: https://eus.codesigning.azure.net/ trusted-signing-account-name: PrismLauncher diff --git a/.github/actions/setup-dependencies/action.yml b/.github/actions/setup-dependencies/action.yml index b73c7509a..7d403ed0a 100644 --- a/.github/actions/setup-dependencies/action.yml +++ b/.github/actions/setup-dependencies/action.yml @@ -55,7 +55,7 @@ runs: # TODO(@getchoo): Get this working on MSYS2! - name: Setup ccache if: ${{ (runner.os != 'Windows' || inputs.msystem == '') && inputs.build-type == 'Debug' }} - uses: hendrikmuhs/ccache-action@v1.2.23 + uses: hendrikmuhs/ccache-action@v1.2.22 with: variant: sccache create-symlink: ${{ runner.os != 'Windows' }} diff --git a/.github/actions/setup-dependencies/linux/action.yml b/.github/actions/setup-dependencies/linux/action.yml index fa5af702b..fe7ee2142 100644 --- a/.github/actions/setup-dependencies/linux/action.yml +++ b/.github/actions/setup-dependencies/linux/action.yml @@ -13,7 +13,7 @@ runs: dpkg-dev \ ninja-build extra-cmake-modules pkg-config scdoc \ cmark gamemode-dev libarchive-dev libcmark-dev libqrencode-dev zlib1g-dev \ - libxcb-cursor-dev libtomlplusplus-dev + libxcb-cursor-dev libtomlplusplus-dev libvulkan-dev - name: Setup AppImage tooling shell: bash diff --git a/.github/actions/setup-dependencies/windows/action.yml b/.github/actions/setup-dependencies/windows/action.yml index 24ad51d8f..d2d0820d8 100644 --- a/.github/actions/setup-dependencies/windows/action.yml +++ b/.github/actions/setup-dependencies/windows/action.yml @@ -91,7 +91,7 @@ runs: - name: Retrieve ccache cache (MinGW) if: ${{ inputs.msystem != '' && inputs.build-type == 'Debug' }} - uses: actions/cache@v5.0.5 + uses: actions/cache@v5.0.4 with: path: '${{ github.workspace }}\.ccache' key: ${{ runner.os }}-mingw-w64-ccache-${{ github.run_id }} diff --git a/.github/workflows/backport.yml b/.github/workflows/backport.yml index 9cde3307d..02fba2f68 100644 --- a/.github/workflows/backport.yml +++ b/.github/workflows/backport.yml @@ -24,7 +24,7 @@ jobs: with: ref: ${{ github.event.pull_request.head.sha }} - name: Create backport PRs - uses: korthout/backport-action@v4.5 + uses: korthout/backport-action@v4.3.0 with: # Config README: https://github.com/korthout/backport-action#backport-action pull_description: |- diff --git a/.github/workflows/clang-tidy.yml b/.github/workflows/clang-tidy.yml index d72994c50..5251c149a 100644 --- a/.github/workflows/clang-tidy.yml +++ b/.github/workflows/clang-tidy.yml @@ -28,14 +28,19 @@ jobs: fetch-depth: 0 # Required for diffing later on submodules: "true" + - name: Setup sccache + uses: hendrikmuhs/ccache-action@v1.2.22 + with: + variant: sccache + - name: Install Nix uses: cachix/install-nix-action@v31 - - name: Run source generators + - name: Run build # TODO(@getchoo): Figure out how to make this work with PCH run: | nix develop --command bash -c ' - cmake -B build -D Launcher_USE_PCH=OFF && cmake --build build --target autogen autorcc + cmake -B build -D Launcher_USE_PCH=OFF -D CMAKE_CXX_COMPILER_LAUNCHER=sccache && cmake --build build ' # TODO: Use SARIF after https://github.com/psastras/sarif-rs/issues/638 is fixed diff --git a/.github/workflows/container.yml b/.github/workflows/container.yml index 7af2c1ccb..a5dcdc48a 100644 --- a/.github/workflows/container.yml +++ b/.github/workflows/container.yml @@ -33,7 +33,7 @@ jobs: - arch: arm64 os: ubuntu-24.04-arm - arch: amd64 - os: ubuntu-24.04 + os: ubuntu-24.04-arm runs-on: ${{ matrix.os }} diff --git a/.github/workflows/nix.yml b/.github/workflows/nix.yml index 58f4d263a..0fea44f08 100644 --- a/.github/workflows/nix.yml +++ b/.github/workflows/nix.yml @@ -103,7 +103,7 @@ jobs: # For PRs - name: Setup Nix Magic Cache if: ${{ github.event_name == 'pull_request' }} - uses: DeterminateSystems/magic-nix-cache-action@v14 + uses: DeterminateSystems/magic-nix-cache-action@v13 with: diagnostic-endpoint: "" use-flakehub: false diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index e332488c3..ecc23effa 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -94,7 +94,7 @@ jobs: - name: Create release id: create_release - uses: softprops/action-gh-release@v3 + uses: softprops/action-gh-release@v2 with: token: ${{ secrets.GITHUB_TOKEN }} tag_name: ${{ github.ref }} diff --git a/.github/workflows/update-flake.yml b/.github/workflows/update-flake.yml index fa3e3b4d3..1353166f1 100644 --- a/.github/workflows/update-flake.yml +++ b/.github/workflows/update-flake.yml @@ -20,7 +20,7 @@ jobs: steps: - uses: actions/checkout@v6 - - uses: cachix/install-nix-action@8aa03977d8d733052d78f4e008a241fd1dbf36b3 # v31 + - uses: cachix/install-nix-action@96951a368ba55167b55f1c916f7d416bac6505fe # v31 - uses: DeterminateSystems/update-flake-lock@v28 with: diff --git a/CMakeLists.txt b/CMakeLists.txt index 12afdefcc..6e5fe090b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,10 +13,6 @@ endif() ##################################### Set CMake options ##################################### set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) -set(CMAKE_AUTOUIC ON) -set(CMAKE_AUTOGEN_ORIGIN_DEPENDS OFF) -set(CMAKE_GLOBAL_AUTOGEN_TARGET ON) -set(CMAKE_GLOBAL_AUTORCC_TARGET ON) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake/") @@ -183,9 +179,9 @@ set(Launcher_LOGIN_CALLBACK_URL "https://prismlauncher.org/successful-login" CAC set(Launcher_LEGACY_FMLLIBS_BASE_URL "https://files.prismlauncher.org/fmllibs/" CACHE STRING "URL for legacy (<=1.5.2) FML Libraries.") ######## Set version numbers ######## -set(Launcher_VERSION_MAJOR 12) +set(Launcher_VERSION_MAJOR 11) set(Launcher_VERSION_MINOR 0) -set(Launcher_VERSION_PATCH 0) +set(Launcher_VERSION_PATCH 1) set(Launcher_VERSION_NAME "${Launcher_VERSION_MAJOR}.${Launcher_VERSION_MINOR}.${Launcher_VERSION_PATCH}") set(Launcher_VERSION_NAME4 "${Launcher_VERSION_MAJOR}.${Launcher_VERSION_MINOR}.${Launcher_VERSION_PATCH}.0") diff --git a/Containerfile b/Containerfile index 59595fe55..8ee4330ed 100644 --- a/Containerfile +++ b/Containerfile @@ -28,7 +28,7 @@ RUN apt-get --assume-yes --no-install-recommends install \ # Build system cmake ninja-build extra-cmake-modules pkg-config \ # Dependencies - cmark gamemode-dev libarchive-dev libcmark-dev libgamemode0 libgl1-mesa-dev libqrencode-dev libtomlplusplus-dev scdoc zlib1g-dev \ + cmark gamemode-dev libarchive-dev libcmark-dev libgamemode0 libgl1-mesa-dev libqrencode-dev libtomlplusplus-dev libvulkan-dev scdoc zlib1g-dev \ # Tooling clang-format clang-tidy git diff --git a/buildconfig/BuildConfig.h b/buildconfig/BuildConfig.h index a5851bfba..d430622bc 100644 --- a/buildconfig/BuildConfig.h +++ b/buildconfig/BuildConfig.h @@ -194,10 +194,8 @@ class Config { QString MODRINTH_STAGING_URL = "https://staging-api.modrinth.com/v2"; QString MODRINTH_PROD_URL = "https://api.modrinth.com/v2"; QStringList MODRINTH_MRPACK_HOSTS{ "cdn.modrinth.com", "github.com", "raw.githubusercontent.com", "gitlab.com" }; - QString MODRINTH_DOWNLOAD_HOST = "cdn.modrinth.com"; QString FLAME_BASE_URL = "https://api.curseforge.com/v1"; - QString FLAME_DOWNLOAD_HOST = "edge.forgecdn.net"; QString versionString() const; /** diff --git a/flake.lock b/flake.lock index 640d2bcf1..eb53cb844 100644 --- a/flake.lock +++ b/flake.lock @@ -18,11 +18,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1778443072, - "narHash": "sha256-rNDJzV2JTV5SUTwv1cgKZYMdyoUYU9/YfegSaUf3QfY=", - "rev": "da5ad661ba4e5ef59ba743f0d112cbc30e474f32", + "lastModified": 1774709303, + "narHash": "sha256-D4ely1FsBcvtj/qSrNhSWpq+CUZKNiKwJIxpxnfy9o4=", + "rev": "8110df5ad7abf5d4c0f6fb0f8f978390e77f9685", "type": "tarball", - "url": "https://releases.nixos.org/nixos/unstable/nixos-26.05pre995699.da5ad661ba4e/nixexprs.tar.xz" + "url": "https://releases.nixos.org/nixos/unstable/nixos-26.05pre971119.8110df5ad7ab/nixexprs.tar.xz" }, "original": { "type": "tarball", diff --git a/launcher/Application.cpp b/launcher/Application.cpp index ddeb30588..115b6489c 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -578,14 +578,16 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) } { - auto migrated = handleDataMigration( - dataPath, FS::PathCombine(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation), "../../PolyMC"), "PolyMC", - "polymc.cfg"); - if (!migrated) { - handleDataMigration(dataPath, - FS::PathCombine(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation), "../../multimc"), - "MultiMC", "multimc.cfg"); - } + bool migrated = false; + + if (!migrated) + migrated = handleDataMigration( + dataPath, FS::PathCombine(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation), "../../PolyMC"), "PolyMC", + "polymc.cfg"); + if (!migrated) + migrated = handleDataMigration( + dataPath, FS::PathCombine(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation), "../../multimc"), "MultiMC", + "multimc.cfg"); } { @@ -777,7 +779,6 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) m_settings->registerSetting("ModDependenciesDisabled", false); m_settings->registerSetting("SkipModpackUpdatePrompt", false); m_settings->registerSetting("ShowModIncompat", false); - m_settings->registerSetting("DownloadGameFilesDuringInstanceCreation", true); // Minecraft offline player name m_settings->registerSetting("LastOfflinePlayerName", ""); @@ -870,7 +871,6 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) resetIfInvalid(m_settings->registerSetting("LegacyFMLLibsURLOverride", "").get()); } - m_settings->registerSetting("MetaRefreshOnLaunch", true); m_settings->registerSetting("CloseAfterLaunch", false); m_settings->registerSetting("QuitAfterGameStop", false); @@ -935,6 +935,15 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) qInfo() << "<> Network done."; } + // load translations + { + m_translations.reset(new TranslationsModel("translations")); + auto bcp47Name = m_settings->get("Language").toString(); + m_translations->selectLanguage(bcp47Name); + qInfo() << "Your language is" << bcp47Name; + qInfo() << "<> Translations loaded."; + } + // Instance icons { auto setting = APPLICATION->settings()->getSetting("IconsDir"); @@ -1013,13 +1022,8 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) qInfo() << "<> Cache initialized."; } - // load translations - { - m_translations.reset(new TranslationsModel("translations")); - m_translations->downloadIndex(); - qInfo() << "Your language is" << m_translations->selectedLanguage(); - qInfo() << "<> Translations loaded."; - } + // now we have network, download translation updates + m_translations->downloadIndex(); // FIXME: what to do with these? m_profilers.insert("jprofiler", std::shared_ptr(new JProfilerFactory())); diff --git a/launcher/BaseVersionList.h b/launcher/BaseVersionList.h index ba546e955..673d13562 100644 --- a/launcher/BaseVersionList.h +++ b/launcher/BaseVersionList.h @@ -63,7 +63,7 @@ class BaseVersionList : public QAbstractListModel { * The task returned by this function should reset the model when it's done. * \return A pointer to a task that reloads the version list. */ - virtual Task::Ptr getLoadTask(bool forceReload = false) = 0; + virtual Task::Ptr getLoadTask() = 0; //! Checks whether or not the list is loaded. If this returns false, the list should be // loaded. diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index 7d4430fd2..c2f5e70cf 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -1206,6 +1206,78 @@ if(WIN32) ) endif() +qt_wrap_ui(LAUNCHER_UI + ui/MainWindow.ui + ui/setupwizard/PasteWizardPage.ui + ui/setupwizard/AutoJavaWizardPage.ui + ui/setupwizard/LoginWizardPage.ui + ui/pages/global/AccountListPage.ui + ui/pages/global/JavaPage.ui + ui/pages/global/LauncherPage.ui + ui/pages/global/APIPage.ui + ui/pages/global/ProxyPage.ui + ui/pages/global/ExternalToolsPage.ui + ui/pages/instance/ExternalResourcesPage.ui + ui/pages/instance/NotesPage.ui + ui/pages/instance/LogPage.ui + ui/pages/instance/ServersPage.ui + ui/pages/instance/OtherLogsPage.ui + ui/pages/instance/VersionPage.ui + ui/pages/instance/ManagedPackPage.ui + ui/pages/instance/WorldListPage.ui + ui/pages/instance/ScreenshotsPage.ui + ui/pages/modplatform/atlauncher/AtlOptionalModDialog.ui + ui/pages/modplatform/atlauncher/AtlPage.ui + ui/pages/modplatform/CustomPage.ui + ui/pages/modplatform/ResourcePage.ui + ui/pages/modplatform/flame/FlamePage.ui + ui/pages/modplatform/legacy_ftb/Page.ui + ui/pages/modplatform/import_ftb/ImportFTBPage.ui + ui/pages/modplatform/ImportPage.ui + ui/pages/modplatform/OptionalModDialog.ui + ui/pages/modplatform/ftb/FtbPage.ui + ui/pages/modplatform/modrinth/ModrinthPage.ui + ui/pages/modplatform/technic/TechnicPage.ui + ui/widgets/CustomCommands.ui + ui/widgets/EnvironmentVariables.ui + ui/widgets/InfoFrame.ui + ui/widgets/ModFilterWidget.ui + ui/widgets/SubTaskProgressBar.ui + ui/widgets/AppearanceWidget.ui + ui/widgets/MinecraftSettingsWidget.ui + ui/widgets/JavaSettingsWidget.ui + ui/dialogs/CopyInstanceDialog.ui + ui/dialogs/CreateShortcutDialog.ui + ui/dialogs/ProfileSetupDialog.ui + ui/dialogs/ProgressDialog.ui + ui/dialogs/NewInstanceDialog.ui + ui/dialogs/NetworkJobFailedDialog.ui + ui/dialogs/NewComponentDialog.ui + ui/dialogs/NewsDialog.ui + ui/dialogs/ProfileSelectDialog.ui + ui/dialogs/ExportInstanceDialog.ui + ui/dialogs/ExportPackDialog.ui + ui/dialogs/ExportToModListDialog.ui + ui/dialogs/IconPickerDialog.ui + ui/dialogs/ImportResourceDialog.ui + ui/dialogs/MSALoginDialog.ui + ui/dialogs/AboutDialog.ui + ui/dialogs/ReviewMessageBox.ui + ui/dialogs/ScrollMessageBox.ui + ui/dialogs/BlockedModsDialog.ui + ui/dialogs/ChooseProviderDialog.ui + ui/dialogs/skins/SkinManageDialog.ui + ui/dialogs/ChooseOfflineNameDialog.ui +) + +qt_wrap_ui(PRISM_UPDATE_UI + ui/dialogs/UpdateAvailableDialog.ui +) + +if (NOT Apple) + set (LAUNCHER_UI ${LAUNCHER_UI} ${PRISM_UPDATE_UI}) +endif() + qt_add_resources(LAUNCHER_RESOURCES resources/backgrounds/backgrounds.qrc resources/multimc/multimc.qrc @@ -1224,6 +1296,12 @@ qt_add_resources(LAUNCHER_RESOURCES "${CMAKE_CURRENT_BINARY_DIR}/../${Launcher_Branding_LogoQRC}" ) +qt_wrap_ui(PRISMUPDATER_UI + updater/prismupdater/SelectReleaseDialog.ui + ui/widgets/SubTaskProgressBar.ui + ui/dialogs/ProgressDialog.ui +) + ######## Windows resource files ######## if(WIN32) set(LAUNCHER_RCS ${CMAKE_CURRENT_BINARY_DIR}/../${Launcher_Branding_WindowsRC}) @@ -1243,7 +1321,7 @@ endif() ####### Targets ######## # Add executable -add_library(Launcher_logic STATIC ${LOGIC_SOURCES} ${LAUNCHER_SOURCES} ${LAUNCHER_RESOURCES}) +add_library(Launcher_logic STATIC ${LOGIC_SOURCES} ${LAUNCHER_SOURCES} ${LAUNCHER_UI} ${LAUNCHER_RESOURCES}) target_include_directories(Launcher_logic PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) target_compile_definitions(Launcher_logic PUBLIC LAUNCHER_APPLICATION) @@ -1363,7 +1441,7 @@ endif() if(Launcher_BUILD_UPDATER) # Updater - add_library(prism_updater_logic STATIC ${PRISMUPDATER_SOURCES} ${TASKS_SOURCES}) + add_library(prism_updater_logic STATIC ${PRISMUPDATER_SOURCES} ${TASKS_SOURCES} ${PRISMUPDATER_UI}) target_include_directories(prism_updater_logic PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) if(${Launcher_USE_PCH}) @@ -1491,10 +1569,8 @@ if (CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC") target_compile_options(Launcher_logic PRIVATE /wd4100) # C4100 - unused parameter target_compile_options(${Launcher_Name} PRIVATE /wd4100) # C4100 - unused parameter else() - # sfinae-incomplete is a new GCC warning and triggers in Qt headers - # no-unknown-warning-option so that compilers that don't have sfinae-incomplete don't error - target_compile_options(Launcher_logic PRIVATE -Wno-unused-parameter -Wno-missing-field-initializers -Wno-unknown-warning-option -Wno-sfinae-incomplete) - target_compile_options(${Launcher_Name} PRIVATE -Wno-unused-parameter -Wno-missing-field-initializers -Wno-unknown-warning-option -Wno-sfinae-incomplete) + target_compile_options(Launcher_logic PRIVATE -Wno-unused-parameter -Wno-missing-field-initializers) + target_compile_options(${Launcher_Name} PRIVATE -Wno-unused-parameter -Wno-missing-field-initializers) endif() #### The bundle mess! #### diff --git a/launcher/FileSystem.cpp b/launcher/FileSystem.cpp index ef56e3e65..f53c9343e 100644 --- a/launcher/FileSystem.cpp +++ b/launcher/FileSystem.cpp @@ -36,7 +36,6 @@ */ #include "FileSystem.h" -#include #include #include "BuildConfig.h" @@ -684,32 +683,6 @@ bool deletePath(QString path) return err.value() == 0; } -bool deleteContents(const QString& path) -{ - const QFileInfo info(path); - if (!info.exists()) { - return true; - } - if (!info.isDir()) { - qWarning() << "Attempted to delete contents of non-directory path:" << path; - return false; - } - - bool ret = true; - - for (const auto& entry : fs::directory_iterator(StringUtils::toStdString(path))) { - std::error_code err; - - fs::remove_all(entry.path(), err); - if (err.value() != 0) { - qWarning().nospace() << "Could not delete directory entry " << entry.path() << ": " << QString::fromStdString(err.message()); - ret = false; - } - } - - return ret; -} - bool trash(QString path, QString* pathInTrash) { // FIXME: Figure out trash in Flatpak. Qt seemingly doesn't use the Trash portal @@ -823,33 +796,68 @@ QString NormalizePath(QString path) } } -namespace { -const QString g_badChars = "<>:\"|?*\r\n!"; -QString removeChars(QString source, QChar replace, const QString& extraChars = "") -{ - auto badChars = g_badChars; - if (!extraChars.isEmpty()) { - badChars += extraChars; - } +static const QString BAD_WIN_CHARS = "<>:\"|?*\r\n"; +static const QString BAD_NTFS_CHARS = "<>:\"|?*"; +static const QString BAD_HFS_CHARS = ":"; - for (auto& c : source) { - if (c.unicode() < 0x20 || !c.isPrint() || badChars.contains(c)) { - c = replace; - } - } - - return source; -} -} // namespace +static const QString BAD_FILENAME_CHARS = BAD_WIN_CHARS + "\\/"; QString RemoveInvalidFilenameChars(QString string, QChar replaceWith) { - return removeChars(std::move(string), replaceWith, "\\/"); + for (int i = 0; i < string.length(); i++) + if (string.at(i) < ' ' || BAD_FILENAME_CHARS.contains(string.at(i))) + string[i] = replaceWith; + return string; } -QString RemoveInvalidPathChars(QString string, QChar replaceWith) +QString RemoveInvalidPathChars(QString path, QChar replaceWith) { - return removeChars(std::move(string), replaceWith); + QString invalidChars; +#ifdef Q_OS_WIN + invalidChars = BAD_WIN_CHARS; +#endif + + // the null character is ignored in this check as it was not a problem until now + switch (statFS(path).fsType) { + case FilesystemType::FAT: // similar to NTFS + /* fallthrough */ + case FilesystemType::NTFS: + /* fallthrough */ + case FilesystemType::REFS: // similar to NTFS(should be available only on windows) + invalidChars += BAD_NTFS_CHARS; + break; + // case FilesystemType::EXT: + // case FilesystemType::EXT_2_OLD: + // case FilesystemType::EXT_2_3_4: + // case FilesystemType::XFS: + // case FilesystemType::BTRFS: + // case FilesystemType::NFS: + // case FilesystemType::ZFS: + case FilesystemType::APFS: + /* fallthrough */ + case FilesystemType::HFS: + /* fallthrough */ + case FilesystemType::HFSPLUS: + /* fallthrough */ + case FilesystemType::HFSX: + invalidChars += BAD_HFS_CHARS; + break; + // case FilesystemType::FUSEBLK: + // case FilesystemType::F2FS: + // case FilesystemType::UNKNOWN: + default: + break; + } + + if (invalidChars.size() != 0) { + for (int i = 0; i < path.length(); i++) { + if (path.at(i) < ' ' || invalidChars.contains(path.at(i))) { + path[i] = replaceWith; + } + } + } + + return path; } QString DirNameFromString(QString string, QString inDir) diff --git a/launcher/FileSystem.h b/launcher/FileSystem.h index 6d9b01178..f2676b147 100644 --- a/launcher/FileSystem.h +++ b/launcher/FileSystem.h @@ -291,13 +291,6 @@ bool move(const QString& source, const QString& dest); */ bool deletePath(QString path); -/** - * Delete a folder's contents recursively but not the folder itself. - * @param path The path to the folder. - * @return Whether the deletion was completely successful. - */ -bool deleteContents(const QString& path); - bool removeFiles(QStringList listFile); /** diff --git a/launcher/HardwareInfo.cpp b/launcher/HardwareInfo.cpp index 36b6f7783..5937c33bc 100644 --- a/launcher/HardwareInfo.cpp +++ b/launcher/HardwareInfo.cpp @@ -18,45 +18,84 @@ #include "HardwareInfo.h" -#include -#include +#include +#include +#include +#include +#include "BuildConfig.h" + +#ifndef Q_OS_MACOS +#include +#include +#endif -#if defined(Q_OS_MACOS) || defined(Q_OS_LINUX) namespace { -QString afterColon(QString str) +bool vulkanInfo(QStringList& out) { - return str.remove(0, str.indexOf(':') + 2).trimmed(); + if (!QProcessEnvironment::systemEnvironment() + .value(QStringLiteral("%1_DISABLE_GLVULKAN").arg(BuildConfig.LAUNCHER_ENVNAME)) + .isEmpty()) { + return false; + } +#ifndef Q_OS_MACOS + QVulkanInstance inst; + if (!inst.create()) { + qWarning() << "Vulkan instance creation failed, VkResult:" << inst.errorCode(); + out << "Couldn't get Vulkan device information"; + return false; + } + + QVulkanWindow window; + window.setVulkanInstance(&inst); + + for (auto device : window.availablePhysicalDevices()) { + const auto supportedVulkanVersion = QVersionNumber(VK_API_VERSION_MAJOR(device.apiVersion), VK_API_VERSION_MINOR(device.apiVersion), + VK_API_VERSION_PATCH(device.apiVersion)); + out << QString("Found Vulkan device: %1 (API version %2)").arg(device.deviceName).arg(supportedVulkanVersion.toString()); + } +#endif + + return true; } -template -bool readFromOutput(const char* command, F function) +bool openGlInfo(QStringList& out) { - FILE* file = popen(command, "r"); // NOLINT(*-command-processor) - if (!file) { - qWarning().nospace() << "Could not execute command '" << command << "': " << strerror(errno); + if (!QProcessEnvironment::systemEnvironment() + .value(QStringLiteral("%1_DISABLE_GLVULKAN").arg(BuildConfig.LAUNCHER_ENVNAME)) + .isEmpty()) { + return false; + } + QOpenGLContext ctx; + if (!ctx.create()) { + qWarning() << "OpenGL context creation failed"; + out << "Couldn't get OpenGL device information"; return false; } - constexpr size_t bufferSize = 512; - std::array buffer{}; - while (fgets(buffer.data(), bufferSize, file) != nullptr) { - function(buffer.data()); - } + QOffscreenSurface surface; + surface.create(); + ctx.makeCurrent(&surface); - const int exitCode = pclose(file); - if (exitCode != 0) { - if (exitCode == -1) { - qWarning().nospace() << "Could not close stream for command '" << command << "': " << strerror(errno); - } else { - qWarning().nospace() << "Command '" << command << "' exited with code " << exitCode; - } + auto* f = ctx.functions(); + f->initializeOpenGLFunctions(); - return false; - } + auto toQString = [](const GLubyte* str) { return QString(reinterpret_cast(str)); }; + out << "OpenGL driver vendor: " + toQString(f->glGetString(GL_VENDOR)); + out << "OpenGL renderer: " + toQString(f->glGetString(GL_RENDERER)); + out << "OpenGL driver version: " + toQString(f->glGetString(GL_VERSION)); return true; } } // namespace + +#ifndef Q_OS_LINUX +QStringList HardwareInfo::gpuInfo() +{ + QStringList info; + vulkanInfo(info); + openGlInfo(info); + return info; +} #endif #ifdef Q_OS_WINDOWS @@ -65,11 +104,7 @@ bool readFromOutput(const char* command, F function) #endif #include -#include -#include - -#include -using Microsoft::WRL::ComPtr; +#include "windows.h" QString HardwareInfo::cpuInfo() { @@ -105,42 +140,16 @@ uint64_t HardwareInfo::availableRamMiB() return 0; } -QStringList HardwareInfo::gpuInfo() -{ - ComPtr factory; - HRESULT hr = CreateDXGIFactory1(IID_PPV_ARGS(&factory)); - if (FAILED(hr)) { - qWarning() << "Could not create DXGI factory:" << Qt::hex << hr; - return { "GPU discovery failed: could not create DXGI factory" }; - } - - UINT i = 0; - ComPtr adapter; - QStringList out; - while (factory->EnumAdapterByGpuPreference(i, DXGI_GPU_PREFERENCE_HIGH_PERFORMANCE, IID_PPV_ARGS(&adapter)) != DXGI_ERROR_NOT_FOUND) { - DXGI_ADAPTER_DESC desc; - hr = adapter->GetDesc(&desc); - if (SUCCEEDED(hr)) { - out << "GPU: " + QString::fromWCharArray(desc.Description); // NOLINT(*-pro-bounds-array-to-pointer-decay, *-no-array-decay) - } else { - qWarning() << "Could not get DXGI adapter description:" << Qt::hex << hr; - } - - ++i; - } - - return out; -} - #elif defined(Q_OS_MACOS) +#include "mach/mach.h" #include "sys/sysctl.h" QString HardwareInfo::cpuInfo() { - std::array buffer{}; + std::array buffer; size_t bufferSize = buffer.size(); if (sysctlbyname("machdep.cpu.brand_string", &buffer, &bufferSize, nullptr, 0) == 0) { - return { buffer.data() }; + return QString(buffer.data()); } qWarning() << "Could not get CPU model: sysctlbyname"; @@ -149,7 +158,7 @@ QString HardwareInfo::cpuInfo() uint64_t HardwareInfo::totalRamMiB() { - uint64_t memsize = 0; + uint64_t memsize; size_t memsizeSize = sizeof memsize; if (sysctlbyname("hw.memsize", &memsize, &memsizeSize, nullptr, 0) == 0) { // transforming bytes -> mib @@ -162,62 +171,36 @@ uint64_t HardwareInfo::totalRamMiB() uint64_t HardwareInfo::availableRamMiB() { + mach_port_t host_port = mach_host_self(); + mach_msg_type_number_t count = HOST_VM_INFO64_COUNT; + + vm_statistics64_data_t vm_stats; + + if (host_statistics64(host_port, HOST_VM_INFO64, reinterpret_cast(&vm_stats), &count) == KERN_SUCCESS) { + // transforming bytes -> mib + return (vm_stats.free_count + vm_stats.inactive_count) * vm_page_size / 1024 / 1024; + } + + qWarning() << "Could not get available RAM: host_statistics64"; return 0; } -MacOSHardwareInfo::MemoryPressureLevel MacOSHardwareInfo::memoryPressureLevel() -{ - uint32_t level = 0; - size_t levelSize = sizeof level; - if (sysctlbyname("kern.memorystatus_vm_pressure_level", &level, &levelSize, nullptr, 0) == 0) { - return static_cast(level); - } - - qWarning() << "Could not get memory pressure level: sysctlbyname"; - return MemoryPressureLevel::Normal; -} - -QString MacOSHardwareInfo::memoryPressureLevelName() -{ - // The names are internal, users refer to levels by their graph colors in Activity Monitor - switch (memoryPressureLevel()) { - case MemoryPressureLevel::Normal: - return "Green"; - case MemoryPressureLevel::Warning: - return "Yellow"; - case MemoryPressureLevel::Critical: - return "Red"; - default: - Q_ASSERT(false); - return ""; - } -} - -QStringList HardwareInfo::gpuInfo() -{ - QStringList out; - const bool success = readFromOutput("system_profiler SPDisplaysDataType", [&](const QString& str) { - // Chipset Model: Intel HD Graphics 620 - if (str.contains("Chipset Model")) { - out << "GPU: " + afterColon(str); - } - }); - if (!success) { - return { "GPU discovery failed: could not read from system_profiler" }; - } - - return out; -} - #elif defined(Q_OS_LINUX) #include +namespace { +QString afterColon(QString& str) +{ + return str.remove(0, str.indexOf(':') + 2).trimmed(); +} +} // namespace + QString HardwareInfo::cpuInfo() { std::ifstream cpuin("/proc/cpuinfo"); for (std::string line; std::getline(cpuin, line);) { // model name : AMD Ryzen 7 5800X 8-Core Processor - if (const QString str = QString::fromStdString(line); str.startsWith("model name")) { + if (QString str = QString::fromStdString(line); str.startsWith("model name")) { return afterColon(str); } } @@ -226,13 +209,12 @@ QString HardwareInfo::cpuInfo() return "unknown"; } -namespace { -uint64_t readMemInfo(const QString& searchTarget) +uint64_t readMemInfo(QString searchTarget) { std::ifstream memin("/proc/meminfo"); for (std::string line; std::getline(memin, line);) { // MemTotal: 16287480 kB - if (const QString str = QString::fromStdString(line); str.startsWith(searchTarget)) { + if (QString str = QString::fromStdString(line); str.startsWith(searchTarget)) { bool ok = false; const uint total = str.simplified().section(' ', 1, 1).toUInt(&ok); if (!ok) { @@ -248,7 +230,6 @@ uint64_t readMemInfo(const QString& searchTarget) qWarning() << "Could not read /proc/meminfo: search target not found:" << searchTarget; return 0; } -} // namespace uint64_t HardwareInfo::totalRamMiB() { @@ -262,50 +243,52 @@ uint64_t HardwareInfo::availableRamMiB() QStringList HardwareInfo::gpuInfo() { - bool readingGpuInfo = false; - QString gpu; - QString driverInUse = "NONE"; - QString driversAvailable = "NONE"; - QStringList out; + QStringList list; + const bool vulkanSuccess = vulkanInfo(list); + const bool openGlSuccess = openGlInfo(list); + if (vulkanSuccess || openGlSuccess) { + return list; + } - const bool success = readFromOutput("lspci -k", [&](const QString& str) { + std::array buffer; + FILE* lspci = popen("lspci -k", "r"); + + if (!lspci) { + return { "Could not detect GPUs: lspci is not present" }; + } + + bool readingGpuInfo = false; + QString currentModel = ""; + while (fgets(buffer.data(), 512, lspci) != nullptr) { + QString str(buffer.data()); // clang-format off // 04:00.0 VGA compatible controller: Advanced Micro Devices, Inc. [AMD/ATI] Ellesmere [Radeon RX 470/480/570/570X/580/580X/590] (rev e7) // Subsystem: Sapphire Technology Limited Radeon RX 580 Pulse 4GB // Kernel driver in use: amdgpu // Kernel modules: amdgpu // clang-format on - if (str.contains("VGA compatible controller") || str.contains("3D controller")) { + if (str.contains("VGA compatible controller")) { readingGpuInfo = true; } else if (!str.startsWith('\t')) { - if (readingGpuInfo) { - out << QString("GPU: %1 (driver in use: %2; drivers available: %3)").arg(gpu, driverInUse, driversAvailable); - driverInUse = "NONE"; - driversAvailable = "NONE"; - } readingGpuInfo = false; } - if (!readingGpuInfo) { - return; + continue; } - const QString value = afterColon(str); if (str.contains("Subsystem")) { - gpu = value; + currentModel = "Found GPU: " + afterColon(str); } if (str.contains("Kernel driver in use")) { - driverInUse = value; + currentModel += " (using driver " + afterColon(str); } if (str.contains("Kernel modules")) { - driversAvailable = value; + currentModel += ", available drivers: " + afterColon(str) + ")"; + list.append(currentModel); } - }); - if (!success) { - return { "GPU discovery failed: could not read from lspci" }; } - - return out; + pclose(lspci); + return list; } #else @@ -320,20 +303,19 @@ QString HardwareInfo::cpuInfo() uint64_t HardwareInfo::totalRamMiB() { - uint64_t out = 0; + char buff[512]; + FILE* fp = popen("sysctl hw.physmem", "r"); + if (fp != nullptr) { + if (fgets(buff, 512, fp) != nullptr) { + std::string str(buff); + uint64_t mem = std::stoull(str.substr(12, std::string::npos)); - const bool success = readFromOutput("sysctl hw.physmem", [&](const QString& str) { - const uint64_t mem = str.mid(12).toULong(); - - // transforming kib -> mib - out = mem / 1024; - }); - if (!success) { - qWarning() << "Could not get total RAM: could not read from sysctl"; - return 0; + // transforming kib -> mib + return mem / 1024; + } } - return out; + return 0; } #else @@ -348,8 +330,4 @@ uint64_t HardwareInfo::availableRamMiB() return 0; } -QStringList HardwareInfo::gpuInfo() -{ - return { "GPU discovery failed: not implemented for this OS" }; -} #endif diff --git a/launcher/HardwareInfo.h b/launcher/HardwareInfo.h index 4efd339b6..00e19f214 100644 --- a/launcher/HardwareInfo.h +++ b/launcher/HardwareInfo.h @@ -27,16 +27,3 @@ uint64_t totalRamMiB(); uint64_t availableRamMiB(); QStringList gpuInfo(); } // namespace HardwareInfo - -#ifdef Q_OS_MACOS -namespace MacOSHardwareInfo { -enum class MemoryPressureLevel : uint8_t { - Normal = 1, - Warning = 2, - Critical = 4, -}; - -MemoryPressureLevel memoryPressureLevel(); -QString memoryPressureLevelName(); -} // namespace MacOSHardwareInfo -#endif \ No newline at end of file diff --git a/launcher/InstanceCreationTask.cpp b/launcher/InstanceCreationTask.cpp index e58926660..ecc9fe591 100644 --- a/launcher/InstanceCreationTask.cpp +++ b/launcher/InstanceCreationTask.cpp @@ -3,7 +3,6 @@ #include #include -#include "Application.h" #include "InstanceTask.h" #include "minecraft/MinecraftLoadAndCheck.h" #include "tasks/SequentialTask.h" @@ -19,7 +18,7 @@ bool InstanceCreationTask::abort() return m_gameFilesTask->abort(); } - return InstanceTask::abort(); + return true; } void InstanceCreationTask::executeTask() @@ -39,9 +38,8 @@ void InstanceCreationTask::executeTask() m_instance = createInstance(); if (!m_instance) { - if (m_abort) { + if (m_abort) return; - } qWarning() << "Instance creation failed!"; if (!m_error_message.isEmpty()) { @@ -65,9 +63,8 @@ void InstanceCreationTask::executeTask() qDebug() << "Removing old files"; for (const QString& path : m_filesToRemove) { - if (!QFile::exists(path)) { + if (!QFile::exists(path)) continue; - } qDebug() << "Removing" << path; @@ -84,10 +81,6 @@ void InstanceCreationTask::executeTask() } if (!m_abort) { - if (!APPLICATION->settings()->get("DownloadGameFilesDuringInstanceCreation").toBool()) { - emitSucceeded(); - return; - } setAbortable(true); setAbortButtonText(tr("Skip")); qDebug() << "Downloading game files"; @@ -117,7 +110,7 @@ void InstanceCreationTask::executeTask() } } -void InstanceCreationTask::scheduleToDelete(QWidget* parent, const QDir& dir, const QString& path, bool checkDisabled) +void InstanceCreationTask::scheduleToDelete(QWidget* parent, QDir dir, QString path, bool checkDisabled) { if (path.isEmpty()) { return; diff --git a/launcher/InstanceCreationTask.h b/launcher/InstanceCreationTask.h index 39acaf8b2..416cf81db 100644 --- a/launcher/InstanceCreationTask.h +++ b/launcher/InstanceCreationTask.h @@ -38,7 +38,7 @@ class InstanceCreationTask : public InstanceTask { protected: void setError(const QString& message) { m_error_message = message; }; - void scheduleToDelete(QWidget* parent, const QDir& dir, const QString& path, bool checkDisabled = false); + void scheduleToDelete(QWidget* parent, QDir dir, QString path, bool checkDisabled = false); protected: bool m_abort = false; diff --git a/launcher/LaunchController.cpp b/launcher/LaunchController.cpp index 2b882338c..d263cc50a 100644 --- a/launcher/LaunchController.cpp +++ b/launcher/LaunchController.cpp @@ -40,7 +40,6 @@ #include "minecraft/auth/AccountData.h" #include "minecraft/auth/AccountList.h" -#include "net/NetUtils.h" #include "ui/InstanceWindow.h" #include "ui/dialogs/CustomMessageBox.h" #include "ui/dialogs/MSALoginDialog.h" @@ -110,7 +109,7 @@ void LaunchController::decideAccount() } } - if (!m_accountToUse && accounts->anyAccountIsValid()) { + if (!m_accountToUse) { // If no default account is set, ask the user which one to use. ProfileSelectDialog selectDialog(tr("Which account would you like to use?"), ProfileSelectDialog::GlobalDefaultCheckbox, m_parentWidget); @@ -134,6 +133,14 @@ LaunchDecision LaunchController::decideLaunchMode() return LaunchDecision::Continue; } + if (m_wantedLaunchMode == LaunchMode::Normal) { + if (m_accountToUse->shouldRefresh() || m_accountToUse->accountState() == AccountState::Offline) { + // Force account refresh on the account used to launch the instance updating the AccountState + // only on first try and if it is not meant to be offline + m_accountToUse->refresh(); + } + } + const auto* accounts = APPLICATION->accounts(); MinecraftAccountPtr accountToCheck = nullptr; @@ -156,9 +163,7 @@ LaunchDecision LaunchController::decideLaunchMode() } auto state = accountToCheck->accountState(); - const bool needsRefresh = - m_wantedLaunchMode == LaunchMode::Normal && (state == AccountState::Offline || accountToCheck->shouldRefresh()); - if (state == AccountState::Unchecked || state == AccountState::Errored || needsRefresh) { + if (state == AccountState::Unchecked || state == AccountState::Errored) { accountToCheck->refresh(); state = AccountState::Working; } @@ -226,14 +231,13 @@ bool LaunchController::askPlayDemo() const return box.clickedButton() == demoButton; } -QString LaunchController::askOfflineName(const QString& playerName, bool* ok) +QString LaunchController::askOfflineName(const QString& playerName, bool* ok) const { if (ok != nullptr) { *ok = false; } - QString title, message; - title = tr("Player name"); + QString message; switch (m_actualLaunchMode) { case LaunchMode::Normal: Q_ASSERT(false); @@ -243,14 +247,7 @@ QString LaunchController::askOfflineName(const QString& playerName, bool* ok) break; case LaunchMode::Offline: if (m_wantedLaunchMode == LaunchMode::Normal) { - auto netErr = m_accountToUse->accountData()->networkError; - if (Net::isServerError(netErr)) { - title = tr("Auth servers offline"); - message = tr("The Minecraft authentication servers are currently unavailable, launching in offline mode.\n\n"); - } else { - title = tr("No internet connection"); - message = tr("You are not connected to the Internet, launching in offline mode.\n\n"); - } + message = tr("You are not connected to the Internet, launching in offline mode\n\n"); } message += tr("Choose your offline mode player name"); break; @@ -260,7 +257,7 @@ QString LaunchController::askOfflineName(const QString& playerName, bool* ok) QString usedname = lastOfflinePlayerName.isEmpty() ? playerName : lastOfflinePlayerName; ChooseOfflineNameDialog dialog(message, m_parentWidget); - dialog.setWindowTitle(title); + dialog.setWindowTitle(tr("Player name")); dialog.setUsername(usedname); if (dialog.exec() != QDialog::Accepted) { return {}; @@ -342,11 +339,11 @@ bool LaunchController::reauthenticateAccount(const MinecraftAccountPtr& account, if (button == QMessageBox::StandardButton::Yes) { auto* accounts = APPLICATION->accounts(); const bool isDefault = accounts->defaultAccount() == account; + accounts->removeAccount(accounts->index(accounts->findAccountByProfileId(account->profileId()))); if (account->accountType() == AccountType::MSA) { auto newAccount = MSALoginDialog::newAccount(m_parentWidget); if (newAccount != nullptr) { - accounts->removeAccount(accounts->index(accounts->findAccountByProfileId(account->profileId()))); accounts->addAccount(newAccount); if (isDefault) { diff --git a/launcher/LaunchController.h b/launcher/LaunchController.h index bc0d14e0f..742f20586 100644 --- a/launcher/LaunchController.h +++ b/launcher/LaunchController.h @@ -78,7 +78,7 @@ class LaunchController : public Task { void decideAccount(); LaunchDecision decideLaunchMode(); bool askPlayDemo() const; - QString askOfflineName(const QString& playerName, bool* ok = nullptr); + QString askOfflineName(const QString& playerName, bool* ok = nullptr) const; bool reauthenticateAccount(const MinecraftAccountPtr& account, const QString& reason); private slots: diff --git a/launcher/LoggedProcess.cpp b/launcher/LoggedProcess.cpp index c5ef47d7b..bae45ad88 100644 --- a/launcher/LoggedProcess.cpp +++ b/launcher/LoggedProcess.cpp @@ -114,7 +114,7 @@ void LoggedProcess::on_error(QProcess::ProcessError error) { switch (error) { case QProcess::FailedToStart: { - emit log({ tr("The process failed to start: %1").arg(errorString()) }, MessageLevel::Fatal); + emit log({ tr("The process failed to start.") }, MessageLevel::Fatal); changeState(LoggedProcess::FailedToStart); break; } diff --git a/launcher/MTPixmapCache.h b/launcher/MTPixmapCache.h index 97db598de..0ba9c5ac8 100644 --- a/launcher/MTPixmapCache.h +++ b/launcher/MTPixmapCache.h @@ -14,26 +14,26 @@ else \ type = Qt::DirectConnection; -#define DEFINE_FUNC_NO_PARAM(NAME, RET_TYPE, RET_DEF) \ +#define DEFINE_FUNC_NO_PARAM(NAME, RET_TYPE) \ static RET_TYPE NAME() \ { \ - RET_TYPE ret = RET_DEF; \ + RET_TYPE ret; \ GET_TYPE() \ QMetaObject::invokeMethod(s_instance, "_" #NAME, type, Q_RETURN_ARG(RET_TYPE, ret)); \ return ret; \ } -#define DEFINE_FUNC_ONE_PARAM(NAME, RET_TYPE, RET_DEF, PARAM_1_TYPE) \ +#define DEFINE_FUNC_ONE_PARAM(NAME, RET_TYPE, PARAM_1_TYPE) \ static RET_TYPE NAME(PARAM_1_TYPE p1) \ { \ - RET_TYPE ret = RET_DEF; \ + RET_TYPE ret; \ GET_TYPE() \ QMetaObject::invokeMethod(s_instance, "_" #NAME, type, Q_RETURN_ARG(RET_TYPE, ret), Q_ARG(PARAM_1_TYPE, p1)); \ return ret; \ } -#define DEFINE_FUNC_TWO_PARAM(NAME, RET_TYPE, RET_DEF, PARAM_1_TYPE, PARAM_2_TYPE) \ +#define DEFINE_FUNC_TWO_PARAM(NAME, RET_TYPE, PARAM_1_TYPE, PARAM_2_TYPE) \ static RET_TYPE NAME(PARAM_1_TYPE p1, PARAM_2_TYPE p2) \ { \ - RET_TYPE ret = RET_DEF; \ + RET_TYPE ret; \ GET_TYPE() \ QMetaObject::invokeMethod(s_instance, "_" #NAME, type, Q_RETURN_ARG(RET_TYPE, ret), Q_ARG(PARAM_1_TYPE, p1), \ Q_ARG(PARAM_2_TYPE, p2)); \ @@ -53,18 +53,18 @@ class PixmapCache final : public QObject { static void setInstance(PixmapCache* i) { s_instance = i; } public: - DEFINE_FUNC_NO_PARAM(cacheLimit, int, -1) - DEFINE_FUNC_NO_PARAM(clear, bool, false) - DEFINE_FUNC_TWO_PARAM(find, bool, false, const QString&, QPixmap*) - DEFINE_FUNC_TWO_PARAM(find, bool, false, const QPixmapCache::Key&, QPixmap*) - DEFINE_FUNC_TWO_PARAM(insert, bool, false, const QString&, const QPixmap&) - DEFINE_FUNC_ONE_PARAM(insert, QPixmapCache::Key, {}, const QPixmap&) - DEFINE_FUNC_ONE_PARAM(remove, bool, false, const QString&) - DEFINE_FUNC_ONE_PARAM(remove, bool, false, const QPixmapCache::Key&) - DEFINE_FUNC_TWO_PARAM(replace, bool, false, const QPixmapCache::Key&, const QPixmap&) - DEFINE_FUNC_ONE_PARAM(setCacheLimit, bool, false, int) - DEFINE_FUNC_NO_PARAM(markCacheMissByEviciton, bool, false) - DEFINE_FUNC_ONE_PARAM(setFastEvictionThreshold, bool, false, int) + DEFINE_FUNC_NO_PARAM(cacheLimit, int) + DEFINE_FUNC_NO_PARAM(clear, bool) + DEFINE_FUNC_TWO_PARAM(find, bool, const QString&, QPixmap*) + DEFINE_FUNC_TWO_PARAM(find, bool, const QPixmapCache::Key&, QPixmap*) + DEFINE_FUNC_TWO_PARAM(insert, bool, const QString&, const QPixmap&) + DEFINE_FUNC_ONE_PARAM(insert, QPixmapCache::Key, const QPixmap&) + DEFINE_FUNC_ONE_PARAM(remove, bool, const QString&) + DEFINE_FUNC_ONE_PARAM(remove, bool, const QPixmapCache::Key&) + DEFINE_FUNC_TWO_PARAM(replace, bool, const QPixmapCache::Key&, const QPixmap&) + DEFINE_FUNC_ONE_PARAM(setCacheLimit, bool, int) + DEFINE_FUNC_NO_PARAM(markCacheMissByEviciton, bool) + DEFINE_FUNC_ONE_PARAM(setFastEvictionThreshold, bool, int) // NOTE: Every function returns something non-void to simplify the macros. private slots: diff --git a/launcher/ResourceDownloadTask.cpp b/launcher/ResourceDownloadTask.cpp index bb44d2495..d50b3d5cf 100644 --- a/launcher/ResourceDownloadTask.cpp +++ b/launcher/ResourceDownloadTask.cpp @@ -19,52 +19,23 @@ #include "ResourceDownloadTask.h" -#include - #include "Application.h" #include "FileSystem.h" -#include "minecraft/MinecraftInstance.h" -#include "minecraft/PackProfile.h" #include "minecraft/mod/ResourceFolderModel.h" #include "minecraft/mod/ShaderPackFolderModel.h" -#include "modplatform/ModIndex.h" #include "modplatform/helpers/HashUtils.h" #include "net/ApiDownload.h" #include "net/ChecksumValidator.h" -namespace { -Net::ModrinthDownloadMeta createModrinthMeta(BaseInstance* instance, QString reason) -{ - auto* mcInstance = dynamic_cast(instance); - if (!mcInstance) { - return {}; - } - - auto* profile = mcInstance->getPackProfile(); - if (!profile) { - return {}; - } - - auto loaders = profile->getModLoadersList(); - - return { - .reason = std::move(reason), - .gameVersion = profile->getComponentVersion("net.minecraft"), - .loader = !loaders.isEmpty() ? ModPlatform::getModLoaderAsString(loaders.first()) : "", - }; -} -} // namespace - ResourceDownloadTask::ResourceDownloadTask(ModPlatform::IndexedPack::Ptr pack, ModPlatform::IndexedVersion version, ResourceFolderModel* packs, - bool isIndexed, - QString downloadReason) + bool is_indexed) : m_pack(std::move(pack)), m_pack_version(std::move(version)), m_pack_model(packs) { - if (isIndexed) { + if (is_indexed) { m_update_task.reset(new LocalResourceUpdateTask(m_pack_model->indexDir(), *m_pack, m_pack_version)); connect(m_update_task.get(), &LocalResourceUpdateTask::hasOldResource, this, &ResourceDownloadTask::hasOldResource); @@ -74,9 +45,7 @@ ResourceDownloadTask::ResourceDownloadTask(ModPlatform::IndexedPack::Ptr pack, m_filesNetJob.reset(new NetJob(tr("Resource download"), APPLICATION->network())); m_filesNetJob->setStatus(tr("Downloading resource:\n%1").arg(m_pack_version.downloadUrl)); - auto action = Net::ApiDownload::makeFile(m_pack_version.downloadUrl, m_pack_model->dir().absoluteFilePath(getFilename()), - Net::Download::Option::NoOptions, - createModrinthMeta(m_pack_model->instance(), std::move(downloadReason))); + auto action = Net::ApiDownload::makeFile(m_pack_version.downloadUrl, m_pack_model->dir().absoluteFilePath(getFilename())); if (!m_pack_version.hash_type.isEmpty() && !m_pack_version.hash.isEmpty()) { switch (Hashing::algorithmFromString(m_pack_version.hash_type)) { case Hashing::Algorithm::Md4: @@ -113,9 +82,8 @@ void ResourceDownloadTask::downloadSucceeded() auto oldName = std::get<0>(to_delete); auto oldFilename = std::get<1>(to_delete); - if (oldName.isEmpty() || oldFilename == m_pack_version.fileName) { + if (oldName.isEmpty() || oldFilename == m_pack_version.fileName) return; - } m_pack_model->uninstallResource(oldFilename, true); @@ -127,9 +95,8 @@ void ResourceDownloadTask::downloadSucceeded() if (oldConfig.exists() && !newConfig.exists()) { bool success = FS::move(oldConfig.filePath(), newConfig.filePath()); - if (!success) { + if (!success) emit logWarning(tr("Failed to rename shader config from '%1' to '%2'").arg(oldConfig.fileName(), newConfig.fileName())); - } } } } @@ -137,7 +104,7 @@ void ResourceDownloadTask::downloadSucceeded() void ResourceDownloadTask::downloadFailed(QString reason) { m_filesNetJob.reset(); - emitFailed(std::move(reason)); + emitFailed(reason); } void ResourceDownloadTask::downloadProgressChanged(qint64 current, qint64 total) @@ -147,7 +114,7 @@ void ResourceDownloadTask::downloadProgressChanged(qint64 current, qint64 total) // This indirection is done so that we don't delete a mod before being sure it was // downloaded successfully! -void ResourceDownloadTask::hasOldResource(const QString& name, const QString& filename) +void ResourceDownloadTask::hasOldResource(QString name, QString filename) { to_delete = { name, filename }; } diff --git a/launcher/ResourceDownloadTask.h b/launcher/ResourceDownloadTask.h index 84324e99a..7a04c6f1c 100644 --- a/launcher/ResourceDownloadTask.h +++ b/launcher/ResourceDownloadTask.h @@ -33,8 +33,7 @@ class ResourceDownloadTask : public SequentialTask { explicit ResourceDownloadTask(ModPlatform::IndexedPack::Ptr pack, ModPlatform::IndexedVersion version, ResourceFolderModel* packs, - bool isIndexed = true, - QString downloadReason = "standalone"); + bool is_indexed = true); const QString& getFilename() const { return m_pack_version.fileName; } const QVariant& getVersionID() const { return m_pack_version.fileId; } const ModPlatform::IndexedVersion& getVersion() const { return m_pack_version; } @@ -57,5 +56,5 @@ class ResourceDownloadTask : public SequentialTask { std::tuple to_delete{ "", "" }; private slots: - void hasOldResource(const QString& name, const QString& filename); + void hasOldResource(QString name, QString filename); }; diff --git a/launcher/java/JavaChecker.cpp b/launcher/java/JavaChecker.cpp index 3a04756fa..5c52c653d 100644 --- a/launcher/java/JavaChecker.cpp +++ b/launcher/java/JavaChecker.cpp @@ -179,20 +179,13 @@ void JavaChecker::finished(int exitcode, QProcess::ExitStatus status) void JavaChecker::error(QProcess::ProcessError err) { if (err == QProcess::FailedToStart) { - qDebug() << "Java checker has failed to start:" << process->errorString(); + qDebug() << "Java checker has failed to start."; qDebug() << "Process environment:"; qDebug() << process->environment(); qDebug() << "Native environment:"; qDebug() << QProcessEnvironment::systemEnvironment().toStringList(); killTimer.stop(); - - Result result = { - m_path, - m_id, - }; - result.errorLog = process->errorString(); - result.validity = Result::Validity::Errored; - emit checkFinished(result); + emit checkFinished({ m_path, m_id }); } emitSucceeded(); } diff --git a/launcher/java/JavaInstallList.cpp b/launcher/java/JavaInstallList.cpp index 1d7b9cdff..254d5f468 100644 --- a/launcher/java/JavaInstallList.cpp +++ b/launcher/java/JavaInstallList.cpp @@ -51,9 +51,8 @@ JavaInstallList::JavaInstallList(QObject* parent, bool onlyManagedVersions) : BaseVersionList(parent), m_only_managed_versions(onlyManagedVersions) {} -Task::Ptr JavaInstallList::getLoadTask(bool forceReload) +Task::Ptr JavaInstallList::getLoadTask() { - Q_UNUSED(forceReload) load(); return getCurrentTask(); } diff --git a/launcher/java/JavaInstallList.h b/launcher/java/JavaInstallList.h index 58d1ad8ca..c68c2a3be 100644 --- a/launcher/java/JavaInstallList.h +++ b/launcher/java/JavaInstallList.h @@ -35,7 +35,7 @@ class JavaInstallList : public BaseVersionList { public: explicit JavaInstallList(QObject* parent = 0, bool onlyManagedVersions = false); - Task::Ptr getLoadTask(bool forceReload = false) override; + Task::Ptr getLoadTask() override; bool isLoaded() override; const BaseVersion::Ptr at(int i) const override; int count() const override; diff --git a/launcher/meta/BaseEntity.cpp b/launcher/meta/BaseEntity.cpp index 1869e14d3..c809f851a 100644 --- a/launcher/meta/BaseEntity.cpp +++ b/launcher/meta/BaseEntity.cpp @@ -82,12 +82,12 @@ QUrl BaseEntity::url() const return QUrl(metaOverride).resolved(localFilename()); } -Task::Ptr BaseEntity::loadTask(Net::Mode mode, bool forceReload) +Task::Ptr BaseEntity::loadTask(Net::Mode mode) { if (m_task && m_task->isRunning()) { return m_task; } - m_task.reset(new BaseEntityLoadTask(this, mode, forceReload)); + m_task.reset(new BaseEntityLoadTask(this, mode)); return m_task; } @@ -107,9 +107,7 @@ BaseEntity::LoadStatus BaseEntity::status() const return m_load_status; } -BaseEntityLoadTask::BaseEntityLoadTask(BaseEntity* parent, Net::Mode mode, bool forceReload) - : m_entity(parent), m_mode(mode), m_force_reload(forceReload) -{} +BaseEntityLoadTask::BaseEntityLoadTask(BaseEntity* parent, Net::Mode mode) : m_entity(parent), m_mode(mode) {} void BaseEntityLoadTask::executeTask() { @@ -127,11 +125,9 @@ void BaseEntityLoadTask::executeTask() } // on online the hash needs to match - const auto& expected = m_entity->m_sha256; - const auto& actual = m_entity->m_file_sha256; - hashMatches = expected == actual; + hashMatches = m_entity->m_sha256 == m_entity->m_file_sha256; if (m_mode == Net::Mode::Online && !m_entity->m_sha256.isEmpty() && !hashMatches) { - throw Exception(QString("Checksum mismatch, expected sha256: %1, got: %2").arg(expected, actual)); + throw Exception("mismatched checksum"); } // load local file @@ -153,18 +149,13 @@ void BaseEntityLoadTask::executeTask() auto wasLoadedOffline = m_entity->m_load_status != BaseEntity::LoadStatus::NotLoaded && m_mode == Net::Mode::Offline; // if has is not present allways fetch from remote(e.g. the main index file), else only fetch if hash doesn't match auto wasLoadedRemote = m_entity->m_sha256.isEmpty() ? m_entity->m_load_status == BaseEntity::LoadStatus::Remote : hashMatches; - if (wasLoadedOffline || (wasLoadedRemote && !m_force_reload)) { + if (wasLoadedOffline || wasLoadedRemote) { emitSucceeded(); return; } m_task.reset(new NetJob(QObject::tr("Download of meta file %1").arg(m_entity->localFilename()), APPLICATION->network())); auto url = m_entity->url(); auto entry = APPLICATION->metacache()->resolveEntry("meta", m_entity->localFilename()); - if (m_force_reload) { - // clear validators so manual refreshes fetch a fresh body - entry->setETag({}); - entry->setRemoteChangedTimestamp({}); - } entry->setStale(true); auto dl = Net::ApiDownload::makeCached(url, entry); /* diff --git a/launcher/meta/BaseEntity.h b/launcher/meta/BaseEntity.h index 32d8bdbb8..17aa0cb87 100644 --- a/launcher/meta/BaseEntity.h +++ b/launcher/meta/BaseEntity.h @@ -43,7 +43,7 @@ class BaseEntity { void setSha256(QString sha256); virtual void parse(const QJsonObject& obj) = 0; - [[nodiscard]] Task::Ptr loadTask(Net::Mode loadType = Net::Mode::Online, bool forceReload = false); + [[nodiscard]] Task::Ptr loadTask(Net::Mode loadType = Net::Mode::Online); protected: QString m_sha256; // the expected sha256 @@ -58,7 +58,7 @@ class BaseEntityLoadTask : public Task { Q_OBJECT public: - explicit BaseEntityLoadTask(BaseEntity* parent, Net::Mode mode, bool forceReload); + explicit BaseEntityLoadTask(BaseEntity* parent, Net::Mode mode); ~BaseEntityLoadTask() override = default; virtual void executeTask() override; @@ -68,7 +68,6 @@ class BaseEntityLoadTask : public Task { private: BaseEntity* m_entity; Net::Mode m_mode; - bool m_force_reload = false; NetJob::Ptr m_task; }; } // namespace Meta diff --git a/launcher/meta/Index.cpp b/launcher/meta/Index.cpp index bd58215c4..d0c7075cd 100644 --- a/launcher/meta/Index.cpp +++ b/launcher/meta/Index.cpp @@ -15,7 +15,6 @@ #include "Index.h" -#include "Application.h" #include "JsonFormat.h" #include "QObjectPtr.h" #include "VersionList.h" @@ -136,7 +135,7 @@ void Index::connectVersionList(const int row, const VersionList::Ptr& list) Task::Ptr Index::loadVersion(const QString& uid, const QString& version, Net::Mode mode, bool force) { - if (mode == Net::Mode::Offline || !APPLICATION->settings()->get("MetaRefreshOnLaunch").toBool()) { + if (mode == Net::Mode::Offline) { return get(uid, version)->loadTask(mode); } diff --git a/launcher/meta/VersionList.cpp b/launcher/meta/VersionList.cpp index fa3a271a6..dfca52d87 100644 --- a/launcher/meta/VersionList.cpp +++ b/launcher/meta/VersionList.cpp @@ -32,11 +32,11 @@ VersionList::VersionList(const QString& uid, QObject* parent) : BaseVersionList( setObjectName("Version list: " + uid); } -Task::Ptr VersionList::getLoadTask(bool forceReload) +Task::Ptr VersionList::getLoadTask() { auto loadTask = makeShared(tr("Load meta for %1", "This is for the task name that loads the meta index.").arg(m_uid)); - loadTask->addTask(APPLICATION->metadataIndex()->loadTask(Net::Mode::Online, forceReload)); - loadTask->addTask(this->loadTask(Net::Mode::Online, forceReload)); + loadTask->addTask(APPLICATION->metadataIndex()->loadTask(Net::Mode::Online)); + loadTask->addTask(this->loadTask(Net::Mode::Online)); return loadTask; } diff --git a/launcher/meta/VersionList.h b/launcher/meta/VersionList.h index 709c361de..18681b8ed 100644 --- a/launcher/meta/VersionList.h +++ b/launcher/meta/VersionList.h @@ -37,7 +37,7 @@ class VersionList : public BaseVersionList, public BaseEntity { enum Roles { UidRole = Qt::UserRole + 100, TimeRole, RequiresRole, VersionPtrRole }; bool isLoaded() override; - Task::Ptr getLoadTask(bool forceReload = false) override; + Task::Ptr getLoadTask() override; const BaseVersion::Ptr at(int i) const override; int count() const override; void sortVersions() override; diff --git a/launcher/minecraft/Library.cpp b/launcher/minecraft/Library.cpp index 2b43d4389..026f9c281 100644 --- a/launcher/minecraft/Library.cpp +++ b/launcher/minecraft/Library.cpp @@ -149,7 +149,7 @@ QList Library::getDownloads(const RuntimeContext& runtimeC if (sha1.size()) { auto dl = Net::ApiDownload::makeCached(url, entry, options); dl->addValidator(new Net::ChecksumValidator(QCryptographicHash::Sha1, sha1)); - qDebug() << "Checksummed Download for:" << rawName().serialize() << "storage:" << storage << "url:" << url << "expected sha1:" << sha1; + qDebug() << "Checksummed Download for:" << rawName().serialize() << "storage:" << storage << "url:" << url; out.append(dl); } else { out.append(Net::ApiDownload::makeCached(url, entry, options)); diff --git a/launcher/minecraft/MinecraftInstance.cpp b/launcher/minecraft/MinecraftInstance.cpp index 8e98a2efe..e8fc642fa 100644 --- a/launcher/minecraft/MinecraftInstance.cpp +++ b/launcher/minecraft/MinecraftInstance.cpp @@ -131,8 +131,7 @@ for (const auto& gpu : gpus) { QString name = qvariant_cast(gpu[QStringLiteral("Name")]); bool defaultGpu = qvariant_cast(gpu[QStringLiteral("Default")]); - bool discrete = qvariant_cast(gpu.value(QStringLiteral("Discrete"), !defaultGpu)); - if (discrete) { + if (!defaultGpu) { QStringList envList = qvariant_cast(gpu[QStringLiteral("Environment")]); for (int i = 0; i + 1 < envList.size(); i += 2) { env.insert(envList[i], envList[i + 1]); @@ -893,14 +892,6 @@ QStringList MinecraftInstance::verboseDescription(AuthSessionPtr session, Minecr QStringList out; - out << "Components:"; - for (int i = 0; i < m_components->rowCount(); ++i) { - const auto& component = m_components->getComponent(i); - out << indent + - QString("%1) %2 (%3) %4").arg(QString::number(i + 1), component->getName(), component->getID(), component->getVersion()); - } - out << emptyLine; - out << "Launcher: " + getLauncher(); out << "Main class: " + getMainClass() << emptyLine; diff --git a/launcher/minecraft/VanillaInstanceCreationTask.cpp b/launcher/minecraft/VanillaInstanceCreationTask.cpp index e646e2c52..017f85027 100644 --- a/launcher/minecraft/VanillaInstanceCreationTask.cpp +++ b/launcher/minecraft/VanillaInstanceCreationTask.cpp @@ -7,27 +7,30 @@ #include "minecraft/PackProfile.h" #include "settings/INISettingsObject.h" -VanillaCreationTask::VanillaCreationTask(BaseVersion::Ptr version, QString loader, BaseVersion::Ptr loaderVersion) - : m_version(std::move(version)), m_using_loader(true), m_loader(std::move(loader)), m_loader_version(std::move(loaderVersion)) +VanillaCreationTask::VanillaCreationTask(BaseVersion::Ptr version, QString loader, BaseVersion::Ptr loader_version) + : InstanceCreationTask() + , m_version(std::move(version)) + , m_using_loader(true) + , m_loader(std::move(loader)) + , m_loader_version(std::move(loader_version)) {} std::unique_ptr VanillaCreationTask::createInstance() { setStatus(tr("Creating instance from version %1").arg(m_version->name())); - auto inst = std::make_unique( - m_globalSettings, std::make_unique(FS::PathCombine(m_stagingPath, "instance.cfg")), m_stagingPath); + auto inst = std::make_unique(m_globalSettings, std::make_unique(FS::PathCombine(m_stagingPath, "instance.cfg")), + m_stagingPath); SettingsObject::Lock lock(inst->settings()); - auto* components = inst->getPackProfile(); + auto components = inst->getPackProfile(); components->buildingFromScratch(); components->setComponentVersion("net.minecraft", m_version->descriptor(), true); - if (m_using_loader) { + if (m_using_loader) components->setComponentVersion(m_loader, m_loader_version->descriptor()); - } inst->setName(name()); inst->setIconKey(m_instIcon); - components->saveNow(); + return inst; } diff --git a/launcher/minecraft/VanillaInstanceCreationTask.h b/launcher/minecraft/VanillaInstanceCreationTask.h index c1a69ab62..7015a4fe5 100644 --- a/launcher/minecraft/VanillaInstanceCreationTask.h +++ b/launcher/minecraft/VanillaInstanceCreationTask.h @@ -7,8 +7,8 @@ class VanillaCreationTask final : public InstanceCreationTask { Q_OBJECT public: - explicit VanillaCreationTask(BaseVersion::Ptr version) : m_version(std::move(version)) {} - VanillaCreationTask(BaseVersion::Ptr version, QString loader, BaseVersion::Ptr loaderVersion); + VanillaCreationTask(BaseVersion::Ptr version) : InstanceCreationTask(), m_version(std::move(version)) {} + VanillaCreationTask(BaseVersion::Ptr version, QString loader, BaseVersion::Ptr loader_version); std::unique_ptr createInstance() override; diff --git a/launcher/minecraft/WorldList.cpp b/launcher/minecraft/WorldList.cpp index ca8ac1aa8..4aa0f7532 100644 --- a/launcher/minecraft/WorldList.cpp +++ b/launcher/minecraft/WorldList.cpp @@ -157,8 +157,7 @@ bool WorldList::resetIcon(int row) return false; World& m = m_worlds[row]; if (m.resetIcon()) { - QModelIndex modelIndex = index(row, NameColumn); - emit dataChanged(modelIndex, modelIndex, { WorldList::IconFileRole }); + emit dataChanged(index(row), index(row), { WorldList::IconFileRole }); return true; } return false; @@ -427,7 +426,7 @@ void WorldList::loadWorldsAsync() m_worlds[row].setSize(size); // Notify views - QModelIndex modelIndex = index(row, SizeColumn); + QModelIndex modelIndex = index(row); emit dataChanged(modelIndex, modelIndex, { SizeRole }); } }, diff --git a/launcher/minecraft/auth/AccountData.h b/launcher/minecraft/auth/AccountData.h index 96ef94f30..5fbe3213b 100644 --- a/launcher/minecraft/auth/AccountData.h +++ b/launcher/minecraft/auth/AccountData.h @@ -41,7 +41,6 @@ #include #include -#include #include enum class Validity { None, Assumed, Certain }; @@ -119,6 +118,5 @@ struct AccountData { // runtime only information (not saved with the account) QString internalId; QString errorString; - QNetworkReply::NetworkError networkError = QNetworkReply::NoError; AccountState accountState = AccountState::Unchecked; }; diff --git a/launcher/minecraft/auth/AccountList.cpp b/launcher/minecraft/auth/AccountList.cpp index 418ba98d2..ac27b6bbc 100644 --- a/launcher/minecraft/auth/AccountList.cpp +++ b/launcher/minecraft/auth/AccountList.cpp @@ -648,17 +648,9 @@ void AccountList::tryNext() while (m_refreshQueue.length()) { auto accountId = m_refreshQueue.front(); m_refreshQueue.pop_front(); - bool found = false; for (int i = 0; i < count(); i++) { auto account = at(i); if (account->internalId() == accountId) { - found = true; - if (!account->shouldRefresh()) { - // Account no longer needs refreshing, skip it. - qDebug() << "RefreshSchedule: Skipping account" << account->profileName() << "with internal ID" - << accountId << "(no longer needs refresh)"; - break; - } m_currentTask = account->refresh(); if (m_currentTask) { connect(m_currentTask.get(), &Task::succeeded, this, &AccountList::authSucceeded); @@ -668,12 +660,9 @@ void AccountList::tryNext() << accountId; return; } - break; } } - if (!found) { - qDebug() << "RefreshSchedule: Account with internal ID" << accountId << "not found."; - } + qDebug() << "RefreshSchedule: Account with internal ID" << accountId << "not found."; } // if we get here, no account needed refreshing. Schedule refresh in an hour. m_refreshTimer->start(1000 * 3600); diff --git a/launcher/minecraft/auth/steps/LauncherLoginStep.cpp b/launcher/minecraft/auth/steps/LauncherLoginStep.cpp index 4ceed8586..89293c22e 100644 --- a/launcher/minecraft/auth/steps/LauncherLoginStep.cpp +++ b/launcher/minecraft/auth/steps/LauncherLoginStep.cpp @@ -56,11 +56,10 @@ void LauncherLoginStep::onRequestDone(QByteArray* response) qCDebug(authCredentials()) << *response; if (m_request->error() != QNetworkReply::NoError) { qWarning() << "Reply error:" << m_request->error(); - if (Net::isApplicationError(m_request->error()) && !Net::isServerError(m_request->error())) { + if (Net::isApplicationError(m_request->error())) { emit finished(AccountTaskState::STATE_FAILED_SOFT, tr("Failed to get Minecraft access token: %1").arg(m_request->errorString())); } else { - m_data->networkError = m_request->error(); emit finished(AccountTaskState::STATE_OFFLINE, tr("Failed to get Minecraft access token: %1").arg(m_request->errorString())); } return; diff --git a/launcher/minecraft/auth/steps/MSADeviceCodeStep.cpp b/launcher/minecraft/auth/steps/MSADeviceCodeStep.cpp index 78762a32a..3feb6852c 100644 --- a/launcher/minecraft/auth/steps/MSADeviceCodeStep.cpp +++ b/launcher/minecraft/auth/steps/MSADeviceCodeStep.cpp @@ -113,12 +113,6 @@ DeviceAuthorizationResponse parseDeviceAuthorizationResponse(const QByteArray& d void MSADeviceCodeStep::deviceAuthorizationFinished(QByteArray* response) { - if (!m_request->wasSuccessful() || m_request->error() != QNetworkReply::NoError) { - qWarning() << "Device authorization failed:" << m_request->error() << m_request->errorString(); - emit finished(AccountTaskState::STATE_FAILED_HARD, tr("Device authorization failed: %1").arg(m_request->errorString())); - return; - } - auto rsp = parseDeviceAuthorizationResponse(*response); if (!rsp.error.isEmpty() || !rsp.error_description.isEmpty()) { qWarning() << "Device authorization failed:" << rsp.error; @@ -126,6 +120,12 @@ void MSADeviceCodeStep::deviceAuthorizationFinished(QByteArray* response) tr("Device authorization failed: %1").arg(rsp.error_description.isEmpty() ? rsp.error : rsp.error_description)); return; } + if (!m_request->wasSuccessful() || m_request->error() != QNetworkReply::NoError) { + qWarning() << "Device authorization failed:" << *response; + emit finished(AccountTaskState::STATE_FAILED_HARD, tr("Failed to retrieve device authorization")); + return; + } + if (rsp.device_code.isEmpty() || rsp.user_code.isEmpty() || rsp.verification_uri.isEmpty() || rsp.expires_in == 0) { qWarning() << "Device authorization failed: required fields missing"; emit finished(AccountTaskState::STATE_FAILED_HARD, tr("Device authorization failed: required fields missing")); diff --git a/launcher/minecraft/auth/steps/MinecraftProfileStep.cpp b/launcher/minecraft/auth/steps/MinecraftProfileStep.cpp index b95682b2b..418c46a0e 100644 --- a/launcher/minecraft/auth/steps/MinecraftProfileStep.cpp +++ b/launcher/minecraft/auth/steps/MinecraftProfileStep.cpp @@ -52,11 +52,10 @@ void MinecraftProfileStep::onRequestDone(QByteArray* response) qWarning() << " Response:"; qWarning() << QString::fromUtf8(*response); - if (Net::isApplicationError(m_request->error()) && !Net::isServerError(m_request->error())) { + if (Net::isApplicationError(m_request->error())) { emit finished(AccountTaskState::STATE_FAILED_SOFT, tr("Minecraft Java profile acquisition failed: %1").arg(m_request->errorString())); } else { - m_data->networkError = m_request->error(); emit finished(AccountTaskState::STATE_OFFLINE, tr("Minecraft Java profile acquisition failed: %1").arg(m_request->errorString())); } diff --git a/launcher/minecraft/auth/steps/XboxAuthorizationStep.cpp b/launcher/minecraft/auth/steps/XboxAuthorizationStep.cpp index 422aa1a54..9e101d42a 100644 --- a/launcher/minecraft/auth/steps/XboxAuthorizationStep.cpp +++ b/launcher/minecraft/auth/steps/XboxAuthorizationStep.cpp @@ -2,7 +2,7 @@ #include #include -#include +#include #include "Application.h" #include "Logging.h" @@ -12,7 +12,7 @@ #include "net/Upload.h" XboxAuthorizationStep::XboxAuthorizationStep(AccountData* data, Token* token, QString relyingParty, QString authorizationKind) - : AuthStep(data), m_token(token), m_relyingParty(std::move(relyingParty)), m_authorizationKind(std::move(authorizationKind)) + : AuthStep(data), m_token(token), m_relyingParty(relyingParty), m_authorizationKind(authorizationKind) {} QString XboxAuthorizationStep::describe() @@ -22,7 +22,7 @@ QString XboxAuthorizationStep::describe() void XboxAuthorizationStep::perform() { - const QString xboxAuthTemplate = R"XXX( + QString xbox_auth_template = R"XXX( { "Properties": { "SandboxId": "RETAIL", @@ -34,13 +34,15 @@ void XboxAuthorizationStep::perform() "TokenType": "JWT" } )XXX"; - const auto xboxAuthData = xboxAuthTemplate.arg(m_data->userToken.token, m_relyingParty); + auto xbox_auth_data = xbox_auth_template.arg(m_data->userToken.token, m_relyingParty); // http://xboxlive.com - const QUrl url("https://xsts.auth.xboxlive.com/xsts/authorize"); - auto headers = QList{ { .headerName = "Content-Type", .headerValue = "application/json" }, - { .headerName = "Accept", .headerValue = "application/json" }, - { .headerName = "x-xbl-contract-version", .headerValue = "1" } }; - auto [request, response] = Net::Upload::makeByteArray(url, xboxAuthData.toUtf8()); + QUrl url("https://xsts.auth.xboxlive.com/xsts/authorize"); + auto headers = QList{ + { "Content-Type", "application/json" }, + { "Accept", "application/json" }, + { "x-xbl-contract-version", "1" } + }; + auto [request, response] = Net::Upload::makeByteArray(url, xbox_auth_data.toUtf8()); m_request = request; m_request->addHeaderProxy(std::make_unique(headers)); m_request->enableAutoRetry(true); @@ -60,14 +62,15 @@ void XboxAuthorizationStep::onRequestDone(QByteArray* response) qCDebug(authCredentials()) << *response; if (m_request->error() != QNetworkReply::NoError) { qWarning() << "Reply error:" << m_request->error(); - if (Net::isApplicationError(m_request->error()) && !Net::isServerError(m_request->error())) { - if (processSTSError(*response)) { - return; + if (Net::isApplicationError(m_request->error())) { + if (!processSTSError(*response)) { + emit finished(AccountTaskState::STATE_FAILED_SOFT, + tr("Failed to get authorization for %1 services. Error %2.").arg(m_authorizationKind, m_request->error())); + } else { + emit finished(AccountTaskState::STATE_FAILED_SOFT, + tr("Unknown STS error for %1 services: %2").arg(m_authorizationKind, m_request->errorString())); } - emit finished(AccountTaskState::STATE_FAILED_SOFT, - tr("Unknown STS error for %1 services: %2").arg(m_authorizationKind, m_request->errorString())); } else { - m_data->networkError = m_request->error(); emit finished(AccountTaskState::STATE_OFFLINE, tr("Failed to get authorization for %1 services: %2").arg(m_authorizationKind, m_request->errorString())); } @@ -96,8 +99,8 @@ bool XboxAuthorizationStep::processSTSError(const QByteArray& response) { if (m_request->error() == QNetworkReply::AuthenticationRequiredError) { QJsonParseError jsonError; - const QJsonDocument doc = QJsonDocument::fromJson(response, &jsonError); - if (jsonError.error != QJsonParseError::NoError) { + QJsonDocument doc = QJsonDocument::fromJson(response, &jsonError); + if (jsonError.error) { qWarning() << "Cannot parse error XSTS response as JSON:" << jsonError.errorString(); emit finished(AccountTaskState::STATE_FAILED_SOFT, tr("Cannot parse %1 authorization error response as JSON: %2").arg(m_authorizationKind, jsonError.errorString())); diff --git a/launcher/minecraft/auth/steps/XboxUserStep.cpp b/launcher/minecraft/auth/steps/XboxUserStep.cpp index 382750218..97544d09b 100644 --- a/launcher/minecraft/auth/steps/XboxUserStep.cpp +++ b/launcher/minecraft/auth/steps/XboxUserStep.cpp @@ -56,10 +56,9 @@ void XboxUserStep::onRequestDone(QByteArray* response) { if (m_request->error() != QNetworkReply::NoError) { qWarning() << "Reply error:" << m_request->error(); - if (Net::isApplicationError(m_request->error()) && !Net::isServerError(m_request->error())) { + if (Net::isApplicationError(m_request->error())) { emit finished(AccountTaskState::STATE_FAILED_SOFT, tr("Xbox user authentication failed: %1").arg(m_request->errorString())); } else { - m_data->networkError = m_request->error(); emit finished(AccountTaskState::STATE_OFFLINE, tr("Xbox user authentication failed: %1").arg(m_request->errorString())); } return; diff --git a/launcher/minecraft/launch/EnsureAvailableMemory.cpp b/launcher/minecraft/launch/EnsureAvailableMemory.cpp index 0f349674a..a0e156770 100644 --- a/launcher/minecraft/launch/EnsureAvailableMemory.cpp +++ b/launcher/minecraft/launch/EnsureAvailableMemory.cpp @@ -25,72 +25,22 @@ EnsureAvailableMemory::EnsureAvailableMemory(LaunchTask* parent, MinecraftInstan void EnsureAvailableMemory::executeTask() { -#ifdef Q_OS_MACOS - QString text; - switch (MacOSHardwareInfo::memoryPressureLevel()) { - case MacOSHardwareInfo::MemoryPressureLevel::Normal: - emitSucceeded(); - return; - case MacOSHardwareInfo::MemoryPressureLevel::Warning: - text = - tr("The system is under increased memory pressure.\n" - "This may lead to lag or slowdowns.\n" - "If possible, close other applications before continuing.\n\n" - "Launch anyway?"); - break; - case MacOSHardwareInfo::MemoryPressureLevel::Critical: - text = - tr("Your system is under critical memory pressure.\n" - "This may lead to severe slowdowns, crashes or system instability.\n" - "It is recommended to close other applications or restart your system.\n\n" - "Launch anyway?"); - break; - } - - bool shouldAbort = false; - - if (m_instance->settings()->get("LowMemWarning").toBool()) { - auto* dialog = CustomMessageBox::selectable(nullptr, tr("High memory pressure"), text, QMessageBox::Icon::Warning, - QMessageBox::StandardButton::Yes | QMessageBox::StandardButton::No, - QMessageBox::StandardButton::No); - - shouldAbort = dialog->exec() == QMessageBox::No; - dialog->deleteLater(); - } - - const auto message = tr("The system is under high memory pressure"); - if (shouldAbort) { - emit logLine(message, MessageLevel::Fatal); - emitFailed(message); - return; - } - - emit logLine(message, MessageLevel::Warning); - emitSucceeded(); -#else const uint64_t available = HardwareInfo::availableRamMiB(); - if (available == 0) { - // could not read - emitSucceeded(); - return; - } + const uint64_t min = m_instance->settings()->get("MinMemAlloc").toUInt(); + const uint64_t max = m_instance->settings()->get("MaxMemAlloc").toUInt(); + const uint64_t required = std::max(min, max); - const uint64_t settingMin = m_instance->settings()->get("MinMemAlloc").toUInt(); - const uint64_t settingMax = m_instance->settings()->get("MaxMemAlloc").toUInt(); - const uint64_t max = std::max(settingMin, settingMax); - - if (static_cast(max) * 0.9 > static_cast(available)) { + if (static_cast(required) * 0.9 > static_cast(available)) { bool shouldAbort = false; if (m_instance->settings()->get("LowMemWarning").toBool()) { auto* dialog = CustomMessageBox::selectable( - nullptr, tr("Low free memory"), - tr("There might not be enough free RAM to launch this instance with the current memory settings.\n\n" - "Maximum allocated: %1 MiB\nFree: %2 MiB (out of %3 MiB total)\n\n" - "Launch anyway? This may cause slowdowns in the game and your system.") - .arg(max) - .arg(available) - .arg(HardwareInfo::totalRamMiB()), + nullptr, tr("Not enough RAM"), + tr("There is not enough RAM available to launch this instance with the current memory settings.\n\n" + "Required: %1 MiB\nAvailable: %2 MiB\n\n" + "Continue anyway? This may cause slowdowns in the game and your system.") + .arg(required) + .arg(available), QMessageBox::Icon::Warning, QMessageBox::StandardButton::Yes | QMessageBox::StandardButton::No, QMessageBox::StandardButton::No); @@ -109,5 +59,4 @@ void EnsureAvailableMemory::executeTask() } emitSucceeded(); -#endif } diff --git a/launcher/minecraft/launch/LauncherPartLaunch.cpp b/launcher/minecraft/launch/LauncherPartLaunch.cpp index e4d3ec1ef..a2c400e75 100644 --- a/launcher/minecraft/launch/LauncherPartLaunch.cpp +++ b/launcher/minecraft/launch/LauncherPartLaunch.cpp @@ -164,9 +164,9 @@ void LauncherPartLaunch::on_state(LoggedProcess::State state) switch (state) { case LoggedProcess::FailedToStart: { //: Error message displayed if instace can't start - const char* reason = QT_TR_NOOP("Could not launch Minecraft: %1"); - emit logLine(QString(reason).arg(m_process.errorString()), MessageLevel::Fatal); - emitFailed(tr(reason).arg(m_process.errorString())); + const char* reason = QT_TR_NOOP("Could not launch Minecraft!"); + emit logLine(reason, MessageLevel::Fatal); + emitFailed(tr(reason)); return; } case LoggedProcess::Aborted: diff --git a/launcher/minecraft/launch/PrintInstanceInfo.cpp b/launcher/minecraft/launch/PrintInstanceInfo.cpp index df8c28c7b..7bfe73746 100644 --- a/launcher/minecraft/launch/PrintInstanceInfo.cpp +++ b/launcher/minecraft/launch/PrintInstanceInfo.cpp @@ -68,12 +68,7 @@ void PrintInstanceInfo::executeTask() ::runPciconf(log); #else log << "CPU: " + HardwareInfo::cpuInfo(); -#ifdef Q_OS_MACOS - log << "Memory pressure level: " + MacOSHardwareInfo::memoryPressureLevelName(); -#else log << QString("RAM: %1 MiB (available: %2 MiB)").arg(HardwareInfo::totalRamMiB()).arg(HardwareInfo::availableRamMiB()); -#endif - #endif log.append(HardwareInfo::gpuInfo()); log << ""; diff --git a/launcher/minecraft/mod/DataPack.cpp b/launcher/minecraft/mod/DataPack.cpp index c2b477d45..140596a29 100644 --- a/launcher/minecraft/mod/DataPack.cpp +++ b/launcher/minecraft/mod/DataPack.cpp @@ -216,7 +216,7 @@ static std::pair map(int format, const QMap(other); - if (type == SortType::PackFormat) { + if (type == SortType::PACK_FORMAT) { auto this_ver = packFormat(); auto other_ver = cast_other.packFormat(); diff --git a/launcher/minecraft/mod/DataPackFolderModel.cpp b/launcher/minecraft/mod/DataPackFolderModel.cpp index 350ae60e1..f1497b809 100644 --- a/launcher/minecraft/mod/DataPackFolderModel.cpp +++ b/launcher/minecraft/mod/DataPackFolderModel.cpp @@ -40,26 +40,25 @@ #include #include +#include "Version.h" + #include "minecraft/mod/tasks/LocalDataPackParseTask.h" -DataPackFolderModel::DataPackFolderModel(const QString& dir, BaseInstance* instance, bool isIndexed, bool createDir, QObject* parent) - : ResourceFolderModel(QDir(dir), instance, isIndexed, createDir, parent) +DataPackFolderModel::DataPackFolderModel(const QString& dir, BaseInstance* instance, bool is_indexed, bool create_dir, QObject* parent) + : ResourceFolderModel(QDir(dir), instance, is_indexed, create_dir, parent) { - m_columnNames = QStringList({ "Enable", "Image", "Name", "Pack Format", "Last Modified", "Size", "File Name" }); - m_columnNamesTranslated = - QStringList({ tr("Enable"), tr("Image"), tr("Name"), tr("Pack Format"), tr("Last Modified"), tr("Size"), tr("File Name") }); - m_columnSortKeys = { SortType::Enabled, SortType::Name, SortType::Name, SortType::PackFormat, - SortType::Date, SortType::Size, SortType::Filename }; - m_columnResizeModes = { QHeaderView::Interactive, QHeaderView::Interactive, QHeaderView::Stretch, QHeaderView::Interactive, - QHeaderView::Interactive, QHeaderView::Interactive, QHeaderView::Interactive }; - m_columnsHideable = { false, true, false, true, true, true, true }; + m_column_names = QStringList({ "Enable", "Image", "Name", "Pack Format", "Last Modified" }); + m_column_names_translated = QStringList({ tr("Enable"), tr("Image"), tr("Name"), tr("Pack Format"), tr("Last Modified") }); + m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::NAME, SortType::PACK_FORMAT, SortType::DATE }; + m_column_resize_modes = { QHeaderView::Interactive, QHeaderView::Interactive, QHeaderView::Stretch, QHeaderView::Interactive, + QHeaderView::Interactive }; + m_columnsHideable = { false, true, false, true, true }; } QVariant DataPackFolderModel::data(const QModelIndex& index, int role) const { - if (!validateIndex(index)) { + if (!validateIndex(index)) return {}; - } int row = index.row(); int column = index.column(); @@ -68,13 +67,11 @@ QVariant DataPackFolderModel::data(const QModelIndex& index, int role) const case Qt::BackgroundRole: return rowBackground(row); case Qt::DisplayRole: - if (column == PackFormatColumn) { - const auto& resource = at(row); - return resource.packFormatStr(); - } - if (column == SizeColumn) { - const auto& resource = at(row); - return resource.sizeStr(); + switch (column) { + case PackFormatColumn: { + const auto& resource = at(row); + return resource.packFormatStr(); + } } break; case Qt::DecorationRole: { @@ -95,8 +92,6 @@ QVariant DataPackFolderModel::data(const QModelIndex& index, int role) const return QSize(32, 32); } break; - default: - break; } // map the columns to the base equivilents @@ -114,14 +109,7 @@ QVariant DataPackFolderModel::data(const QModelIndex& index, int role) const case ProviderColumn: mappedIndex = index.siblingAtColumn(ResourceFolderModel::ProviderColumn); break; - case FileNameColumn: - mappedIndex = index.siblingAtColumn(ResourceFolderModel::FileNameColumn); - break; - case SizeColumn: - mappedIndex = index.siblingAtColumn(ResourceFolderModel::SizeColumn); - break; - default: - break; + // FIXME: there is no size column due to an oversight } if (mappedIndex.isValid()) { @@ -141,8 +129,6 @@ QVariant DataPackFolderModel::headerData(int section, [[maybe_unused]] Qt::Orien case PackFormatColumn: case DateColumn: case ImageColumn: - case SizeColumn: - case FileNameColumn: return columnNames().at(section); default: return {}; @@ -159,10 +145,6 @@ QVariant DataPackFolderModel::headerData(int section, [[maybe_unused]] Qt::Orien return tr("The data pack format ID, as well as the Minecraft versions it was designed for."); case DateColumn: return tr("The date and time this data pack was last changed (or added)."); - case SizeColumn: - return tr("The size of the data pack."); - case FileNameColumn: - return tr("The file name of the data pack."); default: return {}; } @@ -178,7 +160,7 @@ QVariant DataPackFolderModel::headerData(int section, [[maybe_unused]] Qt::Orien int DataPackFolderModel::columnCount(const QModelIndex& parent) const { - return parent.isValid() ? 0 : NumColumns; + return parent.isValid() ? 0 : NUM_COLUMNS; } Resource* DataPackFolderModel::createResource(const QFileInfo& file) @@ -188,5 +170,5 @@ Resource* DataPackFolderModel::createResource(const QFileInfo& file) Task* DataPackFolderModel::createParseTask(Resource& resource) { - return new LocalDataPackParseTask(m_nextResolutionTicket, static_cast(&resource)); + return new LocalDataPackParseTask(m_next_resolution_ticket, static_cast(&resource)); } diff --git a/launcher/minecraft/mod/DataPackFolderModel.h b/launcher/minecraft/mod/DataPackFolderModel.h index 24133354a..2b90e1a2a 100644 --- a/launcher/minecraft/mod/DataPackFolderModel.h +++ b/launcher/minecraft/mod/DataPackFolderModel.h @@ -39,24 +39,16 @@ #include "ResourceFolderModel.h" #include "DataPack.h" +#include "ResourcePack.h" class DataPackFolderModel : public ResourceFolderModel { Q_OBJECT public: - enum Columns : std::uint8_t { - ActiveColumn = 0, - ImageColumn, - NameColumn, - PackFormatColumn, - DateColumn, - SizeColumn, - FileNameColumn, - NumColumns - }; + enum Columns { ActiveColumn = 0, ImageColumn, NameColumn, PackFormatColumn, DateColumn, NUM_COLUMNS }; - explicit DataPackFolderModel(const QString& dir, BaseInstance* instance, bool isIndexed, bool createDir, QObject* parent = nullptr); + explicit DataPackFolderModel(const QString& dir, BaseInstance* instance, bool is_indexed, bool create_dir, QObject* parent = nullptr); - QString id() const override { return "datapacks"; } + virtual QString id() const override { return "datapacks"; } QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; @@ -64,7 +56,7 @@ class DataPackFolderModel : public ResourceFolderModel { int columnCount(const QModelIndex& parent) const override; [[nodiscard]] Resource* createResource(const QFileInfo& file) override; - [[nodiscard]] Task* createParseTask(Resource& /*unused*/) override; + [[nodiscard]] Task* createParseTask(Resource&) override; RESOURCE_HELPERS(DataPack) }; diff --git a/launcher/minecraft/mod/Mod.cpp b/launcher/minecraft/mod/Mod.cpp index f0cdfaff6..661192d67 100644 --- a/launcher/minecraft/mod/Mod.cpp +++ b/launcher/minecraft/mod/Mod.cpp @@ -40,7 +40,6 @@ #include #include #include -#include #include "MTPixmapCache.h" #include "MetadataHandler.h" @@ -50,34 +49,6 @@ #include "minecraft/mod/tasks/LocalModParseTask.h" #include "modplatform/ModIndex.h" -namespace { - -int compareVersionLists(const QStringList& leftVersions, const QStringList& rightVersions) -{ - const qsizetype commonSize = std::min(leftVersions.size(), rightVersions.size()); - - for (qsizetype i = 0; i < commonSize; i++) { - const auto leftVersion = Version(leftVersions.at(i).trimmed()); - const auto rightVersion = Version(rightVersions.at(i).trimmed()); - - if (leftVersion > rightVersion) - return 1; - - if (leftVersion < rightVersion) - return -1; - } - - if (leftVersions.size() > rightVersions.size()) - return 1; - - if (leftVersions.size() < rightVersions.size()) - return -1; - - return 0; -} - -} // namespace - Mod::Mod(const QFileInfo& file) : Resource(file), m_local_details() { m_enabled = (file.suffix() != "disabled"); @@ -90,18 +61,18 @@ void Mod::setDetails(const ModDetails& details) int Mod::compare(const Resource& other, SortType type) const { - auto cast_other = dynamic_cast(&other); + auto cast_other = dynamic_cast(&other); if (!cast_other) return Resource::compare(other, type); switch (type) { default: - case SortType::Enabled: - case SortType::Name: - case SortType::Date: - case SortType::Size: + case SortType::ENABLED: + case SortType::NAME: + case SortType::DATE: + case SortType::SIZE: return Resource::compare(other, type); - case SortType::Version: { + case SortType::VERSION: { auto this_ver = Version(version()); auto other_ver = Version(cast_other->version()); if (this_ver > other_ver) @@ -110,38 +81,38 @@ int Mod::compare(const Resource& other, SortType type) const return -1; break; } - case SortType::Side: { + case SortType::SIDE: { auto compare_result = QString::compare(side(), cast_other->side(), Qt::CaseInsensitive); if (compare_result != 0) return compare_result; break; } - case SortType::McVersions: { - auto compare_result = compareVersionLists(mcVersions(), cast_other->mcVersions()); + case SortType::MC_VERSIONS: { + auto compare_result = QString::compare(mcVersions(), cast_other->mcVersions(), Qt::CaseInsensitive); if (compare_result != 0) return compare_result; break; } - case SortType::Loaders: { + case SortType::LOADERS: { auto compare_result = QString::compare(loaders(), cast_other->loaders(), Qt::CaseInsensitive); if (compare_result != 0) return compare_result; break; } - case SortType::ReleaseType: { + case SortType::RELEASE_TYPE: { auto compare_result = QString::compare(releaseType(), cast_other->releaseType(), Qt::CaseInsensitive); if (compare_result != 0) return compare_result; break; } - case SortType::RequiredBy: { + case SortType::REQUIRED_BY: { if (requiredByCount() > cast_other->requiredByCount()) return 1; if (requiredByCount() < cast_other->requiredByCount()) return -1; break; } - case SortType::Requires: { + case SortType::REQUIRES: { if (requiresCount() > cast_other->requiresCount()) return 1; if (requiresCount() < cast_other->requiresCount()) @@ -226,19 +197,14 @@ auto Mod::side() const -> QString return ModPlatform::SideUtils::toString(ModPlatform::Side::UniversalSide); } -auto Mod::mcVersions() const -> QStringList +auto Mod::mcVersions() const -> QString { if (metadata()) - return metadata()->mcVersions; + return metadata()->mcVersions.join(", "); return {}; } -auto Mod::mcVersionsString() const -> QString -{ - return mcVersions().join(", "); -} - auto Mod::releaseType() const -> QString { if (metadata()) diff --git a/launcher/minecraft/mod/Mod.h b/launcher/minecraft/mod/Mod.h index 27768ae2c..0d24409bf 100644 --- a/launcher/minecraft/mod/Mod.h +++ b/launcher/minecraft/mod/Mod.h @@ -68,8 +68,7 @@ class Mod : public Resource { auto issueTracker() const -> QString; auto side() const -> QString; auto loaders() const -> QString; - auto mcVersions() const -> QStringList; - auto mcVersionsString() const -> QString; + auto mcVersions() const -> QString; auto releaseType() const -> QString; QStringList dependencies() const; diff --git a/launcher/minecraft/mod/ModFolderModel.cpp b/launcher/minecraft/mod/ModFolderModel.cpp index a03410fd3..4d54be921 100644 --- a/launcher/minecraft/mod/ModFolderModel.cpp +++ b/launcher/minecraft/mod/ModFolderModel.cpp @@ -51,39 +51,38 @@ #include #include #include -#include +#include "minecraft/Component.h" #include "minecraft/mod/Resource.h" #include "minecraft/mod/ResourceFolderModel.h" #include "minecraft/mod/tasks/LocalModParseTask.h" #include "modplatform/ModIndex.h" #include "ui/dialogs/CustomMessageBox.h" -ModFolderModel::ModFolderModel(const QDir& dir, BaseInstance* instance, bool isIndexed, bool createDir, QObject* parent) - : ResourceFolderModel(QDir(dir), instance, isIndexed, createDir, parent) +ModFolderModel::ModFolderModel(const QDir& dir, BaseInstance* instance, bool is_indexed, bool create_dir, QObject* parent) + : ResourceFolderModel(QDir(dir), instance, is_indexed, create_dir, parent) { - m_columnNames = QStringList({ "Enable", "Image", "Name", "Version", "Last Modified", "Provider", "Size", "Side", "Loaders", - "Minecraft Versions", "Release Type", "Requires", "Required By", "File Name" }); - m_columnNamesTranslated = + m_column_names = QStringList({ "Enable", "Image", "Name", "Version", "Last Modified", "Provider", "Size", "Side", "Loaders", + "Minecraft Versions", "Release Type", "Requires", "Required By" }); + m_column_names_translated = QStringList({ tr("Enable"), tr("Image"), tr("Name"), tr("Version"), tr("Last Modified"), tr("Provider"), tr("Size"), tr("Side"), - tr("Loaders"), tr("Minecraft Versions"), tr("Release Type"), tr("Requires"), tr("Required By"), tr("File Name") }); - m_columnSortKeys = { SortType::Enabled, SortType::Name, SortType::Name, SortType::Version, SortType::Date, - SortType::Provider, SortType::Size, SortType::Side, SortType::Loaders, SortType::McVersions, - SortType::ReleaseType, SortType::Requires, SortType::RequiredBy, SortType::Filename }; - m_columnResizeModes = { QHeaderView::Interactive, QHeaderView::Interactive, QHeaderView::Stretch, QHeaderView::Interactive, - QHeaderView::Interactive, QHeaderView::Interactive, QHeaderView::Interactive, QHeaderView::Interactive, - QHeaderView::Interactive, QHeaderView::Interactive, QHeaderView::Interactive, QHeaderView::Interactive, - QHeaderView::Interactive, QHeaderView::Interactive }; - m_columnsHideable = { false, true, false, true, true, true, true, true, true, true, true, true, true, true }; + tr("Loaders"), tr("Minecraft Versions"), tr("Release Type"), tr("Requires"), tr("Required By") }); + m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::NAME, SortType::VERSION, SortType::DATE, + SortType::PROVIDER, SortType::SIZE, SortType::SIDE, SortType::LOADERS, SortType::MC_VERSIONS, + SortType::RELEASE_TYPE, SortType::REQUIRES, SortType::REQUIRED_BY }; + m_column_resize_modes = { QHeaderView::Interactive, QHeaderView::Interactive, QHeaderView::Stretch, QHeaderView::Interactive, + QHeaderView::Interactive, QHeaderView::Interactive, QHeaderView::Interactive, QHeaderView::Interactive, + QHeaderView::Interactive, QHeaderView::Interactive, QHeaderView::Interactive, QHeaderView::Interactive, + QHeaderView::Interactive }; + m_columnsHideable = { false, true, false, true, true, true, true, true, true, true, true, true, true }; connect(this, &ModFolderModel::parseFinished, this, &ModFolderModel::onParseFinished); } QVariant ModFolderModel::data(const QModelIndex& index, int role) const { - if (!validateIndex(index)) { + if (!validateIndex(index)) return {}; - } int row = index.row(); int column = index.column(); @@ -110,7 +109,7 @@ QVariant ModFolderModel::data(const QModelIndex& index, int role) const return at(row).loaders(); } case McVersionsColumn: { - return at(row).mcVersionsString(); + return at(row).mcVersions(); } case ReleaseTypeColumn: { return at(row).releaseType(); @@ -121,8 +120,6 @@ QVariant ModFolderModel::data(const QModelIndex& index, int role) const case RequiresColumn: { return at(row).requiresCount(); } - default: - break; } break; case Qt::DecorationRole: { @@ -158,11 +155,6 @@ QVariant ModFolderModel::data(const QModelIndex& index, int role) const case SizeColumn: mappedIndex = index.siblingAtColumn(ResourceFolderModel::SizeColumn); break; - case FileNameColumn: - mappedIndex = index.siblingAtColumn(ResourceFolderModel::FileNameColumn); - break; - default: - break; } if (mappedIndex.isValid()) { @@ -190,7 +182,6 @@ QVariant ModFolderModel::headerData(int section, [[maybe_unused]] Qt::Orientatio case SizeColumn: case RequiredByColumn: case RequiresColumn: - case FileNameColumn: return columnNames().at(section); default: return QVariant(); @@ -222,8 +213,6 @@ QVariant ModFolderModel::headerData(int section, [[maybe_unused]] Qt::Orientatio return tr("For each mod, the number of other mods which depend on it."); case RequiresColumn: return tr("For each mod, the number of other mods it depends on."); - case FileNameColumn: - return tr("The file name of the mod."); default: return QVariant(); } @@ -234,12 +223,12 @@ QVariant ModFolderModel::headerData(int section, [[maybe_unused]] Qt::Orientatio int ModFolderModel::columnCount(const QModelIndex& parent) const { - return parent.isValid() ? 0 : NumColumns; + return parent.isValid() ? 0 : NUM_COLUMNS; } Task* ModFolderModel::createParseTask(Resource& resource) { - return new LocalModParseTask(m_nextResolutionTicket, resource.type(), resource.fileinfo()); + return new LocalModParseTask(m_next_resolution_ticket, resource.type(), resource.fileinfo()); } bool ModFolderModel::isValid() @@ -247,37 +236,35 @@ bool ModFolderModel::isValid() return m_dir.exists() && m_dir.isReadable(); } -void ModFolderModel::onParseSucceeded(int ticket, const QString& resourceId) +void ModFolderModel::onParseSucceeded(int ticket, QString mod_id) { - auto iter = m_activeParseTasks.constFind(ticket); - if (iter == m_activeParseTasks.constEnd()) { + auto iter = m_active_parse_tasks.constFind(ticket); + if (iter == m_active_parse_tasks.constEnd()) return; - } - int row = m_resourcesIndex[resourceId]; + int row = m_resources_index[mod_id]; - const auto& parseTask = *iter; - auto* castTask = static_cast(parseTask.get()); + auto parse_task = *iter; + auto cast_task = static_cast(parse_task.get()); - Q_ASSERT(castTask->token() == ticket); + Q_ASSERT(cast_task->token() == ticket); - auto resource = find(resourceId); + auto resource = find(mod_id); - auto result = castTask->result(); + auto result = cast_task->result(); if (result && resource) { auto* mod = static_cast(resource.get()); mod->finishResolvingWithDetails(std::move(result->details)); + } emit dataChanged(index(row, RequiresColumn), index(row, RequiredByColumn)); } -namespace { -Mod* findById(QSet mods, const QString& resourceId) +Mod* findById(QSet mods, QString modId) { - auto found = std::ranges::find_if(mods, [resourceId](Mod* m) { return m->mod_id() == resourceId; }); + auto found = std::find_if(mods.begin(), mods.end(), [modId](Mod* m) { return m->mod_id() == modId; }); return found != mods.end() ? *found : nullptr; } -} // namespace void ModFolderModel::onParseFinished() { @@ -290,25 +277,25 @@ void ModFolderModel::onParseFinished() m_requires.clear(); m_requiredBy.clear(); - auto findByProjectID = [mods](const QVariant& modId, ModPlatform::ResourceProvider provider) -> Mod* { - auto found = std::ranges::find_if(mods, [modId, provider](Mod* m) { + auto findByProjectID = [mods](QVariant modId, ModPlatform::ResourceProvider provider) -> Mod* { + auto found = std::find_if(mods.begin(), mods.end(), [modId, provider](Mod* m) { return m->metadata() && m->metadata()->provider == provider && m->metadata()->project_id == modId; }); return found != mods.end() ? *found : nullptr; }; - for (auto* mod : mods) { + for (auto mod : mods) { auto id = mod->mod_id(); - for (const auto& dep : mod->dependencies()) { - auto* d = findById(mods, dep); + for (auto dep : mod->dependencies()) { + auto d = findById(mods, dep); if (d) { m_requires[id] << d; m_requiredBy[d->mod_id()] << mod; } } if (mod->metadata()) { - for (const auto& dep : mod->metadata()->dependencies) { + for (auto dep : mod->metadata()->dependencies) { if (dep.type == ModPlatform::DependencyType::REQUIRED) { - auto* d = findByProjectID(dep.addonId, mod->metadata()->provider); + auto d = findByProjectID(dep.addonId, mod->metadata()->provider); if (d) { m_requires[id] << d; m_requiredBy[d->mod_id()] << mod; @@ -317,31 +304,30 @@ void ModFolderModel::onParseFinished() } } } - for (auto* mod : mods) { + for (auto mod : mods) { auto id = mod->mod_id(); if (mod->requiredByCount() != m_requiredBy[id].count() || mod->requiresCount() != m_requires[id].count()) { mod->setRequiredByCount(m_requiredBy[id].count()); mod->setRequiresCount(m_requires[id].count()); - int row = m_resourcesIndex[mod->internalId()]; + int row = m_resources_index[mod->internal_id()]; emit dataChanged(index(row), index(row, columnCount(QModelIndex()) - 1)); } } } -namespace { - -QSet collectMods(const QSet& mods, QHash> relation, std::set& seen, bool shouldBeEnabled) +QSet collectMods(QSet mods, QHash> relation, std::set& seen, bool shouldBeEnabled) { QSet affectedList = {}; QSet needToCheck = {}; - for (auto* mod : mods) { + for (auto mod : mods) { auto id = mod->mod_id(); - if (!seen.contains(id)) { + if (seen.count(id) == 0) { seen.insert(id); - for (auto* affected : relation[id]) { + for (auto affected : relation[id]) { auto affectedId = affected->mod_id(); - if (findById(mods, affectedId) == nullptr && !seen.contains(affectedId)) { + if (findById(mods, affectedId) == nullptr && seen.count(affectedId) == 0) { + seen.insert(affectedId); if (shouldBeEnabled != affected->enabled()) { affectedList << affected; } @@ -356,13 +342,11 @@ QSet collectMods(const QSet& mods, QHash> relati } return affectedList; } -} // namespace QModelIndexList ModFolderModel::getAffectedMods(const QModelIndexList& indexes, EnableAction action) { - if (indexes.isEmpty()) { + if (indexes.isEmpty()) return {}; - } QModelIndexList affectedList = {}; auto affectedModsList = selectedMods(indexes); @@ -382,9 +366,9 @@ QModelIndexList ModFolderModel::getAffectedMods(const QModelIndexList& indexes, return {}; // this function should not be called with TOGGLE } } - for (auto* affected : affectedMods) { + for (auto affected : affectedMods) { auto affectedId = affected->mod_id(); - auto row = m_resourcesIndex[affected->internalId()]; + auto row = m_resources_index[affected->internal_id()]; affectedList << index(row, 0); } return affectedList; @@ -392,9 +376,8 @@ QModelIndexList ModFolderModel::getAffectedMods(const QModelIndexList& indexes, bool ModFolderModel::setResourceEnabled(const QModelIndexList& indexes, EnableAction action) { - if (indexes.isEmpty()) { + if (indexes.isEmpty()) return {}; - } auto indexedModsList = selectedMods(indexes); auto indexedMods = QSet(indexedModsList.begin(), indexedModsList.end()); @@ -413,7 +396,7 @@ bool ModFolderModel::setResourceEnabled(const QModelIndexList& indexes, EnableAc break; } case EnableAction::TOGGLE: { - for (auto* mod : indexedMods) { + for (auto mod : indexedMods) { if (mod->enabled()) { toDisable << mod; } else { @@ -428,10 +411,10 @@ bool ModFolderModel::setResourceEnabled(const QModelIndexList& indexes, EnableAc auto requiredToDisable = collectMods(toDisable, m_requiredBy, seen, false); toDisable.removeIf([toEnable](Mod* m) { return toEnable.contains(m); }); - auto toList = [this](const QSet& mods) { + auto toList = [this](QSet mods) { QModelIndexList list; - for (auto* mod : mods) { - auto row = m_resourcesIndex[mod->internalId()]; + for (auto mod : mods) { + auto row = m_resources_index[mod->internal_id()]; list << index(row, 0); } return list; @@ -464,8 +447,8 @@ bool ModFolderModel::setResourceEnabled(const QModelIndexList& indexes, EnableAc yesButton = tr("Disable Required"); } - auto* box = CustomMessageBox::selectable(nullptr, title, message, QMessageBox::Warning, - QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel, QMessageBox::No); + auto box = CustomMessageBox::selectable(nullptr, title, message, QMessageBox::Warning, + QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel, QMessageBox::No); box->button(QMessageBox::No)->setText(noButton); box->button(QMessageBox::Yes)->setText(yesButton); auto response = box->exec(); @@ -483,23 +466,21 @@ bool ModFolderModel::setResourceEnabled(const QModelIndexList& indexes, EnableAc return disableStatus && enableStatus; } -namespace { -QStringList reqToList(const QSet& l) +QStringList reqToList(QSet l) { QStringList req; - for (auto* m : l) { + for (auto m : l) { req << m->name(); } return req; } -} // namespace -QStringList ModFolderModel::requiresList(const QString& id) +QStringList ModFolderModel::requiresList(QString id) { return reqToList(m_requires[id]); } -QStringList ModFolderModel::requiredByList(const QString& id) +QStringList ModFolderModel::requiredByList(QString id) { return reqToList(m_requiredBy[id]); } @@ -508,7 +489,7 @@ bool ModFolderModel::deleteResources(const QModelIndexList& indexes) { auto deleteInvalid = [](QSet& mods) { for (auto it = mods.begin(); it != mods.end();) { - auto* mod = *it; + auto mod = *it; // the QFileInfo::exists is used instead of mod->fileinfo().exists // because the later somehow caches that the file exists if (!mod || !QFileInfo::exists(mod->fileinfo().absoluteFilePath())) { @@ -519,14 +500,14 @@ bool ModFolderModel::deleteResources(const QModelIndexList& indexes) } }; auto rsp = ResourceFolderModel::deleteResources(indexes); - for (auto* mod : allMods()) { + for (auto mod : allMods()) { auto id = mod->mod_id(); deleteInvalid(m_requiredBy[id]); deleteInvalid(m_requires[id]); if (mod->requiredByCount() != m_requiredBy[id].count() || mod->requiresCount() != m_requires[id].count()) { mod->setRequiredByCount(m_requiredBy[id].count()); mod->setRequiresCount(m_requires[id].count()); - int row = m_resourcesIndex[mod->internalId()]; + int row = m_resources_index[mod->internal_id()]; emit dataChanged(index(row, RequiresColumn), index(row, RequiredByColumn)); } } diff --git a/launcher/minecraft/mod/ModFolderModel.h b/launcher/minecraft/mod/ModFolderModel.h index a5c6ba483..4de875abc 100644 --- a/launcher/minecraft/mod/ModFolderModel.h +++ b/launcher/minecraft/mod/ModFolderModel.h @@ -46,6 +46,7 @@ #include "Mod.h" #include "ResourceFolderModel.h" +#include "minecraft/Component.h" #include "minecraft/mod/Resource.h" class BaseInstance; @@ -58,7 +59,7 @@ class QFileSystemWatcher; class ModFolderModel : public ResourceFolderModel { Q_OBJECT public: - enum Columns : std::uint8_t { + enum Columns { ActiveColumn = 0, ImageColumn, NameColumn, @@ -72,12 +73,11 @@ class ModFolderModel : public ResourceFolderModel { ReleaseTypeColumn, RequiresColumn, RequiredByColumn, - FileNameColumn, - NumColumns + NUM_COLUMNS }; - ModFolderModel(const QDir& dir, BaseInstance* instance, bool isIndexed, bool createDir, QObject* parent = nullptr); + ModFolderModel(const QDir& dir, BaseInstance* instance, bool is_indexed, bool create_dir, QObject* parent = nullptr); - QString id() const override { return "mods"; } + virtual QString id() const override { return "mods"; } QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; @@ -85,7 +85,7 @@ class ModFolderModel : public ResourceFolderModel { int columnCount(const QModelIndex& parent) const override; [[nodiscard]] Resource* createResource(const QFileInfo& file) override { return new Mod(file); } - [[nodiscard]] Task* createParseTask(Resource& /*unused*/) override; + [[nodiscard]] Task* createParseTask(Resource&) override; bool isValid(); @@ -97,11 +97,11 @@ class ModFolderModel : public ResourceFolderModel { RESOURCE_HELPERS(Mod) public: - QStringList requiresList(const QString& id); - QStringList requiredByList(const QString& id); + QStringList requiresList(QString id); + QStringList requiredByList(QString id); private slots: - void onParseSucceeded(int ticket, const QString& resourceId) override; + void onParseSucceeded(int ticket, QString resource_id) override; void onParseFinished(); private: diff --git a/launcher/minecraft/mod/Resource.cpp b/launcher/minecraft/mod/Resource.cpp index 06d9a0af7..692622521 100644 --- a/launcher/minecraft/mod/Resource.cpp +++ b/launcher/minecraft/mod/Resource.cpp @@ -4,75 +4,71 @@ #include #include #include -#include #include "FileSystem.h" #include "StringUtils.h" #include "minecraft/MinecraftInstance.h" #include "minecraft/PackProfile.h" -Resource::Resource(QObject* parent) : QObject(parent), m_size_info(0) {} +Resource::Resource(QObject* parent) : QObject(parent) {} -Resource::Resource(QFileInfo fileInfo) : m_size_info(0) +Resource::Resource(QFileInfo file_info) : QObject() { - setFile(fileInfo); + setFile(file_info); } -void Resource::setFile(QFileInfo fileInfo) +void Resource::setFile(QFileInfo file_info) { - m_file_info = std::move(fileInfo); + m_file_info = file_info; parseFile(); } -namespace { -std::tuple calculateFileSize(const QFileInfo& file) +static std::tuple calculateFileSize(const QFileInfo& file) { if (file.isDir()) { auto dir = QDir(file.absoluteFilePath()); dir.setFilter(QDir::AllEntries | QDir::NoDotAndDotDot); auto count = dir.count(); auto str = QObject::tr("item"); - if (count != 1) { + if (count != 1) str = QObject::tr("items"); - } return { QString("%1 %2").arg(QString::number(count), str), count }; } return { StringUtils::humanReadableFileSize(file.size(), true), file.size() }; } -} // namespace void Resource::parseFile() { - QString fileName{ m_file_info.fileName() }; + QString file_name{ m_file_info.fileName() }; m_type = ResourceType::UNKNOWN; - m_internal_id = fileName; + m_internal_id = file_name; std::tie(m_size_str, m_size_info) = calculateFileSize(m_file_info); if (m_file_info.isDir()) { m_type = ResourceType::FOLDER; - m_name = fileName; + m_name = file_name; } else if (m_file_info.isFile()) { - if (fileName.endsWith(".disabled")) { - fileName.chop(9); + if (file_name.endsWith(".disabled")) { + file_name.chop(9); m_enabled = false; } - if (fileName.endsWith(".zip") || fileName.endsWith(".jar")) { + if (file_name.endsWith(".zip") || file_name.endsWith(".jar")) { m_type = ResourceType::ZIPFILE; - fileName.chop(4); - } else if (fileName.endsWith(".nilmod")) { + file_name.chop(4); + } else if (file_name.endsWith(".nilmod")) { m_type = ResourceType::ZIPFILE; - fileName.chop(7); - } else if (fileName.endsWith(".litemod")) { + file_name.chop(7); + } else if (file_name.endsWith(".litemod")) { m_type = ResourceType::LITEMOD; - fileName.chop(8); + file_name.chop(8); } else { m_type = ResourceType::SINGLEFILE; } - m_name = fileName; + m_name = file_name; } m_changed_date_time = m_file_info.lastModified(); @@ -80,45 +76,39 @@ void Resource::parseFile() auto Resource::name() const -> QString { - if (metadata()) { + if (metadata()) return metadata()->name; - } return m_name; } -namespace { -void removeThePrefix(QString& string) +static void removeThePrefix(QString& string) { static const QRegularExpression s_regex(QStringLiteral("^(?:the|teh) +"), QRegularExpression::CaseInsensitiveOption); string.remove(s_regex); string = string.trimmed(); } -} // namespace auto Resource::provider() const -> QString { - if (metadata()) { + if (metadata()) return ModPlatform::ProviderCapabilities::readableName(metadata()->provider); - } return tr("Unknown"); } auto Resource::homepage() const -> QString { - if (metadata()) { + if (metadata()) return ModPlatform::getMetaURL(metadata()->provider, metadata()->project_id); - } return {}; } void Resource::setMetadata(std::shared_ptr&& metadata) { - if (status() == ResourceStatus::NoMetadata) { - setStatus(ResourceStatus::Installed); - } + if (status() == ResourceStatus::NO_METADATA) + setStatus(ResourceStatus::INSTALLED); m_metadata = metadata; } @@ -143,12 +133,12 @@ void Resource::updateIssues(const BaseInstance* inst) return; } - const auto* mcInst = dynamic_cast(inst); + auto mcInst = dynamic_cast(inst); if (mcInst == nullptr) { return; } - auto* profile = mcInst->getPackProfile(); + auto profile = mcInst->getPackProfile(); QString mcVersion = profile->getComponentVersion("net.minecraft"); if (!m_metadata->mcVersions.empty() && !m_metadata->mcVersions.contains(mcVersion)) { @@ -161,59 +151,46 @@ int Resource::compare(const Resource& other, SortType type) const { switch (type) { default: - case SortType::Enabled: - if (enabled() && !other.enabled()) { + case SortType::ENABLED: + if (enabled() && !other.enabled()) return 1; - } - if (!enabled() && other.enabled()) { + if (!enabled() && other.enabled()) return -1; - } break; - case SortType::Name: { - QString thisName{ name() }; - QString otherName{ other.name() }; + case SortType::NAME: { + QString this_name{ name() }; + QString other_name{ other.name() }; // TODO do we need this? it could result in 0 being returned - removeThePrefix(thisName); - removeThePrefix(otherName); + removeThePrefix(this_name); + removeThePrefix(other_name); - return QString::compare(thisName, otherName, Qt::CaseInsensitive); + return QString::compare(this_name, other_name, Qt::CaseInsensitive); } - case SortType::Date: - if (dateTimeChanged() > other.dateTimeChanged()) { + case SortType::DATE: + if (dateTimeChanged() > other.dateTimeChanged()) return 1; - } - if (dateTimeChanged() < other.dateTimeChanged()) { + if (dateTimeChanged() < other.dateTimeChanged()) return -1; - } break; - case SortType::Filename: - return fileinfo().fileName().localeAwareCompare(other.fileinfo().fileName()); - - case SortType::Size: { + case SortType::SIZE: { if (this->type() != other.type()) { - if (this->type() == ResourceType::FOLDER) { + if (this->type() == ResourceType::FOLDER) return -1; - } - if (other.type() == ResourceType::FOLDER) { + if (other.type() == ResourceType::FOLDER) return 1; - } } - if (sizeInfo() > other.sizeInfo()) { + if (sizeInfo() > other.sizeInfo()) return 1; - } - if (sizeInfo() < other.sizeInfo()) { + if (sizeInfo() < other.sizeInfo()) return -1; - } break; } - - case SortType::Provider: { - auto compareResult = QString::compare(provider(), other.provider(), Qt::CaseInsensitive); - if (compareResult != 0) { - return compareResult; - } + case SortType::PROVIDER: { + auto compare_result = QString::compare(provider(), other.provider(), Qt::CaseInsensitive); + if (compare_result != 0) + return compare_result; break; } } @@ -223,20 +200,13 @@ int Resource::compare(const Resource& other, SortType type) const bool Resource::applyFilter(QRegularExpression filter) const { - if (filter.match(name()).hasMatch()) { - return true; - } - if (filter.match(fileinfo().fileName()).hasMatch()) { - return true; - } - return false; + return filter.match(name()).hasMatch(); } bool Resource::enable(EnableAction action) { - if (m_type == ResourceType::UNKNOWN || m_type == ResourceType::FOLDER) { + if (m_type == ResourceType::UNKNOWN || m_type == ResourceType::FOLDER) return false; - } QString path = m_file_info.absoluteFilePath(); QFile file(path); @@ -255,16 +225,14 @@ bool Resource::enable(EnableAction action) break; } - if (m_enabled == enable) { + if (m_enabled == enable) return false; - } if (enable) { // m_enabled is false, but there's no '.disabled' suffix. // TODO: Report error? - if (!path.endsWith(".disabled")) { + if (!path.endsWith(".disabled")) return false; - } path.chop(9); } else { path += ".disabled"; @@ -272,9 +240,8 @@ bool Resource::enable(EnableAction action) path = FS::getUniqueResourceName(path); } } - if (!file.rename(path)) { + if (!file.rename(path)) return false; - } setFile(QFileInfo(path)); @@ -282,34 +249,33 @@ bool Resource::enable(EnableAction action) return true; } -auto Resource::destroy(const QDir& indexDir, bool preserveMetadata, bool attemptTrash) -> bool +auto Resource::destroy(const QDir& index_dir, bool preserve_metadata, bool attempt_trash) -> bool { m_type = ResourceType::UNKNOWN; - if (!preserveMetadata) { + if (!preserve_metadata) { qDebug() << QString("Destroying metadata for '%1' on purpose").arg(name()); - destroyMetadata(indexDir); + destroyMetadata(index_dir); } - return (attemptTrash && FS::trash(m_file_info.filePath())) || FS::deletePath(m_file_info.filePath()); + return (attempt_trash && FS::trash(m_file_info.filePath())) || FS::deletePath(m_file_info.filePath()); } -auto Resource::destroyMetadata(const QDir& indexDir) -> void +auto Resource::destroyMetadata(const QDir& index_dir) -> void { if (metadata()) { - Metadata::remove(indexDir, metadata()->slug); + Metadata::remove(index_dir, metadata()->slug); } else { auto n = name(); - Metadata::remove(indexDir, n); + Metadata::remove(index_dir, n); } m_metadata = nullptr; } bool Resource::isSymLinkUnder(const QString& instPath) const { - if (isSymLink()) { + if (isSymLink()) return true; - } auto instDir = QDir(instPath); @@ -327,9 +293,8 @@ bool Resource::isMoreThanOneHardLink() const auto Resource::getOriginalFileName() const -> QString { auto fileName = m_file_info.fileName(); - if (!m_enabled) { + if (!m_enabled) fileName.chop(9); - } return fileName; } @@ -359,16 +324,16 @@ QDebug operator<<(QDebug debug, ResourceType type) QDebug operator<<(QDebug debug, ResourceStatus status) { switch (status) { - case ResourceStatus::Installed: + case ResourceStatus::INSTALLED: debug << "INSTALLED"; break; - case ResourceStatus::NotInstalled: + case ResourceStatus::NOT_INSTALLED: debug << "NOT_INSTALLED"; break; - case ResourceStatus::NoMetadata: + case ResourceStatus::NO_METADATA: debug << "NO_METADATA"; break; - case ResourceStatus::Unknown: + case ResourceStatus::UNKNOWN: default: debug << "UNKNOWN"; break; diff --git a/launcher/minecraft/mod/Resource.h b/launcher/minecraft/mod/Resource.h index 694d74ec0..485405b24 100644 --- a/launcher/minecraft/mod/Resource.h +++ b/launcher/minecraft/mod/Resource.h @@ -45,7 +45,7 @@ class BaseInstance; -enum class ResourceType : std::uint8_t { +enum class ResourceType { UNKNOWN, //!< Indicates an unspecified resource type. ZIPFILE, //!< The resource is a zip file containing the resource's class files. SINGLEFILE, //!< The resource is a single file (not a zip file). @@ -55,33 +55,32 @@ enum class ResourceType : std::uint8_t { QDebug operator<<(QDebug debug, ResourceType type); -enum class ResourceStatus : std::uint8_t { - Installed, // Both JAR and Metadata are present - NotInstalled, // Only the Metadata is present - NoMetadata, // Only the JAR is present - Unknown, // Default status +enum class ResourceStatus { + INSTALLED, // Both JAR and Metadata are present + NOT_INSTALLED, // Only the Metadata is present + NO_METADATA, // Only the JAR is present + UNKNOWN, // Default status }; QDebug operator<<(QDebug debug, ResourceStatus status); -enum class SortType : std::uint8_t { - Name, - Date, - Version, - Enabled, - PackFormat, - Provider, - Size, - Side, - McVersions, - Loaders, - ReleaseType, - Requires, - RequiredBy, - Filename, +enum class SortType { + NAME, + DATE, + VERSION, + ENABLED, + PACK_FORMAT, + PROVIDER, + SIZE, + SIDE, + MC_VERSIONS, + LOADERS, + RELEASE_TYPE, + REQUIRES, + REQUIRED_BY, }; -enum class EnableAction : std::uint8_t { ENABLE, DISABLE, TOGGLE }; +enum class EnableAction { ENABLE, DISABLE, TOGGLE }; /** General class for managed resources. It mirrors a file in disk, with some more info * for display and house-keeping purposes. @@ -93,19 +92,20 @@ class Resource : public QObject { Q_DISABLE_COPY(Resource) public: using Ptr = shared_qobject_ptr; + using WeakPtr = QPointer; Resource(QObject* parent = nullptr); - Resource(QFileInfo fileInfo); - Resource(const QString& filePath) : Resource(QFileInfo(filePath)) {} + Resource(QFileInfo file_info); + Resource(QString file_path) : Resource(QFileInfo(file_path)) {} ~Resource() override = default; - void setFile(QFileInfo fileInfo); + void setFile(QFileInfo file_info); void parseFile(); auto fileinfo() const -> QFileInfo { return m_file_info; } auto dateTimeChanged() const -> QDateTime { return m_changed_date_time; } - auto internalId() const -> QString { return m_internal_id; } + auto internal_id() const -> QString { return m_internal_id; } auto type() const -> ResourceType { return m_type; } bool enabled() const { return m_enabled; } auto getOriginalFileName() const -> QString; @@ -138,7 +138,7 @@ class Resource : public QObject { * = 0: 'this' is equal to 'other' * < 0: 'this' comes before 'other' */ - virtual int compare(const Resource& other, SortType type = SortType::Name) const; + virtual int compare(const Resource& other, SortType type = SortType::NAME) const; /** Returns whether the given filter should filter out 'this' (false), * or if such filter includes the Resource (true). @@ -163,9 +163,9 @@ class Resource : public QObject { } // Delete all files of this resource. - auto destroy(const QDir& indexDir, bool preserveMetadata = false, bool attemptTrash = true) -> bool; + auto destroy(const QDir& index_dir, bool preserve_metadata = false, bool attempt_trash = true) -> bool; // Delete the metadata only. - auto destroyMetadata(const QDir& indexDir) -> void; + auto destroyMetadata(const QDir& index_dir) -> void; auto isSymLink() const -> bool { return m_file_info.isSymLink(); } @@ -195,7 +195,7 @@ class Resource : public QObject { ResourceType m_type = ResourceType::UNKNOWN; /* Installation status of the resource. */ - ResourceStatus m_status = ResourceStatus::Unknown; + ResourceStatus m_status = ResourceStatus::UNKNOWN; std::shared_ptr m_metadata = nullptr; diff --git a/launcher/minecraft/mod/ResourceFolderModel.cpp b/launcher/minecraft/mod/ResourceFolderModel.cpp index ddc132089..9d3f3e749 100644 --- a/launcher/minecraft/mod/ResourceFolderModel.cpp +++ b/launcher/minecraft/mod/ResourceFolderModel.cpp @@ -11,7 +11,6 @@ #include #include #include -#include #include #include "Application.h" @@ -28,10 +27,10 @@ #include "tasks/Task.h" #include "ui/dialogs/CustomMessageBox.h" -ResourceFolderModel::ResourceFolderModel(const QDir& dir, BaseInstance* instance, bool isIndexed, bool createDir, QObject* parent) - : QAbstractListModel(parent), m_dir(dir), m_instance(instance), m_watcher(this), m_isIndexed(isIndexed) +ResourceFolderModel::ResourceFolderModel(const QDir& dir, BaseInstance* instance, bool is_indexed, bool create_dir, QObject* parent) + : QAbstractListModel(parent), m_dir(dir), m_instance(instance), m_watcher(this), m_is_indexed(is_indexed) { - if (createDir) { + if (create_dir) { FS::ensureFolderPathExists(m_dir.absolutePath()); } @@ -50,75 +49,70 @@ ResourceFolderModel::ResourceFolderModel(const QDir& dir, BaseInstance* instance ResourceFolderModel::~ResourceFolderModel() { - while (!QThreadPool::globalInstance()->waitForDone(100)) { + while (!QThreadPool::globalInstance()->waitForDone(100)) QCoreApplication::processEvents(); - } } bool ResourceFolderModel::startWatching(const QStringList& paths) { // Remove orphaned metadata next time - m_firstFolderLoad = true; + m_first_folder_load = true; - if (m_isWatching) { + if (m_is_watching) return false; - } - auto couldntBeWatched = m_watcher.addPaths(paths); - for (const auto& path : paths) { - if (couldntBeWatched.contains(path)) { + auto couldnt_be_watched = m_watcher.addPaths(paths); + for (auto path : paths) { + if (couldnt_be_watched.contains(path)) qDebug() << "Failed to start watching" << path; - } else { + else qDebug() << "Started watching" << path; - } } update(); - m_isWatching = !m_isWatching; - return m_isWatching; + m_is_watching = !m_is_watching; + return m_is_watching; } bool ResourceFolderModel::stopWatching(const QStringList& paths) { - if (!m_isWatching) { + if (!m_is_watching) return false; - } - auto couldntBeStopped = m_watcher.removePaths(paths); - for (const auto& path : paths) { - if (couldntBeStopped.contains(path)) { + auto couldnt_be_stopped = m_watcher.removePaths(paths); + for (auto path : paths) { + if (couldnt_be_stopped.contains(path)) qDebug() << "Failed to stop watching" << path; - } else { + else qDebug() << "Stopped watching" << path; - } } - m_isWatching = !m_isWatching; - return !m_isWatching; + m_is_watching = !m_is_watching; + return !m_is_watching; } -bool ResourceFolderModel::installResource(QString originalPath) +bool ResourceFolderModel::installResource(QString original_path) { // NOTE: fix for GH-1178: remove trailing slash to avoid issues with using the empty result of QFileInfo::fileName - originalPath = FS::NormalizePath(originalPath); - QFileInfo fileInfo(originalPath); + original_path = FS::NormalizePath(original_path); + QFileInfo file_info(original_path); - if (!fileInfo.exists() || !fileInfo.isReadable()) { - qWarning() << "Caught attempt to install non-existing file or file-like object:" << originalPath; + if (!file_info.exists() || !file_info.isReadable()) { + qWarning() << "Caught attempt to install non-existing file or file-like object:" << original_path; return false; } - qDebug() << "Installing:" << fileInfo.absoluteFilePath(); + qDebug() << "Installing:" << file_info.absoluteFilePath(); - Resource resource(fileInfo); + Resource resource(file_info); if (!resource.valid()) { - qWarning() << originalPath << "is not a valid resource. Ignoring it."; + qWarning() << original_path << "is not a valid resource. Ignoring it."; return false; } - auto newPath = FS::NormalizePath(m_dir.filePath(fileInfo.fileName())); - if (originalPath == newPath) { - qWarning() << "Overwriting the mod (" << originalPath << ") with itself makes no sense..."; + auto new_path = FS::NormalizePath(m_dir.filePath(file_info.fileName())); + if (original_path == new_path) { + qWarning() << "Overwriting the mod (" << original_path << ") with itself makes no sense..."; return false; } @@ -126,47 +120,45 @@ bool ResourceFolderModel::installResource(QString originalPath) case ResourceType::SINGLEFILE: case ResourceType::ZIPFILE: case ResourceType::LITEMOD: { - if (QFile::exists(newPath) || QFile::exists(newPath + QString(".disabled"))) { - if (!FS::deletePath(newPath)) { - qCritical() << "Cleaning up new location (" << newPath << ") was unsuccessful!"; + if (QFile::exists(new_path) || QFile::exists(new_path + QString(".disabled"))) { + if (!FS::deletePath(new_path)) { + qCritical() << "Cleaning up new location (" << new_path << ") was unsuccessful!"; return false; } - qDebug() << newPath << "has been deleted."; + qDebug() << new_path << "has been deleted."; } - if (!QFile::copy(originalPath, newPath)) { - qCritical() << "Copy from" << originalPath << "to" << newPath << "has failed."; + if (!QFile::copy(original_path, new_path)) { + qCritical() << "Copy from" << original_path << "to" << new_path << "has failed."; return false; } - FS::updateTimestamp(newPath); + FS::updateTimestamp(new_path); - QFileInfo newPathFileInfo(newPath); - resource.setFile(newPathFileInfo); + QFileInfo new_path_file_info(new_path); + resource.setFile(new_path_file_info); - if (!m_isWatching) { + if (!m_is_watching) return update(); - } return true; } case ResourceType::FOLDER: { - if (QFile::exists(newPath)) { - qDebug() << "Ignoring folder '" << originalPath << "', it would merge with" << newPath; + if (QFile::exists(new_path)) { + qDebug() << "Ignoring folder '" << original_path << "', it would merge with" << new_path; return false; } - if (!FS::copy(originalPath, newPath)()) { - qWarning() << "Copy of folder from" << originalPath << "to" << newPath << "has (potentially partially) failed."; + if (!FS::copy(original_path, new_path)()) { + qWarning() << "Copy of folder from" << original_path << "to" << new_path << "has (potentially partially) failed."; return false; } - QFileInfo newpathInfo(newPath); + QFileInfo newpathInfo(new_path); resource.setFile(newpathInfo); - if (!m_isWatching) { + if (!m_is_watching) return update(); - } return true; } @@ -176,24 +168,24 @@ bool ResourceFolderModel::installResource(QString originalPath) return false; } -void ResourceFolderModel::installResourceWithFlameMetadata(const QString& path, ModPlatform::IndexedVersion& vers) +void ResourceFolderModel::installResourceWithFlameMetadata(QString path, ModPlatform::IndexedVersion& vers) { - auto install = [this, path] { installResource(path); }; + auto install = [this, path] { installResource(std::move(path)); }; if (vers.addonId.isValid()) { ModPlatform::IndexedPack pack{ - .addonId = vers.addonId, - .provider = ModPlatform::ResourceProvider::FLAME, + vers.addonId, + ModPlatform::ResourceProvider::FLAME, }; auto [job, response] = FlameAPI().getProject(vers.addonId.toString()); connect(job.get(), &Task::failed, this, install); connect(job.get(), &Task::aborted, this, install); connect(job.get(), &Task::succeeded, [response, this, &vers, install, &pack] { - QJsonParseError parseError{}; - QJsonDocument doc = QJsonDocument::fromJson(*response, &parseError); - if (parseError.error != QJsonParseError::NoError) { - qWarning() << "Error while parsing JSON response for mod info at" << parseError.offset - << "reason:" << parseError.errorString(); + QJsonParseError parse_error{}; + QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error); + if (parse_error.error != QJsonParseError::NoError) { + qWarning() << "Error while parsing JSON response for mod info at" << parse_error.offset + << "reason:" << parse_error.errorString(); qDebug() << *response; return; } @@ -204,9 +196,9 @@ void ResourceFolderModel::installResourceWithFlameMetadata(const QString& path, qDebug() << doc; qWarning() << "Error while reading mod info:" << e.cause(); } - LocalResourceUpdateTask updateMetadata(indexDir(), pack, vers); - connect(&updateMetadata, &Task::finished, this, install); - updateMetadata.start(); + LocalResourceUpdateTask update_metadata(indexDir(), pack, vers); + connect(&update_metadata, &Task::finished, this, install); + update_metadata.start(); }); job->start(); @@ -215,7 +207,7 @@ void ResourceFolderModel::installResourceWithFlameMetadata(const QString& path, } } -bool ResourceFolderModel::uninstallResource(const QString& fileName, bool preserveMetadata) +bool ResourceFolderModel::uninstallResource(const QString& file_name, bool preserve_metadata) { for (auto& resource : m_resources) { auto resourceFileInfo = resource->fileinfo(); @@ -224,8 +216,8 @@ bool ResourceFolderModel::uninstallResource(const QString& fileName, bool preser resourceFileName.chop(9); } - if (resourceFileName == fileName) { - auto res = resource->destroy(indexDir(), preserveMetadata, false); + if (resourceFileName == file_name) { + auto res = resource->destroy(indexDir(), preserve_metadata, false); update(); @@ -237,16 +229,14 @@ bool ResourceFolderModel::uninstallResource(const QString& fileName, bool preser bool ResourceFolderModel::deleteResources(const QModelIndexList& indexes) { - if (indexes.isEmpty()) { + if (indexes.isEmpty()) return true; - } for (auto i : indexes) { - if (i.column() != 0) { + if (i.column() != 0) continue; - } - const auto& resource = m_resources.at(i.row()); + auto& resource = m_resources.at(i.row()); resource->destroy(indexDir()); } @@ -257,16 +247,14 @@ bool ResourceFolderModel::deleteResources(const QModelIndexList& indexes) void ResourceFolderModel::deleteMetadata(const QModelIndexList& indexes) { - if (indexes.isEmpty()) { + if (indexes.isEmpty()) return; - } for (auto i : indexes) { - if (i.column() != 0) { + if (i.column() != 0) continue; - } - const auto& resource = m_resources.at(i.row()); + auto& resource = m_resources.at(i.row()); resource->destroyMetadata(indexDir()); } @@ -283,36 +271,33 @@ bool ResourceFolderModel::setResourceEnabled(const QModelIndexList& indexes, Ena QMessageBox::Warning, QMessageBox::Yes | QMessageBox::No, QMessageBox::No) ->exec(); - if (response != QMessageBox::Yes) { + if (response != QMessageBox::Yes) return false; - } } - if (indexes.isEmpty()) { + if (indexes.isEmpty()) return true; - } bool succeeded = true; - for (const auto& idx : indexes) { - if (!validateIndex(idx) || idx.column() != 0) { + for (auto const& idx : indexes) { + if (!validateIndex(idx) || idx.column() != 0) continue; - } int row = idx.row(); auto& resource = m_resources[row]; // Preserve the row, but change its ID - auto oldId = resource->internalId(); + auto old_id = resource->internal_id(); if (!resource->enable(action)) { succeeded = false; continue; } - auto newId = resource->internalId(); + auto new_id = resource->internal_id(); - m_resourcesIndex.remove(oldId); - m_resourcesIndex[newId] = row; + m_resources_index.remove(old_id); + m_resources_index[new_id] = row; emit dataChanged(index(row, 0), index(row, columnCount(QModelIndex()) - 1)); } @@ -327,25 +312,24 @@ bool ResourceFolderModel::update() QMutexLocker lock(&s_update_task_mutex); // Already updating, so we schedule a future update and return. - if (m_currentUpdateTask) { - m_scheduledUpdate = true; + if (m_current_update_task) { + m_scheduled_update = true; return false; } - m_currentUpdateTask.reset(createUpdateTask()); - if (!m_currentUpdateTask) { + m_current_update_task.reset(createUpdateTask()); + if (!m_current_update_task) return false; - } - connect(m_currentUpdateTask.get(), &Task::succeeded, this, &ResourceFolderModel::onUpdateSucceeded, + connect(m_current_update_task.get(), &Task::succeeded, this, &ResourceFolderModel::onUpdateSucceeded, Qt::ConnectionType::QueuedConnection); - connect(m_currentUpdateTask.get(), &Task::failed, this, &ResourceFolderModel::onUpdateFailed, Qt::ConnectionType::QueuedConnection); + connect(m_current_update_task.get(), &Task::failed, this, &ResourceFolderModel::onUpdateFailed, Qt::ConnectionType::QueuedConnection); connect( - m_currentUpdateTask.get(), &Task::finished, this, + m_current_update_task.get(), &Task::finished, this, [this] { - m_currentUpdateTask.reset(); - if (m_scheduledUpdate) { - m_scheduledUpdate = false; + m_current_update_task.reset(); + if (m_scheduled_update) { + m_scheduled_update = false; update(); } else { emit updateFinished(); @@ -356,16 +340,16 @@ bool ResourceFolderModel::update() Task::Ptr preUpdate{ createPreUpdateTask() }; if (preUpdate != nullptr) { - auto* task = new SequentialTask("ResourceFolderModel::update"); + auto task = new SequentialTask("ResourceFolderModel::update"); task->addTask(preUpdate); - task->addTask(m_currentUpdateTask); + task->addTask(m_current_update_task); connect(task, &Task::finished, [task] { task->deleteLater(); }); QThreadPool::globalInstance()->start(task); } else { - QThreadPool::globalInstance()->start(m_currentUpdateTask.get()); + QThreadPool::globalInstance()->start(m_current_update_task.get()); } return true; @@ -378,25 +362,24 @@ void ResourceFolderModel::resolveResource(Resource::Ptr res) } Task::Ptr task{ createParseTask(*res) }; - if (!task) { + if (!task) return; - } - int ticket = m_nextResolutionTicket.fetch_add(1); + int ticket = m_next_resolution_ticket.fetch_add(1); res->setResolving(true, ticket); - m_activeParseTasks.insert(ticket, task); + m_active_parse_tasks.insert(ticket, task); connect( - task.get(), &Task::succeeded, this, [this, ticket, res] { onParseSucceeded(ticket, res->internalId()); }, + task.get(), &Task::succeeded, this, [this, ticket, res] { onParseSucceeded(ticket, res->internal_id()); }, Qt::ConnectionType::QueuedConnection); connect( - task.get(), &Task::failed, this, [this, ticket, res] { onParseFailed(ticket, res->internalId()); }, + task.get(), &Task::failed, this, [this, ticket, res] { onParseFailed(ticket, res->internal_id()); }, Qt::ConnectionType::QueuedConnection); connect( task.get(), &Task::finished, this, [this, ticket] { - m_activeParseTasks.remove(ticket); + m_active_parse_tasks.remove(ticket); emit parseFinished(); }, Qt::ConnectionType::QueuedConnection); @@ -411,45 +394,44 @@ void ResourceFolderModel::resolveResource(Resource::Ptr res) void ResourceFolderModel::onUpdateSucceeded() { - auto updateResults = static_cast(m_currentUpdateTask.get())->result(); + auto update_results = static_cast(m_current_update_task.get())->result(); - auto& newResources = updateResults->resources; + auto& new_resources = update_results->resources; - auto currentList = m_resourcesIndex.keys(); - QSet currentSet(currentList.begin(), currentList.end()); + auto current_list = m_resources_index.keys(); + QSet current_set(current_list.begin(), current_list.end()); - auto newList = newResources.keys(); - QSet newSet(newList.begin(), newList.end()); + auto new_list = new_resources.keys(); + QSet new_set(new_list.begin(), new_list.end()); - applyUpdates(currentSet, newSet, newResources); + applyUpdates(current_set, new_set, new_resources); } -void ResourceFolderModel::onParseSucceeded(int ticket, const QString& resourceId) +void ResourceFolderModel::onParseSucceeded(int ticket, QString resource_id) { - auto iter = m_activeParseTasks.constFind(ticket); - if (iter == m_activeParseTasks.constEnd() || !m_resourcesIndex.contains(resourceId)) { + auto iter = m_active_parse_tasks.constFind(ticket); + if (iter == m_active_parse_tasks.constEnd() || !m_resources_index.contains(resource_id)) return; - } - int row = m_resourcesIndex[resourceId]; + int row = m_resources_index[resource_id]; emit dataChanged(index(row), index(row, columnCount(QModelIndex()) - 1)); } Task* ResourceFolderModel::createUpdateTask() { - auto indexDir2 = indexDir(); - auto* task = new ResourceFolderLoadTask(dir(), indexDir2, m_isIndexed, m_firstFolderLoad, - [this](const QFileInfo& file) { return createResource(file); }); - m_firstFolderLoad = false; + auto index_dir = indexDir(); + auto task = new ResourceFolderLoadTask(dir(), index_dir, m_is_indexed, m_first_folder_load, + [this](const QFileInfo& file) { return createResource(file); }); + m_first_folder_load = false; return task; } bool ResourceFolderModel::hasPendingParseTasks() const { - return !m_activeParseTasks.isEmpty(); + return !m_active_parse_tasks.isEmpty(); } -void ResourceFolderModel::directoryChanged(const QString& /*path*/) +void ResourceFolderModel::directoryChanged(QString path) { update(); } @@ -464,9 +446,8 @@ Qt::ItemFlags ResourceFolderModel::flags(const QModelIndex& index) const { Qt::ItemFlags defaultFlags = QAbstractListModel::flags(index); auto flags = defaultFlags | Qt::ItemIsDropEnabled; - if (index.isValid()) { + if (index.isValid()) flags |= Qt::ItemIsUserCheckable; - } return flags; } @@ -477,25 +458,21 @@ QStringList ResourceFolderModel::mimeTypes() const return types; } -bool ResourceFolderModel::dropMimeData(const QMimeData* data, - Qt::DropAction action, - int /*row*/, - int /*column*/, - const QModelIndex& /*parent*/) +bool ResourceFolderModel::dropMimeData(const QMimeData* data, Qt::DropAction action, int, int, const QModelIndex&) { if (action == Qt::IgnoreAction) { return true; } // check if the action is supported - if ((data == nullptr) || !(action & supportedDropActions())) { + if (!data || !(action & supportedDropActions())) { return false; } // files dropped from outside? if (data->hasUrls()) { auto urls = data->urls(); - for (const auto& url : urls) { + for (auto url : urls) { // only local files may be dropped... if (!url.isLocalFile()) { continue; @@ -511,12 +488,14 @@ bool ResourceFolderModel::dropMimeData(const QMimeData* data, bool ResourceFolderModel::validateIndex(const QModelIndex& index) const { - if (!index.isValid()) { + if (!index.isValid()) return false; - } int row = index.row(); - return row >= 0 && row < m_resources.size(); + if (row < 0 || row >= m_resources.size()) + return false; + + return true; } // HACK: all subclasses need to call this to have the whole row painted @@ -525,15 +504,15 @@ QBrush ResourceFolderModel::rowBackground(int row) const { if (APPLICATION->settings()->get("ShowModIncompat").toBool() && m_resources[row]->hasIssues()) { return { QColor(255, 0, 0, 40) }; + } else { + return {}; } - return {}; } QVariant ResourceFolderModel::data(const QModelIndex& index, int role) const { - if (!validateIndex(index)) { + if (!validateIndex(index)) return {}; - } int row = index.row(); int column = index.column(); @@ -551,13 +530,11 @@ QVariant ResourceFolderModel::data(const QModelIndex& index, int role) const return m_resources[row]->provider(); case SizeColumn: return m_resources[row]->sizeStr(); - case FileNameColumn: - return m_resources[row]->fileinfo().fileName(); default: return {}; } case Qt::ToolTipRole: { - QString tooltip = m_resources[row]->internalId(); + QString tooltip = m_resources[row]->internal_id(); if (column == NameColumn) { if (APPLICATION->settings()->get("ShowModIncompat").toBool()) { @@ -568,7 +545,7 @@ QVariant ResourceFolderModel::data(const QModelIndex& index, int role) const if (at(row).isSymLinkUnder(instDirPath())) { tooltip += - m_resources[row]->internalId() + + m_resources[row]->internal_id() + tr("\nWarning: This resource is symbolically linked from elsewhere. Editing it will also change the original." "\nCanonical Path: %1") .arg(at(row).fileinfo().canonicalFilePath()); @@ -585,8 +562,7 @@ QVariant ResourceFolderModel::data(const QModelIndex& index, int role) const if (column == NameColumn) { if (APPLICATION->settings()->get("ShowModIncompat").toBool() && at(row).hasIssues()) { return QIcon::fromTheme("status-bad"); - } - if (at(row).isSymLinkUnder(instDirPath()) || at(row).isMoreThanOneHardLink()) { + } else if (at(row).isSymLinkUnder(instDirPath()) || at(row).isMoreThanOneHardLink()) { return QIcon::fromTheme("status-yellow"); } } @@ -594,9 +570,8 @@ QVariant ResourceFolderModel::data(const QModelIndex& index, int role) const return {}; } case Qt::CheckStateRole: - if (column == ActiveColumn) { + if (column == ActiveColumn) return m_resources[row]->enabled() ? Qt::Checked : Qt::Unchecked; - } return {}; default: return {}; @@ -606,9 +581,8 @@ QVariant ResourceFolderModel::data(const QModelIndex& index, int role) const bool ResourceFolderModel::setData(const QModelIndex& index, [[maybe_unused]] const QVariant& value, int role) { int row = index.row(); - if (row < 0 || row >= rowCount(index.parent()) || !index.isValid()) { + if (row < 0 || row >= rowCount(index.parent()) || !index.isValid()) return false; - } if (role == Qt::CheckStateRole) { return setResourceEnabled({ index }, EnableAction::TOGGLE); @@ -627,7 +601,6 @@ QVariant ResourceFolderModel::headerData(int section, [[maybe_unused]] Qt::Orien case DateColumn: case ProviderColumn: case SizeColumn: - case FileNameColumn: return columnNames().at(section); default: return {}; @@ -645,8 +618,6 @@ QVariant ResourceFolderModel::headerData(int section, [[maybe_unused]] Qt::Orien return tr("The source provider of the resource."); case SizeColumn: return tr("The size of the resource."); - case FileNameColumn: - return tr("The file name of the resource."); default: return {}; } @@ -667,22 +638,22 @@ void ResourceFolderModel::setupHeaderAction(QAction* act, int column) void ResourceFolderModel::saveColumns(QTreeView* tree) { - const auto stateSettingName = QString("UI/%1_Page/Columns").arg(id()); - const auto overrideSettingName = QString("UI/%1_Page/ColumnsOverride").arg(id()); - const auto visibilitySettingName = QString("UI/%1_Page/ColumnsVisibility").arg(id()); + auto const stateSettingName = QString("UI/%1_Page/Columns").arg(id()); + auto const overrideSettingName = QString("UI/%1_Page/ColumnsOverride").arg(id()); + auto const visibilitySettingName = QString("UI/%1_Page/ColumnsVisibility").arg(id()); auto stateSetting = m_instance->settings()->getSetting(stateSettingName); stateSetting->set(QString::fromUtf8(tree->header()->saveState().toBase64())); // neither passthrough nor override settings works for this usecase as I need to only set the global when the gate is false - auto* settings = m_instance->settings(); + auto settings = m_instance->settings(); if (!settings->get(overrideSettingName).toBool()) { settings = APPLICATION->settings(); } auto visibility = Json::toMap(settings->get(visibilitySettingName).toString()); - for (auto i = 0; i < m_columnNames.size(); ++i) { + for (auto i = 0; i < m_column_names.size(); ++i) { if (m_columnsHideable[i]) { - auto name = m_columnNames[i]; + auto name = m_column_names[i]; visibility[name] = !tree->isColumnHidden(i); } } @@ -691,24 +662,24 @@ void ResourceFolderModel::saveColumns(QTreeView* tree) void ResourceFolderModel::loadColumns(QTreeView* tree) { - const auto stateSettingName = QString("UI/%1_Page/Columns").arg(id()); - const auto overrideSettingName = QString("UI/%1_Page/ColumnsOverride").arg(id()); - const auto visibilitySettingName = QString("UI/%1_Page/ColumnsVisibility").arg(id()); + auto const stateSettingName = QString("UI/%1_Page/Columns").arg(id()); + auto const overrideSettingName = QString("UI/%1_Page/ColumnsOverride").arg(id()); + auto const visibilitySettingName = QString("UI/%1_Page/ColumnsVisibility").arg(id()); auto stateSetting = m_instance->settings()->getOrRegisterSetting(stateSettingName, ""); tree->header()->restoreState(QByteArray::fromBase64(stateSetting->get().toString().toUtf8())); - auto setVisible = [this, tree](const QVariant& value) { + auto setVisible = [this, tree](QVariant value) { auto visibility = Json::toMap(value.toString()); - for (auto i = 0; i < m_columnNames.size(); ++i) { + for (auto i = 0; i < m_column_names.size(); ++i) { if (m_columnsHideable[i]) { - auto name = m_columnNames[i]; + auto name = m_column_names[i]; tree->setColumnHidden(i, !visibility.value(name, false).toBool()); } } }; - const auto defaultValue = Json::fromMap({ + auto const defaultValue = Json::fromMap({ { "Image", true }, { "Version", true }, { "Last Modified", true }, @@ -716,7 +687,7 @@ void ResourceFolderModel::loadColumns(QTreeView* tree) { "Pack Format", true }, }); // neither passthrough nor override settings works for this usecase as I need to only set the global when the gate is false - auto* settings = m_instance->settings(); + auto settings = m_instance->settings(); if (!settings->getOrRegisterSetting(overrideSettingName, false)->get().toBool()) { settings = APPLICATION->settings(); } @@ -725,7 +696,7 @@ void ResourceFolderModel::loadColumns(QTreeView* tree) // allways connect the signal in case the setting is toggled on and off auto gSetting = APPLICATION->settings()->getOrRegisterSetting(visibilitySettingName, defaultValue); - connect(gSetting.get(), &Setting::SettingChanged, tree, [this, setVisible, overrideSettingName](const Setting&, const QVariant& value) { + connect(gSetting.get(), &Setting::SettingChanged, tree, [this, setVisible, overrideSettingName](const Setting&, QVariant value) { if (!m_instance->settings()->get(overrideSettingName).toBool()) { setVisible(value); } @@ -734,11 +705,11 @@ void ResourceFolderModel::loadColumns(QTreeView* tree) QMenu* ResourceFolderModel::createHeaderContextMenu(QTreeView* tree) { - auto* menu = new QMenu(tree); + auto menu = new QMenu(tree); { // action to decide if the visibility is per instance or not - auto* act = new QAction(tr("Override Columns Visibility"), menu); - const auto overrideSettingName = QString("UI/%1_Page/ColumnsOverride").arg(id()); + auto act = new QAction(tr("Override Columns Visibility"), menu); + auto const overrideSettingName = QString("UI/%1_Page/ColumnsOverride").arg(id()); act->setCheckable(true); act->setChecked(m_instance->settings()->getOrRegisterSetting(overrideSettingName, false)->get().toBool()); @@ -754,10 +725,9 @@ QMenu* ResourceFolderModel::createHeaderContextMenu(QTreeView* tree) for (int col = 0; col < columnCount(); ++col) { // Skip creating actions for columns that should not be hidden - if (!m_columnsHideable.at(col)) { + if (!m_columnsHideable.at(col)) continue; - } - auto* act = new QAction(menu); + auto act = new QAction(menu); setupHeaderAction(act, col); act->setCheckable(true); @@ -766,9 +736,8 @@ QMenu* ResourceFolderModel::createHeaderContextMenu(QTreeView* tree) connect(act, &QAction::toggled, tree, [this, col, tree](bool toggled) { tree->setColumnHidden(col, !toggled); for (int c = 0; c < columnCount(); ++c) { - if (m_columnResizeModes.at(c) == QHeaderView::ResizeToContents) { + if (m_column_resize_modes.at(c) == QHeaderView::ResizeToContents) tree->resizeColumnToContents(c); - } } saveColumns(tree); }); @@ -786,43 +755,41 @@ QSortFilterProxyModel* ResourceFolderModel::createFilterProxyModel(QObject* pare SortType ResourceFolderModel::columnToSortKey(size_t column) const { - Q_ASSERT(m_columnSortKeys.size() == columnCount()); - return m_columnSortKeys.at(column); + Q_ASSERT(m_column_sort_keys.size() == columnCount()); + return m_column_sort_keys.at(column); } /* Standard Proxy Model for createFilterProxyModel */ -bool ResourceFolderModel::ProxyModel::filterAcceptsRow(int sourceRow, [[maybe_unused]] const QModelIndex& sourceParent) const +bool ResourceFolderModel::ProxyModel::filterAcceptsRow(int source_row, [[maybe_unused]] const QModelIndex& source_parent) const { auto* model = qobject_cast(sourceModel()); - if (!model) { + if (!model) return true; - } - const auto& resource = model->at(sourceRow); + const auto& resource = model->at(source_row); return resource.applyFilter(filterRegularExpression()); } -bool ResourceFolderModel::ProxyModel::lessThan(const QModelIndex& sourceLeft, const QModelIndex& sourceRight) const +bool ResourceFolderModel::ProxyModel::lessThan(const QModelIndex& source_left, const QModelIndex& source_right) const { auto* model = qobject_cast(sourceModel()); - if (!model || !sourceLeft.isValid() || !sourceRight.isValid() || sourceLeft.column() != sourceRight.column()) { - return QSortFilterProxyModel::lessThan(sourceLeft, sourceRight); + if (!model || !source_left.isValid() || !source_right.isValid() || source_left.column() != source_right.column()) { + return QSortFilterProxyModel::lessThan(source_left, source_right); } // we are now guaranteed to have two valid indexes in the same column... we love the provided invariants unconditionally and // proceed. - auto columnSortKey = model->columnToSortKey(sourceLeft.column()); - const auto& resourceLeft = model->at(sourceLeft.row()); - const auto& resourceRight = model->at(sourceRight.row()); + auto column_sort_key = model->columnToSortKey(source_left.column()); + auto const& resource_left = model->at(source_left.row()); + auto const& resource_right = model->at(source_right.row()); - auto compareResult = resourceLeft.compare(resourceRight, columnSortKey); - if (compareResult == 0) { - return QSortFilterProxyModel::lessThan(sourceLeft, sourceRight); - } + auto compare_result = resource_left.compare(resource_right, column_sort_key); + if (compare_result == 0) + return QSortFilterProxyModel::lessThan(source_left, source_right); - return compareResult < 0; + return compare_result < 0; } QString ResourceFolderModel::instDirPath() const @@ -830,51 +797,50 @@ QString ResourceFolderModel::instDirPath() const return QFileInfo(m_instance->instanceRoot()).absoluteFilePath(); } -void ResourceFolderModel::onParseFailed(int ticket, const QString& resourceId) +void ResourceFolderModel::onParseFailed(int ticket, QString resource_id) { - auto iter = m_activeParseTasks.constFind(ticket); - if (iter == m_activeParseTasks.constEnd() || !m_resourcesIndex.contains(resourceId)) { + auto iter = m_active_parse_tasks.constFind(ticket); + if (iter == m_active_parse_tasks.constEnd() || !m_resources_index.contains(resource_id)) return; - } - auto removedIndex = m_resourcesIndex[resourceId]; - auto removedIt = m_resources.begin() + removedIndex; - Q_ASSERT(removedIt != m_resources.end()); + auto removed_index = m_resources_index[resource_id]; + auto removed_it = m_resources.begin() + removed_index; + Q_ASSERT(removed_it != m_resources.end()); - beginRemoveRows(QModelIndex(), removedIndex, removedIndex); - m_resources.erase(removedIt); + beginRemoveRows(QModelIndex(), removed_index, removed_index); + m_resources.erase(removed_it); // update index - m_resourcesIndex.clear(); + m_resources_index.clear(); int idx = 0; - for (const auto& mod : qAsConst(m_resources)) { - m_resourcesIndex[mod->internalId()] = idx; + for (auto const& mod : qAsConst(m_resources)) { + m_resources_index[mod->internal_id()] = idx; idx++; } endRemoveRows(); } -void ResourceFolderModel::applyUpdates(QSet& currentSet, QSet& newSet, QMap& newResources) +void ResourceFolderModel::applyUpdates(QSet& current_set, QSet& new_set, QMap& new_resources) { // see if the kept resources changed in some way { - QSet keptSet = currentSet; - keptSet.intersect(newSet); + QSet kept_set = current_set; + kept_set.intersect(new_set); - for (const auto& kept : keptSet) { - auto rowIt = m_resourcesIndex.constFind(kept); - Q_ASSERT(rowIt != m_resourcesIndex.constEnd()); - auto row = rowIt.value(); + for (auto const& kept : kept_set) { + auto row_it = m_resources_index.constFind(kept); + Q_ASSERT(row_it != m_resources_index.constEnd()); + auto row = row_it.value(); - auto& newResource = newResources[kept]; - const auto& currentResource = m_resources.at(row); + auto& new_resource = new_resources[kept]; + auto const& current_resource = m_resources.at(row); - if (newResource->dateTimeChanged() == currentResource->dateTimeChanged()) { + if (new_resource->dateTimeChanged() == current_resource->dateTimeChanged()) { // no significant change - bool hadIssues = !currentResource->hasIssues(); - currentResource->updateIssues(m_instance); + bool hadIssues = !current_resource->hasIssues(); + current_resource->updateIssues(m_instance); - if (hadIssues != currentResource->hasIssues()) { + if (hadIssues != current_resource->hasIssues()) { emit dataChanged(index(row, 0), index(row, columnCount({}) - 1)); } continue; @@ -882,16 +848,16 @@ void ResourceFolderModel::applyUpdates(QSet& currentSet, QSet& // If the resource is resolving, but something about it changed, we don't want to // continue the resolving. - if (currentResource->isResolving()) { - auto ticket = currentResource->resolutionTicket(); - if (m_activeParseTasks.contains(ticket)) { - auto* task = (*m_activeParseTasks.find(ticket)).get(); + if (current_resource->isResolving()) { + auto ticket = current_resource->resolutionTicket(); + if (m_active_parse_tasks.contains(ticket)) { + auto task = (*m_active_parse_tasks.find(ticket)).get(); task->abort(); } } - m_resources[row].reset(newResource); - newResource->updateIssues(m_instance); + m_resources[row].reset(new_resource); + new_resource->updateIssues(m_instance); resolveResource(m_resources.at(row)); emit dataChanged(index(row, 0), index(row, columnCount(QModelIndex()) - 1)); @@ -900,47 +866,46 @@ void ResourceFolderModel::applyUpdates(QSet& currentSet, QSet& // remove resources no longer present { - QSet removedSet = currentSet; - removedSet.subtract(newSet); + QSet removed_set = current_set; + removed_set.subtract(new_set); - QList removedRows; - for (const auto& removed : removedSet) { - removedRows.append(m_resourcesIndex[removed]); - } + QList removed_rows; + for (auto& removed : removed_set) + removed_rows.append(m_resources_index[removed]); - std::ranges::sort(removedRows, std::greater()); + std::sort(removed_rows.begin(), removed_rows.end(), std::greater()); - for (auto& removedIndex : removedRows) { - auto removedIt = m_resources.begin() + removedIndex; + for (auto& removed_index : removed_rows) { + auto removed_it = m_resources.begin() + removed_index; - Q_ASSERT(removedIt != m_resources.end()); + Q_ASSERT(removed_it != m_resources.end()); - if ((*removedIt)->isResolving()) { - auto ticket = (*removedIt)->resolutionTicket(); - if (m_activeParseTasks.contains(ticket)) { - auto* task = (*m_activeParseTasks.find(ticket)).get(); + if ((*removed_it)->isResolving()) { + auto ticket = (*removed_it)->resolutionTicket(); + if (m_active_parse_tasks.contains(ticket)) { + auto task = (*m_active_parse_tasks.find(ticket)).get(); task->abort(); } } - beginRemoveRows(QModelIndex(), removedIndex, removedIndex); - m_resources.erase(removedIt); + beginRemoveRows(QModelIndex(), removed_index, removed_index); + m_resources.erase(removed_it); endRemoveRows(); } } // add new resources to the end { - QSet addedSet = newSet; - addedSet.subtract(currentSet); + QSet added_set = new_set; + added_set.subtract(current_set); // When you have a Qt build with assertions turned on, proceeding here will abort the application - if (addedSet.size() > 0) { + if (added_set.size() > 0) { beginInsertRows(QModelIndex(), static_cast(m_resources.size()), - static_cast(m_resources.size() + addedSet.size() - 1)); + static_cast(m_resources.size() + added_set.size() - 1)); - for (const auto& added : addedSet) { - auto res = newResources[added]; + for (auto& added : added_set) { + auto res = new_resources[added]; res->updateIssues(m_instance); m_resources.append(res); resolveResource(m_resources.last()); @@ -952,10 +917,10 @@ void ResourceFolderModel::applyUpdates(QSet& currentSet, QSet& // update index { - m_resourcesIndex.clear(); + m_resources_index.clear(); int idx = 0; - for (const auto& mod : qAsConst(m_resources)) { - m_resourcesIndex[mod->internalId()] = idx; + for (auto const& mod : qAsConst(m_resources)) { + m_resources_index[mod->internal_id()] = idx; idx++; } } @@ -963,19 +928,17 @@ void ResourceFolderModel::applyUpdates(QSet& currentSet, QSet& Resource::Ptr ResourceFolderModel::find(QString id) { auto iter = - std::find_if(m_resources.constBegin(), m_resources.constEnd(), [&](const Resource::Ptr& r) { return r->internalId() == id; }); - if (iter == m_resources.constEnd()) { + std::find_if(m_resources.constBegin(), m_resources.constEnd(), [&](Resource::Ptr const& r) { return r->internal_id() == id; }); + if (iter == m_resources.constEnd()) return nullptr; - } return *iter; } QList ResourceFolderModel::allResources() { QList result; result.reserve(m_resources.size()); - for (const Resource ::Ptr& resource : m_resources) { + for (const Resource ::Ptr& resource : m_resources) result.append((resource.get())); - } return result; } @@ -983,9 +946,8 @@ QList ResourceFolderModel::selectedResources(const QModelIndexList& i { QList result; for (const QModelIndex& index : indexes) { - if (index.column() != 0) { + if (index.column() != 0) continue; - } result.append(&at(index.row())); } return result; diff --git a/launcher/minecraft/mod/ResourceFolderModel.h b/launcher/minecraft/mod/ResourceFolderModel.h index 7699394ab..81bc6f5fc 100644 --- a/launcher/minecraft/mod/ResourceFolderModel.h +++ b/launcher/minecraft/mod/ResourceFolderModel.h @@ -61,7 +61,7 @@ class QSortFilterProxyModel; class ResourceFolderModel : public QAbstractListModel { Q_OBJECT public: - ResourceFolderModel(const QDir& dir, BaseInstance* instance, bool isIndexed, bool createDir, QObject* parent = nullptr); + ResourceFolderModel(const QDir& dir, BaseInstance* instance, bool is_indexed, bool create_dir, QObject* parent = nullptr); ~ResourceFolderModel() override; virtual QString id() const { return "resource"; } @@ -93,13 +93,13 @@ class ResourceFolderModel : public QAbstractListModel { */ virtual bool installResource(QString path); - virtual void installResourceWithFlameMetadata(const QString& path, ModPlatform::IndexedVersion& vers); + virtual void installResourceWithFlameMetadata(QString path, ModPlatform::IndexedVersion& vers); /** Uninstall (i.e. remove all data about it) a resource, given its file name. * * Returns whether the removal was successful. */ - virtual bool uninstallResource(const QString& fileName, bool preserveMetadata = false); + virtual bool uninstallResource(const QString& file_name, bool preserve_metadata = false); virtual bool deleteResources(const QModelIndexList&); virtual void deleteMetadata(const QModelIndexList&); @@ -125,7 +125,7 @@ class ResourceFolderModel : public QAbstractListModel { Resource::Ptr find(QString id); - const QDir& dir() const { return m_dir; } + QDir const& dir() const { return m_dir; } /** Checks whether there's any parse tasks being done. * @@ -137,12 +137,12 @@ class ResourceFolderModel : public QAbstractListModel { /* Qt behavior */ /* Basic columns */ - enum Columns : std::uint8_t { ActiveColumn = 0, NameColumn, DateColumn, ProviderColumn, SizeColumn, FileNameColumn, NumColumns }; + enum Columns { ActiveColumn = 0, NameColumn, DateColumn, ProviderColumn, SizeColumn, NUM_COLUMNS }; - QStringList columnNames(bool translated = true) const { return translated ? m_columnNamesTranslated : m_columnNames; } + QStringList columnNames(bool translated = true) const { return translated ? m_column_names_translated : m_column_names; } int rowCount(const QModelIndex& parent = {}) const override { return parent.isValid() ? 0 : static_cast(size()); } - int columnCount(const QModelIndex& parent = {}) const override { return parent.isValid() ? 0 : NumColumns; } + int columnCount(const QModelIndex& parent = {}) const override { return parent.isValid() ? 0 : NUM_COLUMNS; } Qt::DropActions supportedDropActions() const override; @@ -171,19 +171,18 @@ class ResourceFolderModel : public QAbstractListModel { QSortFilterProxyModel* createFilterProxyModel(QObject* parent = nullptr); SortType columnToSortKey(size_t column) const; - QList columnResizeModes() const { return m_columnResizeModes; } + QList columnResizeModes() const { return m_column_resize_modes; } class ProxyModel : public QSortFilterProxyModel { public: explicit ProxyModel(QObject* parent = nullptr) : QSortFilterProxyModel(parent) {} protected: - bool filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const override; - bool lessThan(const QModelIndex& sourceLeft, const QModelIndex& sourceRight) const override; + bool filterAcceptsRow(int source_row, const QModelIndex& source_parent) const override; + bool lessThan(const QModelIndex& source_left, const QModelIndex& source_right) const override; }; QString instDirPath() const; - BaseInstance* instance() const { return m_instance; } signals: void updateFinished(); @@ -207,7 +206,7 @@ class ResourceFolderModel : public QAbstractListModel { * This task should load and parse all heavy info needed by a resource, such as parsing a manifest. It gets executed * in the background, so it slowly updates the UI as tasks get done. */ - [[nodiscard]] virtual Task* createParseTask(Resource& /*unused*/) { return nullptr; } + [[nodiscard]] virtual Task* createParseTask(Resource&) { return nullptr; } /** Standard implementation of the model update logic. * @@ -215,10 +214,10 @@ class ResourceFolderModel : public QAbstractListModel { * to act only on those disparities. * */ - void applyUpdates(QSet& currentSet, QSet& newSet, QMap& newResources); + void applyUpdates(QSet& current_set, QSet& new_set, QMap& new_resources); protected slots: - void directoryChanged(const QString&); + void directoryChanged(QString); /** Called when the update task is successful. * @@ -234,40 +233,39 @@ class ResourceFolderModel : public QAbstractListModel { * This is just a simple reference implementation. You probably want to override it with your own logic in a subclass * if the resource is complex and has more stuff to parse. */ - virtual void onParseSucceeded(int ticket, const QString& resourceId); - virtual void onParseFailed(int ticket, const QString& resourceId); + virtual void onParseSucceeded(int ticket, QString resource_id); + virtual void onParseFailed(int ticket, QString resource_id); protected: // Represents the relationship between a column's index (represented by the list index), and it's sorting key. // As such, the order in with they appear is very important! - QList m_columnSortKeys = { SortType::Enabled, SortType::Name, SortType::Date, - SortType::Provider, SortType::Size, SortType::Filename }; - QStringList m_columnNames = { "Enable", "Name", "Last Modified", "Provider", "Size", "File Name" }; - QStringList m_columnNamesTranslated = { tr("Enable"), tr("Name"), tr("Last Modified"), tr("Provider"), tr("Size"), tr("File Name") }; - QList m_columnResizeModes = { QHeaderView::Interactive, QHeaderView::Stretch, QHeaderView::Interactive, - QHeaderView::Interactive, QHeaderView::Interactive, QHeaderView::Interactive }; - QList m_columnsHideable = { false, false, true, true, true, true }; + QList m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::DATE, SortType::PROVIDER, SortType::SIZE }; + QStringList m_column_names = { "Enable", "Name", "Last Modified", "Provider", "Size" }; + QStringList m_column_names_translated = { tr("Enable"), tr("Name"), tr("Last Modified"), tr("Provider"), tr("Size") }; + QList m_column_resize_modes = { QHeaderView::Interactive, QHeaderView::Stretch, QHeaderView::Interactive, + QHeaderView::Interactive, QHeaderView::Interactive }; + QList m_columnsHideable = { false, false, true, true, true }; QDir m_dir; BaseInstance* m_instance; QFileSystemWatcher m_watcher; - bool m_isWatching = false; + bool m_is_watching = false; - bool m_isIndexed; - bool m_firstFolderLoad = true; + bool m_is_indexed; + bool m_first_folder_load = true; - Task::Ptr m_currentUpdateTask = nullptr; - bool m_scheduledUpdate = false; + Task::Ptr m_current_update_task = nullptr; + bool m_scheduled_update = false; QList m_resources; // Represents the relationship between a resource's internal ID and it's row position on the model. - QMap m_resourcesIndex; + QMap m_resources_index; // Runs off-thread ConcurrentTask m_resourceResolver; bool m_resourceResolverRunning = false; - QMap m_activeParseTasks; - std::atomic m_nextResolutionTicket = 0; + QMap m_active_parse_tasks; + std::atomic m_next_resolution_ticket = 0; }; diff --git a/launcher/minecraft/mod/ResourcePackFolderModel.cpp b/launcher/minecraft/mod/ResourcePackFolderModel.cpp index 4dd8e314c..b2a28290a 100644 --- a/launcher/minecraft/mod/ResourcePackFolderModel.cpp +++ b/launcher/minecraft/mod/ResourcePackFolderModel.cpp @@ -39,26 +39,27 @@ #include #include +#include "Version.h" + #include "minecraft/mod/tasks/LocalDataPackParseTask.h" -ResourcePackFolderModel::ResourcePackFolderModel(const QDir& dir, BaseInstance* instance, bool isIndexed, bool createDir, QObject* parent) - : ResourceFolderModel(dir, instance, isIndexed, createDir, parent) +ResourcePackFolderModel::ResourcePackFolderModel(const QDir& dir, BaseInstance* instance, bool is_indexed, bool create_dir, QObject* parent) + : ResourceFolderModel(dir, instance, is_indexed, create_dir, parent) { - m_columnNames = QStringList({ "Enable", "Image", "Name", "Pack Format", "Last Modified", "Provider", "Size", "File Name" }); - m_columnNamesTranslated = QStringList( - { tr("Enable"), tr("Image"), tr("Name"), tr("Pack Format"), tr("Last Modified"), tr("Provider"), tr("Size"), tr("File Name") }); - m_columnSortKeys = { SortType::Enabled, SortType::Name, SortType::Name, SortType::PackFormat, - SortType::Date, SortType::Provider, SortType::Size, SortType::Filename }; - m_columnResizeModes = { QHeaderView::Interactive, QHeaderView::Interactive, QHeaderView::Stretch, QHeaderView::Interactive, - QHeaderView::Interactive, QHeaderView::Interactive, QHeaderView::Interactive, QHeaderView::Interactive }; - m_columnsHideable = { false, true, false, true, true, true, true, true }; + m_column_names = QStringList({ "Enable", "Image", "Name", "Pack Format", "Last Modified", "Provider", "Size" }); + m_column_names_translated = + QStringList({ tr("Enable"), tr("Image"), tr("Name"), tr("Pack Format"), tr("Last Modified"), tr("Provider"), tr("Size") }); + m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::NAME, SortType::PACK_FORMAT, + SortType::DATE, SortType::PROVIDER, SortType::SIZE }; + m_column_resize_modes = { QHeaderView::Interactive, QHeaderView::Interactive, QHeaderView::Stretch, QHeaderView::Interactive, + QHeaderView::Interactive, QHeaderView::Interactive, QHeaderView::Interactive }; + m_columnsHideable = { false, true, false, true, true, true, true }; } QVariant ResourcePackFolderModel::data(const QModelIndex& index, int role) const { - if (!validateIndex(index)) { + if (!validateIndex(index)) return {}; - } int row = index.row(); int column = index.column(); @@ -91,8 +92,6 @@ QVariant ResourcePackFolderModel::data(const QModelIndex& index, int role) const return QSize(32, 32); } break; - default: - break; } // map the columns to the base equivilents @@ -113,11 +112,6 @@ QVariant ResourcePackFolderModel::data(const QModelIndex& index, int role) const case SizeColumn: mappedIndex = index.siblingAtColumn(ResourceFolderModel::SizeColumn); break; - case FileNameColumn: - mappedIndex = index.siblingAtColumn(ResourceFolderModel::FileNameColumn); - break; - default: - break; } if (mappedIndex.isValid()) { @@ -139,7 +133,6 @@ QVariant ResourcePackFolderModel::headerData(int section, [[maybe_unused]] Qt::O case ImageColumn: case ProviderColumn: case SizeColumn: - case FileNameColumn: return columnNames().at(section); default: return {}; @@ -160,8 +153,6 @@ QVariant ResourcePackFolderModel::headerData(int section, [[maybe_unused]] Qt::O return tr("The source provider of the resource pack."); case SizeColumn: return tr("The size of the resource pack."); - case FileNameColumn: - return tr("The file name of the resource pack."); default: return {}; } @@ -177,10 +168,10 @@ QVariant ResourcePackFolderModel::headerData(int section, [[maybe_unused]] Qt::O int ResourcePackFolderModel::columnCount(const QModelIndex& parent) const { - return parent.isValid() ? 0 : NumColumns; + return parent.isValid() ? 0 : NUM_COLUMNS; } Task* ResourcePackFolderModel::createParseTask(Resource& resource) { - return new LocalDataPackParseTask(m_nextResolutionTicket, dynamic_cast(&resource)); + return new LocalDataPackParseTask(m_next_resolution_ticket, dynamic_cast(&resource)); } diff --git a/launcher/minecraft/mod/ResourcePackFolderModel.h b/launcher/minecraft/mod/ResourcePackFolderModel.h index 186bbb75d..b552c324e 100644 --- a/launcher/minecraft/mod/ResourcePackFolderModel.h +++ b/launcher/minecraft/mod/ResourcePackFolderModel.h @@ -7,19 +7,9 @@ class ResourcePackFolderModel : public ResourceFolderModel { Q_OBJECT public: - enum Columns : std::uint8_t { - ActiveColumn = 0, - ImageColumn, - NameColumn, - PackFormatColumn, - DateColumn, - ProviderColumn, - SizeColumn, - FileNameColumn, - NumColumns - }; + enum Columns { ActiveColumn = 0, ImageColumn, NameColumn, PackFormatColumn, DateColumn, ProviderColumn, SizeColumn, NUM_COLUMNS }; - explicit ResourcePackFolderModel(const QDir& dir, BaseInstance* instance, bool isIndexed, bool createDir, QObject* parent = nullptr); + explicit ResourcePackFolderModel(const QDir& dir, BaseInstance* instance, bool is_indexed, bool create_dir, QObject* parent = nullptr); QString id() const override { return "resourcepacks"; } @@ -29,7 +19,7 @@ class ResourcePackFolderModel : public ResourceFolderModel { int columnCount(const QModelIndex& parent) const override; [[nodiscard]] Resource* createResource(const QFileInfo& file) override { return new ResourcePack(file); } - [[nodiscard]] Task* createParseTask(Resource& /*unused*/) override; + [[nodiscard]] Task* createParseTask(Resource&) override; RESOURCE_HELPERS(ResourcePack) }; diff --git a/launcher/minecraft/mod/ShaderPackFolderModel.h b/launcher/minecraft/mod/ShaderPackFolderModel.h index ded641770..9b0180180 100644 --- a/launcher/minecraft/mod/ShaderPackFolderModel.h +++ b/launcher/minecraft/mod/ShaderPackFolderModel.h @@ -18,7 +18,7 @@ class ShaderPackFolderModel : public ResourceFolderModel { [[nodiscard]] Task* createParseTask(Resource& resource) override { - return new LocalShaderPackParseTask(m_nextResolutionTicket, static_cast(resource)); + return new LocalShaderPackParseTask(m_next_resolution_ticket, static_cast(resource)); } QDir indexDir() const override { return m_dir; } diff --git a/launcher/minecraft/mod/TexturePackFolderModel.cpp b/launcher/minecraft/mod/TexturePackFolderModel.cpp index 976bf3854..d96b768db 100644 --- a/launcher/minecraft/mod/TexturePackFolderModel.cpp +++ b/launcher/minecraft/mod/TexturePackFolderModel.cpp @@ -36,30 +36,28 @@ #include "TexturePackFolderModel.h" #include "minecraft/mod/tasks/LocalTexturePackParseTask.h" +#include "minecraft/mod/tasks/ResourceFolderLoadTask.h" -TexturePackFolderModel::TexturePackFolderModel(const QDir& dir, BaseInstance* instance, bool isIndexed, bool createDir, QObject* parent) - : ResourceFolderModel(QDir(dir), instance, isIndexed, createDir, parent) +TexturePackFolderModel::TexturePackFolderModel(const QDir& dir, BaseInstance* instance, bool is_indexed, bool create_dir, QObject* parent) + : ResourceFolderModel(QDir(dir), instance, is_indexed, create_dir, parent) { - m_columnNames = QStringList({ "Enable", "Image", "Name", "Last Modified", "Provider", "Size", "File Name" }); - m_columnNamesTranslated = - QStringList({ tr("Enable"), tr("Image"), tr("Name"), tr("Last Modified"), tr("Provider"), tr("Size"), tr("File Name") }); - m_columnSortKeys = { SortType::Enabled, SortType::Name, SortType::Name, SortType::Date, - SortType::Provider, SortType::Size, SortType::Filename }; - m_columnResizeModes = { QHeaderView::Interactive, QHeaderView::Interactive, QHeaderView::Stretch, QHeaderView::Interactive, - QHeaderView::Interactive, QHeaderView::Interactive, QHeaderView::Interactive }; - m_columnsHideable = { false, true, false, true, true, true, true }; + m_column_names = QStringList({ "Enable", "Image", "Name", "Last Modified", "Provider", "Size" }); + m_column_names_translated = QStringList({ tr("Enable"), tr("Image"), tr("Name"), tr("Last Modified"), tr("Provider"), tr("Size") }); + m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::NAME, SortType::DATE, SortType::PROVIDER, SortType::SIZE }; + m_column_resize_modes = { QHeaderView::Interactive, QHeaderView::Interactive, QHeaderView::Stretch, + QHeaderView::Interactive, QHeaderView::Interactive, QHeaderView::Interactive }; + m_columnsHideable = { false, true, false, true, true, true }; } Task* TexturePackFolderModel::createParseTask(Resource& resource) { - return new LocalTexturePackParseTask(m_nextResolutionTicket, static_cast(resource)); + return new LocalTexturePackParseTask(m_next_resolution_ticket, static_cast(resource)); } QVariant TexturePackFolderModel::data(const QModelIndex& index, int role) const { - if (!validateIndex(index)) { + if (!validateIndex(index)) return {}; - } int row = index.row(); int column = index.column(); @@ -78,8 +76,6 @@ QVariant TexturePackFolderModel::data(const QModelIndex& index, int role) const return QSize(32, 32); } break; - default: - break; } // map the columns to the base equivilents @@ -100,11 +96,6 @@ QVariant TexturePackFolderModel::data(const QModelIndex& index, int role) const case SizeColumn: mappedIndex = index.siblingAtColumn(ResourceFolderModel::SizeColumn); break; - case FileNameColumn: - mappedIndex = index.siblingAtColumn(ResourceFolderModel::FileNameColumn); - break; - default: - break; } if (mappedIndex.isValid()) { @@ -125,7 +116,6 @@ QVariant TexturePackFolderModel::headerData(int section, [[maybe_unused]] Qt::Or case ImageColumn: case ProviderColumn: case SizeColumn: - case FileNameColumn: return columnNames().at(section); default: return {}; @@ -142,8 +132,6 @@ QVariant TexturePackFolderModel::headerData(int section, [[maybe_unused]] Qt::Or return tr("The source provider of the texture pack."); case SizeColumn: return tr("The size of the texture pack."); - case FileNameColumn: - return tr("The file name of the texture pack."); default: return {}; } @@ -157,5 +145,5 @@ QVariant TexturePackFolderModel::headerData(int section, [[maybe_unused]] Qt::Or int TexturePackFolderModel::columnCount(const QModelIndex& parent) const { - return parent.isValid() ? 0 : NumColumns; + return parent.isValid() ? 0 : NUM_COLUMNS; } diff --git a/launcher/minecraft/mod/TexturePackFolderModel.h b/launcher/minecraft/mod/TexturePackFolderModel.h index 3e7343092..37f78d8d7 100644 --- a/launcher/minecraft/mod/TexturePackFolderModel.h +++ b/launcher/minecraft/mod/TexturePackFolderModel.h @@ -44,20 +44,11 @@ class TexturePackFolderModel : public ResourceFolderModel { Q_OBJECT public: - enum Columns : std::uint8_t { - ActiveColumn = 0, - ImageColumn, - NameColumn, - DateColumn, - ProviderColumn, - SizeColumn, - FileNameColumn, - NumColumns - }; + enum Columns { ActiveColumn = 0, ImageColumn, NameColumn, DateColumn, ProviderColumn, SizeColumn, NUM_COLUMNS }; - explicit TexturePackFolderModel(const QDir& dir, BaseInstance* instance, bool isIndexed, bool createDir, QObject* parent = nullptr); + explicit TexturePackFolderModel(const QDir& dir, BaseInstance* instance, bool is_indexed, bool create_dir, QObject* parent = nullptr); - QString id() const override { return "texturepacks"; } + virtual QString id() const override { return "texturepacks"; } QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; @@ -65,7 +56,7 @@ class TexturePackFolderModel : public ResourceFolderModel { int columnCount(const QModelIndex& parent) const override; [[nodiscard]] Resource* createResource(const QFileInfo& file) override { return new TexturePack(file); } - [[nodiscard]] Task* createParseTask(Resource& /*unused*/) override; + [[nodiscard]] Task* createParseTask(Resource&) override; RESOURCE_HELPERS(TexturePack) }; diff --git a/launcher/minecraft/mod/tasks/ResourceFolderLoadTask.cpp b/launcher/minecraft/mod/tasks/ResourceFolderLoadTask.cpp index a90e9ca5e..3b98e053b 100644 --- a/launcher/minecraft/mod/tasks/ResourceFolderLoadTask.cpp +++ b/launcher/minecraft/mod/tasks/ResourceFolderLoadTask.cpp @@ -41,28 +41,26 @@ #include "minecraft/mod/MetadataHandler.h" #include -#include -ResourceFolderLoadTask::ResourceFolderLoadTask(const QDir& resourceDir, - const QDir& indexDir, - bool isIndexed, - bool cleanOrphan, - std::function createFunction) +ResourceFolderLoadTask::ResourceFolderLoadTask(const QDir& resource_dir, + const QDir& index_dir, + bool is_indexed, + bool clean_orphan, + std::function create_function) : Task(false) - , m_resource_dir(resourceDir) - , m_index_dir(indexDir) - , m_is_indexed(isIndexed) - , m_clean_orphan(cleanOrphan) - , m_create_func(std::move(createFunction)) + , m_resource_dir(resource_dir) + , m_index_dir(index_dir) + , m_is_indexed(is_indexed) + , m_clean_orphan(clean_orphan) + , m_create_func(create_function) , m_result(new Result()) , m_thread_to_spawn_into(thread()) {} void ResourceFolderLoadTask::executeTask() { - if (thread() != m_thread_to_spawn_into) { + if (thread() != m_thread_to_spawn_into) connect(this, &Task::finished, this->thread(), &QThread::quit); - } if (m_is_indexed) { // Read metadata first @@ -73,7 +71,7 @@ void ResourceFolderLoadTask::executeTask() m_resource_dir.refresh(); for (auto entry : m_resource_dir.entryInfoList()) { auto filePath = entry.absoluteFilePath(); - if (auto* app = APPLICATION_DYN; (app != nullptr) && app->checkQSavePath(filePath)) { + if (auto app = APPLICATION_DYN; app && app->checkQSavePath(filePath)) { continue; } auto newFilePath = FS::getUniqueResourceName(filePath); @@ -85,29 +83,29 @@ void ResourceFolderLoadTask::executeTask() Resource* resource = m_create_func(entry); if (resource->enabled()) { - if (m_result->resources.contains(resource->internalId())) { - m_result->resources[resource->internalId()]->setStatus(ResourceStatus::Installed); + if (m_result->resources.contains(resource->internal_id())) { + m_result->resources[resource->internal_id()]->setStatus(ResourceStatus::INSTALLED); // Delete the object we just created, since a valid one is already in the mods list. delete resource; } else { - m_result->resources[resource->internalId()].reset(resource); - m_result->resources[resource->internalId()]->setStatus(ResourceStatus::NoMetadata); + m_result->resources[resource->internal_id()].reset(resource); + m_result->resources[resource->internal_id()]->setStatus(ResourceStatus::NO_METADATA); } } else { - QString choppedId = resource->internalId().chopped(9); - if (m_result->resources.contains(choppedId)) { - m_result->resources[resource->internalId()].reset(resource); + QString chopped_id = resource->internal_id().chopped(9); + if (m_result->resources.contains(chopped_id)) { + m_result->resources[resource->internal_id()].reset(resource); - auto metadata = m_result->resources[choppedId]->metadata(); + auto metadata = m_result->resources[chopped_id]->metadata(); if (metadata) { resource->setMetadata(*metadata); - m_result->resources[resource->internalId()]->setStatus(ResourceStatus::Installed); - m_result->resources.remove(choppedId); + m_result->resources[resource->internal_id()]->setStatus(ResourceStatus::INSTALLED); + m_result->resources.remove(chopped_id); } } else { - m_result->resources[resource->internalId()].reset(resource); - m_result->resources[resource->internalId()]->setStatus(ResourceStatus::NoMetadata); + m_result->resources[resource->internal_id()].reset(resource); + m_result->resources[resource->internal_id()]->setStatus(ResourceStatus::NO_METADATA); } } } @@ -118,41 +116,38 @@ void ResourceFolderLoadTask::executeTask() QMutableMapIterator iter(m_result->resources); while (iter.hasNext()) { auto resource = iter.next().value(); - if (resource->status() == ResourceStatus::NotInstalled) { + if (resource->status() == ResourceStatus::NOT_INSTALLED) { resource->destroy(m_index_dir, false, false); iter.remove(); } } } - for (const auto& mod : m_result->resources) { + for (auto mod : m_result->resources) mod->moveToThread(m_thread_to_spawn_into); - } - if (m_aborted) { + if (m_aborted) emit finished(); - } else { + else emitSucceeded(); - } } void ResourceFolderLoadTask::getFromMetadata() { m_index_dir.refresh(); - for (const auto& entry : m_index_dir.entryList(QDir::Files)) { + for (auto entry : m_index_dir.entryList(QDir::Files)) { if (!entry.endsWith(".pw.toml")) { continue; } auto metadata = Metadata::get(m_index_dir, entry); - if (!metadata.isValid()) { + if (!metadata.isValid()) continue; - } auto* resource = m_create_func(QFileInfo(m_resource_dir.filePath(metadata.filename))); resource->setMetadata(metadata); - resource->setStatus(ResourceStatus::NotInstalled); - m_result->resources[resource->internalId()].reset(resource); + resource->setStatus(ResourceStatus::NOT_INSTALLED); + m_result->resources[resource->internal_id()].reset(resource); } } diff --git a/launcher/minecraft/mod/tasks/ResourceFolderLoadTask.h b/launcher/minecraft/mod/tasks/ResourceFolderLoadTask.h index 6489176b7..7c872c13d 100644 --- a/launcher/minecraft/mod/tasks/ResourceFolderLoadTask.h +++ b/launcher/minecraft/mod/tasks/ResourceFolderLoadTask.h @@ -41,7 +41,7 @@ #include #include #include -#include "minecraft/mod/Resource.h" +#include "minecraft/mod/Mod.h" #include "tasks/Task.h" class ResourceFolderLoadTask : public Task { @@ -54,11 +54,11 @@ class ResourceFolderLoadTask : public Task { ResultPtr result() const { return m_result; } public: - ResourceFolderLoadTask(const QDir& resourceDir, - const QDir& indexDir, - bool isIndexed, - bool cleanOrphan, - std::function createFunction); + ResourceFolderLoadTask(const QDir& resource_dir, + const QDir& index_dir, + bool is_indexed, + bool clean_orphan, + std::function create_function); bool canAbort() const override { return true; } bool abort() override @@ -76,7 +76,7 @@ class ResourceFolderLoadTask : public Task { QDir m_resource_dir, m_index_dir; bool m_is_indexed; bool m_clean_orphan; - std::function m_create_func; + std::function m_create_func; ResultPtr m_result; std::atomic m_aborted = false; diff --git a/launcher/minecraft/skins/SkinList.cpp b/launcher/minecraft/skins/SkinList.cpp index c960b9493..b47f17db5 100644 --- a/launcher/minecraft/skins/SkinList.cpp +++ b/launcher/minecraft/skins/SkinList.cpp @@ -121,7 +121,7 @@ bool SkinList::update() auto folderContents = m_dir.entryInfoList(); // if there are any untracked files... for (QFileInfo entry : folderContents) { - if (!entry.isFile() || entry.suffix() != "png") + if (!entry.isFile() && entry.suffix() != "png") continue; SkinModel w(entry.absoluteFilePath()); diff --git a/launcher/modplatform/CheckUpdateTask.h b/launcher/modplatform/CheckUpdateTask.h index ad68fd963..d3f577f44 100644 --- a/launcher/modplatform/CheckUpdateTask.h +++ b/launcher/modplatform/CheckUpdateTask.h @@ -15,15 +15,15 @@ class CheckUpdateTask : public Task { std::vector& mcVersions, QList loadersList, ResourceFolderModel* resourceModel) - : m_resources(resources), m_gameVersions(mcVersions), m_loadersList(std::move(loadersList)), m_resourceModel(resourceModel) + : Task(), m_resources(resources), m_gameVersions(mcVersions), m_loadersList(std::move(loadersList)), m_resourceModel(resourceModel) {} struct Update { QString name; - QString oldHash; - QString oldVersion; - QString newVersion; - std::optional newVersionType; + QString old_hash; + QString old_version; + QString new_version; + std::optional new_version_type; QString changelog; ModPlatform::ResourceProvider provider; shared_qobject_ptr download; @@ -31,19 +31,19 @@ class CheckUpdateTask : public Task { public: Update(QString name, - QString oldH, - QString oldV, - QString newV, - std::optional newVType, + QString old_h, + QString old_v, + QString new_v, + std::optional new_v_type, QString changelog, ModPlatform::ResourceProvider p, shared_qobject_ptr t, bool enabled = true) : name(std::move(name)) - , oldHash(std::move(oldH)) - , oldVersion(std::move(oldV)) - , newVersion(std::move(newV)) - , newVersionType(newVType) + , old_hash(std::move(old_h)) + , old_version(std::move(old_v)) + , new_version(std::move(new_v)) + , new_version_type(std::move(new_v_type)) , changelog(std::move(changelog)) , provider(p) , download(std::move(t)) @@ -54,11 +54,14 @@ class CheckUpdateTask : public Task { auto getUpdates() -> std::vector&& { return std::move(m_updates); } auto getDependencies() -> QList>&& { return std::move(m_deps); } + public slots: + bool abort() override = 0; + protected slots: void executeTask() override = 0; signals: - void checkFailed(Resource* failed, QString reason, QUrl recoverUrl = {}); + void checkFailed(Resource* failed, QString reason, QUrl recover_url = {}); protected: QList& m_resources; diff --git a/launcher/modplatform/EnsureMetadataTask.cpp b/launcher/modplatform/EnsureMetadataTask.cpp index 2c7e485e5..1ef3a56c9 100644 --- a/launcher/modplatform/EnsureMetadataTask.cpp +++ b/launcher/modplatform/EnsureMetadataTask.cpp @@ -99,7 +99,7 @@ void EnsureMetadataTask::executeTask() } // They already have the right metadata :o - if (resource->status() != ResourceStatus::NoMetadata && resource->metadata() && resource->metadata()->provider == m_provider) { + if (resource->status() != ResourceStatus::NO_METADATA && resource->metadata() && resource->metadata()->provider == m_provider) { qDebug() << "Resource" << resource->name() << "already has metadata!"; emitReady(resource); continue; @@ -263,7 +263,7 @@ Task::Ptr EnsureMetadataTask::modrinthVersionsTask() Task::Ptr EnsureMetadataTask::modrinthProjectsTask() { QHash addonIds; - for (const auto& data : m_tempVersions) + for (auto const& data : m_tempVersions) addonIds.insert(data.addonId.toString(), data.hash); Task::Ptr proj_task; @@ -404,7 +404,7 @@ Task::Ptr EnsureMetadataTask::flameVersionsTask() Task::Ptr EnsureMetadataTask::flameProjectsTask() { QHash addonIds; - for (const auto& hash : m_resources.keys()) { + for (auto const& hash : m_resources.keys()) { if (m_tempVersions.contains(hash)) { auto data = m_tempVersions.find(hash).value(); diff --git a/launcher/modplatform/ModIndex.h b/launcher/modplatform/ModIndex.h index 8984e575e..e1278ae84 100644 --- a/launcher/modplatform/ModIndex.h +++ b/launcher/modplatform/ModIndex.h @@ -32,7 +32,6 @@ class QIODevice; namespace ModPlatform { enum class ModLoaderType : std::uint16_t { - None = 0U, NeoForge = 1U << 0U, Forge = 1U << 1U, Cauldron = 1U << 2U, diff --git a/launcher/modplatform/ResourceAPI.cpp b/launcher/modplatform/ResourceAPI.cpp index bd683ed21..cda90b677 100644 --- a/launcher/modplatform/ResourceAPI.cpp +++ b/launcher/modplatform/ResourceAPI.cpp @@ -148,9 +148,9 @@ Task::Ptr ResourceAPI::getProjectVersions(VersionSearchArgs&& args, Callback&& callbacks, bool askRetry) const +Task::Ptr ResourceAPI::getProjectInfo(ProjectInfoArgs&& args, Callback&& callbacks) const { - auto [job, response] = getProject(args.pack->addonId.toString(), askRetry); + auto [job, response] = getProject(args.pack->addonId.toString()); QObject::connect(job.get(), &NetJob::succeeded, [this, response, callbacks, args] { auto pack = args.pack; @@ -284,7 +284,7 @@ QString ResourceAPI::mapMCVersionToModrinth(Version v) const return verStr; } -std::pair ResourceAPI::getProject(QString addonId, bool askRetry) const +std::pair ResourceAPI::getProject(QString addonId) const { auto project_url_optional = getInfoURL(addonId); if (!project_url_optional.has_value()) @@ -293,7 +293,6 @@ std::pair ResourceAPI::getProject(QString addonId, bool auto project_url = project_url_optional.value(); auto netJob = makeShared(QString("%1::GetProject").arg(addonId), APPLICATION->network()); - netJob->setAskRetry(askRetry); auto [action, response] = Net::ApiDownload::makeByteArray(QUrl(project_url)); netJob->addNetAction(action); diff --git a/launcher/modplatform/ResourceAPI.h b/launcher/modplatform/ResourceAPI.h index 51b6d4b50..0ad55775c 100644 --- a/launcher/modplatform/ResourceAPI.h +++ b/launcher/modplatform/ResourceAPI.h @@ -115,10 +115,10 @@ class ResourceAPI { public slots: virtual Task::Ptr searchProjects(SearchArgs&&, Callback>&&) const; - virtual std::pair getProject(QString addonId, bool askRetry = true) const; + virtual std::pair getProject(QString addonId) const; virtual std::pair getProjects(QStringList addonIds) const = 0; - virtual Task::Ptr getProjectInfo(ProjectInfoArgs&&, Callback&&, bool askRetry = true) const; + virtual Task::Ptr getProjectInfo(ProjectInfoArgs&&, Callback&&) const; Task::Ptr getProjectVersions(VersionSearchArgs&& args, Callback>&& callbacks) const; virtual Task::Ptr getDependencyVersion(DependencySearchArgs&&, Callback&&) const; diff --git a/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp b/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp index f3f66997b..7a7365fbc 100644 --- a/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp +++ b/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp @@ -38,7 +38,6 @@ #include #include -#include #include "FileSystem.h" #include "Json.h" @@ -60,28 +59,18 @@ #include "BuildConfig.h" #include "ui/dialogs/BlockedModsDialog.h" -namespace { -bool isPathTraversal(const QString& basePath, const QString& entryName) -{ - auto safeName = FS::RemoveInvalidPathChars(entryName); - auto fullPath = FS::PathCombine(basePath, safeName); - auto baseUrl = QUrl::fromLocalFile(basePath); - return !baseUrl.isParentOf(QUrl::fromLocalFile(fullPath)); -} - -Meta::Version::Ptr getComponentVersion(const QString& uid, const QString& version) -{ - return APPLICATION->metadataIndex()->getLoadedVersion(uid, version); -} -} // namespace - namespace ATLauncher { +static Meta::Version::Ptr getComponentVersion(const QString& uid, const QString& version); + PackInstallTask::PackInstallTask(UserInteractionSupport* support, QString packName, QString version, InstallMode installMode) - : m_support(support), m_install_mode(installMode), m_pack_name(packName), m_version_name(std::move(version)) { + m_support = support; + m_pack_name = packName; static const QRegularExpression s_regex("[^A-Za-z0-9]"); m_pack_safe_name = packName.replace(s_regex, ""); + m_version_name = version; + m_install_mode = installMode; } bool PackInstallTask::abort() @@ -118,10 +107,11 @@ void PackInstallTask::onDownloadSucceeded(QByteArray* responsePtr) QByteArray response = std::move(*responsePtr); jobPtr.reset(); - QJsonParseError parseError{}; - QJsonDocument doc = QJsonDocument::fromJson(response, &parseError); - if (parseError.error != QJsonParseError::NoError) { - qWarning() << "Error while parsing JSON response from ATLauncher at" << parseError.offset << "reason:" << parseError.errorString(); + QJsonParseError parse_error{}; + QJsonDocument doc = QJsonDocument::fromJson(response, &parse_error); + if (parse_error.error != QJsonParseError::NoError) { + qWarning() << "Error while parsing JSON response from ATLauncher at" << parse_error.offset + << "reason:" << parse_error.errorString(); qWarning() << response; return; } @@ -138,7 +128,7 @@ void PackInstallTask::onDownloadSucceeded(QByteArray* responsePtr) // Derived from the installation mode QString message; - bool resetDirectory = false; + bool resetDirectory; switch (m_install_mode) { case InstallMode::Reinstall: @@ -158,9 +148,8 @@ void PackInstallTask::onDownloadSucceeded(QByteArray* responsePtr) } // Display message if one exists - if (!message.isEmpty()) { + if (!message.isEmpty()) m_support->displayMessage(message); - } auto ver = getComponentVersion("net.minecraft", m_version.minecraft); if (!ver) { @@ -184,7 +173,7 @@ void PackInstallTask::onDownloadFailed(QString reason) { qDebug() << "PackInstallTask::onDownloadFailed:" << QThread::currentThreadId(); jobPtr.reset(); - emitFailed(std::move(reason)); + emitFailed(reason); } void PackInstallTask::onDownloadAborted() @@ -213,30 +202,26 @@ void PackInstallTask::deleteExistingFiles() keeps.files.append(VersionKeep{ "root", "servers.dat" }); // Merge with version deletes and keeps - for (const auto& item : m_version.deletes.files) { + for (const auto& item : m_version.deletes.files) deletes.files.append(item); - } - for (const auto& item : m_version.deletes.folders) { + for (const auto& item : m_version.deletes.folders) deletes.folders.append(item); - } - for (const auto& item : m_version.keeps.files) { + for (const auto& item : m_version.keeps.files) keeps.files.append(item); - } - for (const auto& item : m_version.keeps.folders) { + for (const auto& item : m_version.keeps.folders) keeps.folders.append(item); - } auto getPathForBase = [this](const QString& base) { auto minecraftPath = FS::PathCombine(m_stagingPath, "minecraft"); if (base == "root") { return minecraftPath; - } - if (base == "config") { + } else if (base == "config") { return FS::PathCombine(minecraftPath, "config"); + } else { + qWarning() << "Unrecognised base path" << base; + return minecraftPath; } - qWarning() << "Unrecognised base path" << base; - return minecraftPath; }; auto convertToSystemPath = [](const QString& path) { @@ -246,22 +231,24 @@ void PackInstallTask::deleteExistingFiles() }; auto shouldKeep = [keeps, getPathForBase, convertToSystemPath](const QString& fullPath) { - if (std::ranges::any_of(keeps.files, [&fullPath, &getPathForBase, &convertToSystemPath](const auto& item) { - auto basePath = getPathForBase(item.base); - auto targetPath = convertToSystemPath(item.target); - auto path = FS::PathCombine(basePath, targetPath); - return fullPath == path; - })) { - return true; + for (const auto& item : keeps.files) { + auto basePath = getPathForBase(item.base); + auto targetPath = convertToSystemPath(item.target); + auto path = FS::PathCombine(basePath, targetPath); + + if (fullPath == path) { + return true; + } } - if (std::ranges::any_of(keeps.folders, [&fullPath, &getPathForBase, &convertToSystemPath](const auto& item) { - auto basePath = getPathForBase(item.base); - auto targetPath = convertToSystemPath(item.target); - auto path = FS::PathCombine(basePath, targetPath); - return fullPath.startsWith(path); - })) { - return true; + for (const auto& item : keeps.folders) { + auto basePath = getPathForBase(item.base); + auto targetPath = convertToSystemPath(item.target); + auto path = FS::PathCombine(basePath, targetPath); + + if (fullPath.startsWith(path)) { + return true; + } } return false; @@ -275,9 +262,8 @@ void PackInstallTask::deleteExistingFiles() auto targetPath = convertToSystemPath(item.target); auto fullPath = FS::PathCombine(basePath, targetPath); - if (shouldKeep(fullPath)) { + if (shouldKeep(fullPath)) continue; - } filesToDelete.insert(fullPath); } @@ -291,9 +277,8 @@ void PackInstallTask::deleteExistingFiles() while (it.hasNext()) { auto path = it.next(); - if (shouldKeep(path)) { + if (shouldKeep(path)) continue; - } filesToDelete.insert(path); } @@ -305,7 +290,7 @@ void PackInstallTask::deleteExistingFiles() } } -QString PackInstallTask::getDirForModType(ModType type, const QString& raw) +QString PackInstallTask::getDirForModType(ModType type, QString raw) { switch (type) { // Mod types that can either be ignored at this stage, or ignored @@ -353,7 +338,7 @@ QString PackInstallTask::getDirForModType(ModType type, const QString& raw) return Q_NULLPTR; } -QString PackInstallTask::getVersionForLoader(const QString& uid) +QString PackInstallTask::getVersionForLoader(QString uid) { if (m_version.loader.recommended || m_version.loader.latest || m_version.loader.choose) { auto vlist = APPLICATION->metadataIndex()->get(uid); @@ -374,19 +359,16 @@ QString PackInstallTask::getVersionForLoader(const QString& uid) // filtering for those loaders. if (m_version.loader.type != "fabric") { auto iter = std::find_if(reqs.begin(), reqs.end(), [](const Meta::Require& req) { return req.uid == "net.minecraft"; }); - if (iter == reqs.end()) { + if (iter == reqs.end()) continue; - } - if (iter->equalsVersion != m_version.minecraft) { + if (iter->equalsVersion != m_version.minecraft) continue; - } } if (m_version.loader.recommended) { // first recommended build we find, we use. - if (!version->isRecommended()) { + if (!version->isRecommended()) continue; - } } return version->descriptor(); @@ -394,8 +376,7 @@ QString PackInstallTask::getVersionForLoader(const QString& uid) emitFailed(tr("Failed to find version for %1 loader").arg(m_version.loader.type)); return Q_NULLPTR; - } - if (m_version.loader.choose) { + } else if (m_version.loader.choose) { // Fabric Loader doesn't depend on a given Minecraft version. if (m_version.loader.type == "fabric") { return m_support->chooseVersion(vlist, Q_NULLPTR); @@ -439,8 +420,7 @@ QString PackInstallTask::detectLibrary(const VersionLibrary& library) if (name == QString("guava")) { return "com.google.guava:guava:" + version; - } - if (name == QString("commons-lang3")) { + } else if (name == QString("commons-lang3")) { return "org.apache.commons:commons-lang3:" + version; } } @@ -448,7 +428,7 @@ QString PackInstallTask::detectLibrary(const VersionLibrary& library) return "org.multimc.atlauncher:" + library.md5 + ":1"; } -bool PackInstallTask::createLibrariesComponent(const QString& instanceRoot, PackProfile* profile) +bool PackInstallTask::createLibrariesComponent(QString instanceRoot, PackProfile* profile) { if (m_version.libraries.isEmpty()) { return true; @@ -473,18 +453,18 @@ bool PackInstallTask::createLibrariesComponent(const QString& instanceRoot, Pack } auto id = QUuid::createUuid().toString(QUuid::WithoutBraces); - auto targetId = "org.multimc.atlauncher." + id; + auto target_id = "org.multimc.atlauncher." + id; auto patchDir = FS::PathCombine(instanceRoot, "patches"); if (!FS::ensureFolderPathExists(patchDir)) { return false; } - auto patchFileName = FS::PathCombine(patchDir, targetId + ".json"); + auto patchFileName = FS::PathCombine(patchDir, target_id + ".json"); auto f = std::make_shared(); f->name = m_pack_name + " " + m_version_name + " (libraries)"; - const static QMap s_liteLoaderMap = { + const static QMap liteLoaderMap = { { "61179803bcd5fb7790789b790908663d", "1.12-SNAPSHOT" }, { "1420785ecbfed5aff4a586c5c9dd97eb", "1.12.2-SNAPSHOT" }, { "073f68e2fcb518b91fd0d99462441714", "1.6.2_03" }, { "10a15b52fc59b1bfb9c05b56de1097d6", "1.6.2_02" }, { "b52f90f08303edd3d4c374e268a5acf1", "1.6.2_04" }, { "ea747e24e03e24b7cad5bc8a246e0319", "1.6.2_01" }, @@ -504,8 +484,8 @@ bool PackInstallTask::createLibrariesComponent(const QString& instanceRoot, Pack for (const auto& lib : m_version.libraries) { // If the library is LiteLoader, we need to ignore it and handle it separately. - if (s_liteLoaderMap.contains(lib.md5)) { - auto ver = getComponentVersion("com.mumfrey.liteloader", s_liteLoaderMap.value(lib.md5)); + if (liteLoaderMap.contains(lib.md5)) { + auto ver = getComponentVersion("com.mumfrey.liteloader", liteLoaderMap.value(lib.md5)); if (ver) { componentsToInstall.insert("com.mumfrey.liteloader", ver); continue; @@ -522,9 +502,8 @@ bool PackInstallTask::createLibrariesComponent(const QString& instanceRoot, Pack libExempt = Version(libSpecifier.version()) >= Version(existingLib.version()); } } - if (libExempt) { + if (libExempt) continue; - } auto library = std::make_shared(); library->setRawName(libName); @@ -557,11 +536,11 @@ bool PackInstallTask::createLibrariesComponent(const QString& instanceRoot, Pack file.write(OneSixVersionFormat::versionFileToJson(f).toJson()); file.close(); - profile->appendComponent(ComponentPtr{ new Component(profile, targetId, f) }); + profile->appendComponent(ComponentPtr{ new Component(profile, target_id, f) }); return true; } -bool PackInstallTask::createPackComponent(const QString& instanceRoot, PackProfile* profile) +bool PackInstallTask::createPackComponent(QString instanceRoot, PackProfile* profile) { if (m_version.mainClass.mainClass.isEmpty() && m_version.extraArguments.arguments.isEmpty()) { return true; @@ -592,13 +571,13 @@ bool PackInstallTask::createPackComponent(const QString& instanceRoot, PackProfi } auto id = QUuid::createUuid().toString(QUuid::WithoutBraces); - auto targetId = "org.multimc.atlauncher." + id; + auto target_id = "org.multimc.atlauncher." + id; auto patchDir = FS::PathCombine(instanceRoot, "patches"); if (!FS::ensureFolderPathExists(patchDir)) { return false; } - auto patchFileName = FS::PathCombine(patchDir, targetId + ".json"); + auto patchFileName = FS::PathCombine(patchDir, target_id + ".json"); QStringList mainClasses; QStringList tweakers; @@ -625,9 +604,8 @@ bool PackInstallTask::createPackComponent(const QString& instanceRoot, PackProfi for (auto arg : args) { if (arg.startsWith("--tweakClass=") || previous == "--tweakClass") { auto tweakClass = arg.remove("--tweakClass="); - if (tweakers.contains(tweakClass)) { + if (tweakers.contains(tweakClass)) continue; - } f->addTweakers.append(tweakClass); } @@ -646,7 +624,7 @@ bool PackInstallTask::createPackComponent(const QString& instanceRoot, PackProfi file.write(OneSixVersionFormat::versionFileToJson(f).toJson()); file.close(); - profile->appendComponent(ComponentPtr{ new Component(profile, targetId, f) }); + profile->appendComponent(ComponentPtr{ new Component(profile, target_id, f) }); return true; } @@ -676,7 +654,7 @@ void PackInstallTask::installConfigs() connect(jobPtr.get(), &NetJob::failed, [this](QString reason) { abortable = false; jobPtr.reset(); - emitFailed(std::move(reason)); + emitFailed(reason); }); connect(jobPtr.get(), &NetJob::progress, [this](qint64 current, qint64 total) { abortable = true; @@ -733,17 +711,15 @@ void PackInstallTask::downloadMods() jarmods.clear(); jobPtr.reset(new NetJob(tr("Mod download"), APPLICATION->network())); - QList blockedMods; + QList blocked_mods; for (const auto& mod : m_version.mods) { // skip non-client mods - if (!mod.client) { + if (!mod.client) continue; - } // skip optional mods that were not selected - if (mod.optional && !selectedMods.contains(mod.name)) { + if (mod.optional && !selectedMods.contains(mod.name)) continue; - } QString url; switch (mod.download) { @@ -751,7 +727,7 @@ void PackInstallTask::downloadMods() url = BuildConfig.ATL_DOWNLOAD_SERVER_URL + mod.url; break; case DownloadType::Browser: { - blockedMods.append(mod); + blocked_mods.append(mod); continue; } case DownloadType::Direct: @@ -787,9 +763,8 @@ void PackInstallTask::downloadMods() jobPtr->addNetAction(dl); } else { auto relpath = getDirForModType(mod.type, mod.type_raw); - if (relpath == Q_NULLPTR) { + if (relpath == Q_NULLPTR) continue; - } auto entry = APPLICATION->metacache()->resolveEntry("ATLauncherPacks", cacheName); entry->setStale(true); @@ -823,51 +798,49 @@ void PackInstallTask::downloadMods() modsToCopy[entry->getFullPath()] = path; } } - if (!blockedMods.isEmpty()) { + if (!blocked_mods.isEmpty()) { QList mods; - for (const auto& mod : blockedMods) { - BlockedMod blockedMod; - blockedMod.name = mod.file; - blockedMod.websiteUrl = mod.url; - blockedMod.hash = mod.md5; - blockedMod.matched = false; - blockedMod.localPath = ""; + for (auto mod : blocked_mods) { + BlockedMod blocked_mod; + blocked_mod.name = mod.file; + blocked_mod.websiteUrl = mod.url; + blocked_mod.hash = mod.md5; + blocked_mod.matched = false; + blocked_mod.localPath = ""; - mods.append(blockedMod); + mods.append(blocked_mod); } qWarning() << "Blocked mods found, displaying mod list"; - BlockedModsDialog messageDialog(nullptr, tr("Blocked mods found"), - tr("The following files are not available for download in third party launchers.
" - "You will need to manually download them and add them to the instance."), - mods, "md5"); + BlockedModsDialog message_dialog(nullptr, tr("Blocked mods found"), + tr("The following files are not available for download in third party launchers.
" + "You will need to manually download them and add them to the instance."), + mods, "md5"); - messageDialog.setModal(true); + message_dialog.setModal(true); - if (messageDialog.exec() != 0) { + if (message_dialog.exec()) { qDebug() << "Post dialog blocked mods list:" << mods; - for (const auto& blocked : mods) { + for (auto blocked : mods) { if (!blocked.matched) { qDebug() << blocked.name << "was not matched to a local file, skipping copy"; continue; } - auto modIter = - std::ranges::find_if(blockedMods, [blocked](const VersionMod& mod) { return mod.url == blocked.websiteUrl; }); - if (modIter == blockedMods.end()) { + auto modIter = std::find_if(blocked_mods.begin(), blocked_mods.end(), + [blocked](const VersionMod& mod) { return mod.url == blocked.websiteUrl; }); + if (modIter == blocked_mods.end()) continue; - } - const auto& mod = *modIter; + auto mod = *modIter; if (mod.type == ModType::Extract || mod.type == ModType::TexturePackExtract || mod.type == ModType::ResourcePackExtract) { modsToExtract.insert(blocked.localPath, mod); } else if (mod.type == ModType::Decomp) { modsToDecomp.insert(blocked.localPath, mod); } else { auto relpath = getDirForModType(mod.type, mod.type_raw); - if (relpath == Q_NULLPTR) { + if (relpath == Q_NULLPTR) continue; - } auto path = FS::PathCombine(m_stagingPath, "minecraft", relpath, mod.file); @@ -945,8 +918,8 @@ bool PackInstallTask::extractMods(const QMap& toExtract, setStatus(tr("Extracting mods...")); for (auto iter = toExtract.begin(); iter != toExtract.end(); iter++) { - const auto& modPath = iter.key(); - const auto& mod = iter.value(); + auto& modPath = iter.key(); + auto& mod = iter.value(); QString extractToDir; if (mod.type == ModType::Extract) { @@ -965,10 +938,6 @@ bool PackInstallTask::extractMods(const QMap& toExtract, folderToExtract = mod.extractFolder; static const QRegularExpression s_regex("^/"); folderToExtract.remove(s_regex); - if (isPathTraversal(extractToPath, folderToExtract)) { - qWarning() << "Blocked path traversal in" << mod.extractFolder; - return false; - } } qDebug() << "Extracting " + mod.file + " to " + extractToDir; @@ -979,18 +948,13 @@ bool PackInstallTask::extractMods(const QMap& toExtract, } for (auto iter = toDecomp.begin(); iter != toDecomp.end(); iter++) { - const auto& modPath = iter.key(); - const auto& mod = iter.value(); + auto& modPath = iter.key(); + auto& mod = iter.value(); auto extractToDir = getDirForModType(mod.decompType, mod.decompType_raw); QDir extractDir(m_stagingPath); auto extractToPath = FS::PathCombine(extractDir.absolutePath(), "minecraft", extractToDir, mod.decompFile); - if (isPathTraversal(extractToPath, mod.decompFile)) { - qWarning() << "Blocked path traversal in decompFile" << mod.decompFile; - return false; - } - qDebug() << "Extracting " + mod.decompFile + " to " + extractToDir; if (!MMCZip::extractFile(modPath, mod.decompFile, extractToPath)) { qWarning() << "Failed to extract" << mod.decompFile; @@ -999,8 +963,8 @@ bool PackInstallTask::extractMods(const QMap& toExtract, } for (auto iter = toCopy.begin(); iter != toCopy.end(); iter++) { - const auto& from = iter.key(); - const auto& to = iter.value(); + auto& from = iter.key(); + auto& to = iter.value(); // If the file already exists, assume the mod is the correct copy - and remove // the copy from the Configs.zip @@ -1030,7 +994,7 @@ void PackInstallTask::install() MinecraftInstance instance(m_globalSettings, std::make_unique(instanceConfigPath), m_stagingPath); { SettingsObject::Lock lock(instance.settings()); - auto* components = instance.getPackProfile(); + auto components = instance.getPackProfile(); components->buildingFromScratch(); // Use a component to add libraries BEFORE Minecraft @@ -1045,23 +1009,20 @@ void PackInstallTask::install() // Loader if (m_version.loader.type == QString("forge")) { auto version = getVersionForLoader("net.minecraftforge"); - if (version == Q_NULLPTR) { + if (version == Q_NULLPTR) return; - } components->setComponentVersion("net.minecraftforge", version); } else if (m_version.loader.type == QString("neoforge")) { auto version = getVersionForLoader("net.neoforged"); - if (version == Q_NULLPTR) { + if (version == Q_NULLPTR) return; - } components->setComponentVersion("net.neoforged", version); } else if (m_version.loader.type == QString("fabric")) { auto version = getVersionForLoader("net.fabricmc.fabric-loader"); - if (version == Q_NULLPTR) { + if (version == Q_NULLPTR) return; - } components->setComponentVersion("net.fabricmc.fabric-loader", version); } else if (m_version.loader.type != QString()) { @@ -1094,4 +1055,9 @@ void PackInstallTask::install() emitSucceeded(); } +static Meta::Version::Ptr getComponentVersion(const QString& uid, const QString& version) +{ + return APPLICATION->metadataIndex()->getLoadedVersion(uid, version); +} + } // namespace ATLauncher diff --git a/launcher/modplatform/atlauncher/ATLPackInstallTask.h b/launcher/modplatform/atlauncher/ATLPackInstallTask.h index e8df132be..d1ffdfe7d 100644 --- a/launcher/modplatform/atlauncher/ATLPackInstallTask.h +++ b/launcher/modplatform/atlauncher/ATLPackInstallTask.h @@ -44,13 +44,14 @@ #include "minecraft/MinecraftInstance.h" #include "minecraft/PackProfile.h" #include "net/NetJob.h" +#include "settings/INISettingsObject.h" -#include +#include #include namespace ATLauncher { -enum class InstallMode : std::uint8_t { +enum class InstallMode { Install, Reinstall, Update, @@ -85,13 +86,13 @@ class PackInstallTask : public InstanceTask { QString packName, QString version, InstallMode installMode = InstallMode::Install); - ~PackInstallTask() override { delete m_support; } + virtual ~PackInstallTask() { delete m_support; } bool canAbort() const override { return true; } bool abort() override; protected: - void executeTask() override; + virtual void executeTask() override; private slots: void onDownloadSucceeded(QByteArray* responsePtr); @@ -102,12 +103,12 @@ class PackInstallTask : public InstanceTask { void onModsExtracted(); private: - QString getDirForModType(ModType type, const QString& raw); - QString getVersionForLoader(const QString& uid); - static QString detectLibrary(const VersionLibrary& library); + QString getDirForModType(ModType type, QString raw); + QString getVersionForLoader(QString uid); + QString detectLibrary(const VersionLibrary& library); - bool createLibrariesComponent(const QString& instanceRoot, PackProfile* profile); - bool createPackComponent(const QString& instanceRoot, PackProfile* profile); + bool createLibrariesComponent(QString instanceRoot, PackProfile* profile); + bool createPackComponent(QString instanceRoot, PackProfile* profile); void deleteExistingFiles(); void installConfigs(); diff --git a/launcher/modplatform/flame/FlameAPI.h b/launcher/modplatform/flame/FlameAPI.h index e77d53a4b..607b32cab 100644 --- a/launcher/modplatform/flame/FlameAPI.h +++ b/launcher/modplatform/flame/FlameAPI.h @@ -79,7 +79,6 @@ class FlameAPI : public ResourceAPI { case ModPlatform::LegacyFabric: case ModPlatform::Ornithe: case ModPlatform::Rift: - case ModPlatform::None: break; // not supported } return 0; diff --git a/launcher/modplatform/flame/FlameCheckUpdate.cpp b/launcher/modplatform/flame/FlameCheckUpdate.cpp index 577f9967a..37f0bcb32 100644 --- a/launcher/modplatform/flame/FlameCheckUpdate.cpp +++ b/launcher/modplatform/flame/FlameCheckUpdate.cpp @@ -18,6 +18,8 @@ #include "net/NetJob.h" #include "tasks/Task.h" +static FlameAPI api; + bool FlameCheckUpdate::abort() { bool result = false; @@ -37,7 +39,7 @@ void FlameCheckUpdate::executeTask() { setStatus(tr("Preparing resources for CurseForge...")); - auto* netJob = new NetJob("Get latest versions", APPLICATION->network()); + auto netJob = new NetJob("Get latest versions", APPLICATION->network()); connect(netJob, &Task::finished, this, &FlameCheckUpdate::collectBlockedMods); connect(netJob, &Task::progress, this, &FlameCheckUpdate::setProgress); @@ -46,10 +48,9 @@ void FlameCheckUpdate::executeTask() for (auto* resource : m_resources) { auto project = std::make_shared(); project->addonId = resource->metadata()->project_id.toString(); - auto versionsUrlOptional = FlameAPI().getVersionsURL({ .pack = project, .mcVersions = m_gameVersions }); - if (!versionsUrlOptional.has_value()) { + auto versionsUrlOptional = api.getVersionsURL({ project, m_gameVersions }); + if (!versionsUrlOptional.has_value()) continue; - } auto [task, response] = Net::ApiDownload::makeByteArray(versionsUrlOptional.value()); @@ -62,11 +63,11 @@ void FlameCheckUpdate::executeTask() void FlameCheckUpdate::getLatestVersionCallback(Resource* resource, QByteArray* response) { - QJsonParseError parseError{}; - QJsonDocument doc = QJsonDocument::fromJson(*response, &parseError); - if (parseError.error != QJsonParseError::NoError) { - qWarning() << "Error while parsing JSON response from latest mod version at" << parseError.offset - << "reason:" << parseError.errorString(); + QJsonParseError parse_error{}; + QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error); + if (parse_error.error != QJsonParseError::NoError) { + qWarning() << "Error while parsing JSON response from latest mod version at" << parse_error.offset + << "reason:" << parse_error.errorString(); qWarning() << *response; return; } @@ -87,104 +88,100 @@ void FlameCheckUpdate::getLatestVersionCallback(Resource* resource, QByteArray* qCritical() << e.what(); qDebug() << doc; } - auto latestVer = FlameAPI().getLatestVersion(pack->versions, m_loadersList, resource->metadata()->loaders, !m_loadersList.isEmpty()); + auto latest_ver = api.getLatestVersion(pack->versions, m_loadersList, resource->metadata()->loaders, !m_loadersList.isEmpty()); setStatus(tr("Parsing the API response from CurseForge for '%1'...").arg(resource->name())); - if (!latestVer.has_value() || !latestVer->addonId.isValid()) { + if (!latest_ver.has_value() || !latest_ver->addonId.isValid()) { QString reason; - if (dynamic_cast(resource) != nullptr) { + if (dynamic_cast(resource) != nullptr) reason = tr("No valid version found for this resource. It's probably unavailable for the current game " "version / mod loader."); - } else { + else reason = tr("No valid version found for this resource. It's probably unavailable for the current game version."); - } emit checkFailed(resource, reason); return; } - if (latestVer->downloadUrl.isEmpty() && latestVer->fileId != resource->metadata()->file_id) { - m_blocked[resource] = latestVer->fileId.toString(); + if (latest_ver->downloadUrl.isEmpty() && latest_ver->fileId != resource->metadata()->file_id) { + m_blocked[resource] = latest_ver->fileId.toString(); return; } - if (!latestVer->hash.isEmpty() && - (resource->metadata()->hash != latestVer->hash || resource->status() == ResourceStatus::NotInstalled)) { - auto oldVersion = resource->metadata()->version_number; - if (oldVersion.isEmpty()) { - if (resource->status() == ResourceStatus::NotInstalled) { - oldVersion = tr("Not installed"); - } else { - oldVersion = tr("Unknown"); - } + if (!latest_ver->hash.isEmpty() && + (resource->metadata()->hash != latest_ver->hash || resource->status() == ResourceStatus::NOT_INSTALLED)) { + auto old_version = resource->metadata()->version_number; + if (old_version.isEmpty()) { + if (resource->status() == ResourceStatus::NOT_INSTALLED) + old_version = tr("Not installed"); + else + old_version = tr("Unknown"); } - auto downloadTask = makeShared(pack, latestVer.value(), m_resourceModel, true, "update"); - m_updates.emplace_back(pack->name, resource->metadata()->hash, oldVersion, latestVer->version, latestVer->version_type, - FlameAPI().getModFileChangelog(latestVer->addonId.toInt(), latestVer->fileId.toInt()), - ModPlatform::ResourceProvider::FLAME, downloadTask, resource->enabled()); + auto download_task = makeShared(pack, latest_ver.value(), m_resourceModel); + m_updates.emplace_back(pack->name, resource->metadata()->hash, old_version, latest_ver->version, latest_ver->version_type, + api.getModFileChangelog(latest_ver->addonId.toInt(), latest_ver->fileId.toInt()), + ModPlatform::ResourceProvider::FLAME, download_task, resource->enabled()); } - m_deps.append(std::make_shared(pack, latestVer.value())); + m_deps.append(std::make_shared(pack, latest_ver.value())); } void FlameCheckUpdate::collectBlockedMods() { QStringList addonIds; QHash quickSearch; - for (const auto& resource : m_blocked.keys()) { + for (auto const& resource : m_blocked.keys()) { auto addonId = resource->metadata()->project_id.toString(); addonIds.append(addonId); quickSearch[addonId] = resource; } Task::Ptr projTask; - QByteArray* response = nullptr; + QByteArray* response; if (addonIds.isEmpty()) { emitSucceeded(); return; - } - if (addonIds.size() == 1) { - std::tie(projTask, response) = FlameAPI().getProject(*addonIds.begin()); + } else if (addonIds.size() == 1) { + std::tie(projTask, response) = api.getProject(*addonIds.begin()); } else { - std::tie(projTask, response) = FlameAPI().getProjects(addonIds); + std::tie(projTask, response) = api.getProjects(addonIds); } connect(projTask.get(), &Task::succeeded, this, [this, response, addonIds, quickSearch] { - QJsonParseError parseError{}; - auto doc = QJsonDocument::fromJson(*response, &parseError); - if (parseError.error != QJsonParseError::NoError) { - qWarning() << "Error while parsing JSON response from Flame projects task at" << parseError.offset - << "reason:" << parseError.errorString(); + QJsonParseError parse_error{}; + auto doc = QJsonDocument::fromJson(*response, &parse_error); + if (parse_error.error != QJsonParseError::NoError) { + qWarning() << "Error while parsing JSON response from Flame projects task at" << parse_error.offset + << "reason:" << parse_error.errorString(); qWarning() << *response; return; } try { QJsonArray entries; - if (addonIds.size() == 1) { + if (addonIds.size() == 1) entries = { Json::requireObject(Json::requireObject(doc), "data") }; - } else { + else entries = Json::requireArray(Json::requireObject(doc), "data"); - } for (auto entry : entries) { - auto entryObj = Json::requireObject(entry); + auto entry_obj = Json::requireObject(entry); - auto id = QString::number(Json::requireInteger(entryObj, "id")); + auto id = QString::number(Json::requireInteger(entry_obj, "id")); - auto* resource = quickSearch.find(id).value(); + auto resource = quickSearch.find(id).value(); ModPlatform::IndexedPack pack; try { setStatus(tr("Parsing API response from CurseForge for '%1'...").arg(resource->name())); - FlameMod::loadIndexedPack(pack, entryObj); - auto recoverUrl = QString("%1/download/%2").arg(pack.websiteUrl, m_blocked[resource]); + FlameMod::loadIndexedPack(pack, entry_obj); + auto recover_url = QString("%1/download/%2").arg(pack.websiteUrl, m_blocked[resource]); emit checkFailed(resource, tr("Resource has a new update available, but is not downloadable using CurseForge."), - recoverUrl); + recover_url); } catch (Json::JsonException& e) { qDebug() << e.cause(); qDebug() << entries; diff --git a/launcher/modplatform/helpers/ExportToModList.h b/launcher/modplatform/helpers/ExportToModList.h index 7cbe730f2..ab7797fe6 100644 --- a/launcher/modplatform/helpers/ExportToModList.h +++ b/launcher/modplatform/helpers/ExportToModList.h @@ -23,9 +23,7 @@ namespace ExportToModList { enum Formats { HTML, MARKDOWN, PLAINTXT, JSON, CSV, CUSTOM }; -enum OptionalDataValue { None = 0, Authors = 1 << 0, Url = 1 << 1, Version = 1 << 2, FileName = 1 << 3 }; -Q_DECLARE_FLAGS(OptionalData, OptionalDataValue) - +enum OptionalData { Authors = 1 << 0, Url = 1 << 1, Version = 1 << 2, FileName = 1 << 3 }; QString exportToModList(QList mods, Formats format, OptionalData extraData); QString exportToModList(QList mods, QString lineTemplate); } // namespace ExportToModList diff --git a/launcher/modplatform/import_ftb/PackInstallTask.cpp b/launcher/modplatform/import_ftb/PackInstallTask.cpp index 659c5d2ed..878ef26fa 100644 --- a/launcher/modplatform/import_ftb/PackInstallTask.cpp +++ b/launcher/modplatform/import_ftb/PackInstallTask.cpp @@ -63,12 +63,12 @@ void PackInstallTask::copySettings() instance.settings()->set("JvmArgs", m_pack.jvmArgs.toString()); } - auto* components = instance.getPackProfile(); + auto components = instance.getPackProfile(); components->buildingFromScratch(); components->setComponentVersion("net.minecraft", m_pack.mcVersion, true); auto modloader = m_pack.loaderType; - if (modloader.has_value()) { + if (modloader.has_value()) switch (modloader.value()) { case ModPlatform::NeoForge: { components->setComponentVersion("net.neoforged", m_pack.loaderVersion, true); @@ -86,16 +86,28 @@ void PackInstallTask::copySettings() components->setComponentVersion("org.quiltmc.quilt-loader", m_pack.loaderVersion, true); break; } - default: + case ModPlatform::Cauldron: + break; + case ModPlatform::LiteLoader: + break; + case ModPlatform::DataPack: + break; + case ModPlatform::Babric: + break; + case ModPlatform::BTA: + break; + case ModPlatform::LegacyFabric: + break; + case ModPlatform::Ornithe: + break; + case ModPlatform::Rift: break; } - } components->saveNow(); instance.setName(name()); - if (m_instIcon == "default") { + if (m_instIcon == "default") m_instIcon = "ftb_logo"; - } instance.setIconKey(m_instIcon); } emitSucceeded(); diff --git a/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp b/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp index 0fda37e57..bd5a50d1b 100644 --- a/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp +++ b/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp @@ -53,7 +53,7 @@ void ModrinthCheckUpdate::executeTask() setStatus(tr("Preparing resources for Modrinth...")); setProgress(0, ((m_loadersList.isEmpty() ? 1 : m_loadersList.length()) * 2) + 1); - auto hashingTask = + auto hashing_task = makeShared("MakeModrinthHashesTask", APPLICATION->settings()->get("NumberOfConcurrentTasks").toInt()); bool startHasing = false; for (auto* resource : m_resources) { @@ -63,11 +63,10 @@ void ModrinthCheckUpdate::executeTask() // need to generate a new hash if the current one is innadequate // (though it will rarely happen, if at all) if (resource->metadata()->hash_format != m_hashType) { - auto hashTask = Hashing::createHasher(resource->fileinfo().absoluteFilePath(), ModPlatform::ResourceProvider::MODRINTH); - connect(hashTask.get(), &Hashing::Hasher::resultsReady, - [this, resource](const QString& hash) { m_mappings.insert(hash, resource); }); - connect(hashTask.get(), &Task::failed, [this] { failed("Failed to generate hash"); }); - hashingTask->addTask(hashTask); + auto hash_task = Hashing::createHasher(resource->fileinfo().absoluteFilePath(), ModPlatform::ResourceProvider::MODRINTH); + connect(hash_task.get(), &Hashing::Hasher::resultsReady, [this, resource](QString hash) { m_mappings.insert(hash, resource); }); + connect(hash_task.get(), &Task::failed, [this] { failed("Failed to generate hash"); }); + hashing_task->addTask(hash_task); startHasing = true; } else { m_mappings.insert(hash, resource); @@ -75,9 +74,9 @@ void ModrinthCheckUpdate::executeTask() } if (startHasing) { - connect(hashingTask.get(), &Task::finished, this, &ModrinthCheckUpdate::checkNextLoader); - m_job = hashingTask; - hashingTask->start(); + connect(hashing_task.get(), &Task::finished, this, &ModrinthCheckUpdate::checkNextLoader); + m_job = hashing_task; + hashing_task->start(); } else { checkNextLoader(); } @@ -121,14 +120,14 @@ void ModrinthCheckUpdate::checkVersionsResponse(QByteArray* response, std::optio setStatus(tr("Parsing the API response from Modrinth...")); setProgress(m_progress + 1, m_progressTotal); - QJsonParseError parseError{}; - QJsonDocument doc = QJsonDocument::fromJson(*response, &parseError); - if (parseError.error != QJsonParseError::NoError) { - qWarning() << "Error while parsing JSON response from ModrinthCheckUpdate at" << parseError.offset - << "reason:" << parseError.errorString(); + QJsonParseError parse_error{}; + QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error); + if (parse_error.error != QJsonParseError::NoError) { + qWarning() << "Error while parsing JSON response from ModrinthCheckUpdate at" << parse_error.offset + << "reason:" << parse_error.errorString(); qWarning() << *response; - emitFailed(parseError.errorString()); + emitFailed(parse_error.errorString()); return; } @@ -139,11 +138,11 @@ void ModrinthCheckUpdate::checkVersionsResponse(QByteArray* response, std::optio const QString hash = iter.key(); Resource* resource = iter.value(); - auto projectObj = doc[hash].toObject(); + auto project_obj = doc[hash].toObject(); // If the returned project is empty, but we have Modrinth metadata, // it means this specific version is not available - if (projectObj.isEmpty()) { + if (project_obj.isEmpty()) { qDebug() << "Mod" << m_mappings.find(hash).value()->name() << "got an empty response. Hash:" << hash; ++iter; continue; @@ -151,11 +150,11 @@ void ModrinthCheckUpdate::checkVersionsResponse(QByteArray* response, std::optio // Sometimes a version may have multiple files, one with "forge" and one with "fabric", // so we may want to filter it - QString loaderFilter; + QString loader_filter; if (loader.has_value() && loader != 0) { auto modLoaders = ModPlatform::modLoaderTypesToList(*loader); if (!modLoaders.isEmpty()) { - loaderFilter = ModPlatform::getModLoaderAsString(modLoaders.first()); + loader_filter = ModPlatform::getModLoaderAsString(modLoaders.first()); } } @@ -165,9 +164,9 @@ void ModrinthCheckUpdate::checkVersionsResponse(QByteArray* response, std::optio // - The version reported by the JAR is different from the version reported by the indexed version (it's usually the case) // Such is the pain of having arbitrary files for a given version .-. - auto projectVer = Modrinth::loadIndexedPackVersion(projectObj, m_hashType, loaderFilter); - if (projectVer.downloadUrl.isEmpty()) { - qCritical() << "Modrinth mod without download url!" << projectVer.fileName; + auto project_ver = Modrinth::loadIndexedPackVersion(project_obj, m_hashType, loader_filter); + if (project_ver.downloadUrl.isEmpty()) { + qCritical() << "Modrinth mod without download url!" << project_ver.fileName; ++iter; continue; } @@ -178,22 +177,21 @@ void ModrinthCheckUpdate::checkVersionsResponse(QByteArray* response, std::optio pack->slug = resource->metadata()->slug; pack->addonId = resource->metadata()->project_id; pack->provider = ModPlatform::ResourceProvider::MODRINTH; - if ((projectVer.hash != hash && projectVer.is_preferred) || (resource->status() == ResourceStatus::NotInstalled)) { - auto downloadTask = makeShared(pack, projectVer, m_resourceModel, true, "update"); + if ((project_ver.hash != hash && project_ver.is_preferred) || (resource->status() == ResourceStatus::NOT_INSTALLED)) { + auto download_task = makeShared(pack, project_ver, m_resourceModel); - QString oldVersion = resource->metadata()->version_number; - if (oldVersion.isEmpty()) { - if (resource->status() == ResourceStatus::NotInstalled) { - oldVersion = tr("Not installed"); - } else { - oldVersion = tr("Unknown"); - } + QString old_version = resource->metadata()->version_number; + if (old_version.isEmpty()) { + if (resource->status() == ResourceStatus::NOT_INSTALLED) + old_version = tr("Not installed"); + else + old_version = tr("Unknown"); } - m_updates.emplace_back(pack->name, hash, oldVersion, projectVer.version_number, projectVer.version_type, - projectVer.changelog, ModPlatform::ResourceProvider::MODRINTH, downloadTask, resource->enabled()); + m_updates.emplace_back(pack->name, hash, old_version, project_ver.version_number, project_ver.version_type, + project_ver.changelog, ModPlatform::ResourceProvider::MODRINTH, download_task, resource->enabled()); } - m_deps.append(std::make_shared(pack, projectVer)); + m_deps.append(std::make_shared(pack, project_ver)); iter = m_mappings.erase(iter); } @@ -213,22 +211,20 @@ void ModrinthCheckUpdate::checkNextLoader() if (m_loaderIdx < m_loadersList.size()) { // this are mods so check with loades getUpdateModsForLoader(m_loadersList.at(m_loaderIdx), m_loaderIdx > m_initialSize); return; - } - if (m_loadersList.isEmpty() && m_loaderIdx == 0) { // this are other resources no need to check more than once with empty loader + } else if (m_loadersList.isEmpty() && m_loaderIdx == 0) { // this are other resources no need to check more than once with empty loader getUpdateModsForLoader(); return; } - for (auto* resource : m_mappings) { + for (auto resource : m_mappings) { QString reason; - if (dynamic_cast(resource) != nullptr) { + if (dynamic_cast(resource) != nullptr) reason = tr("No valid version found for this resource. It's probably unavailable for the current game " "version / mod loader."); - } else { + else reason = tr("No valid version found for this resource. It's probably unavailable for the current game version."); - } emit checkFailed(resource, reason); } diff --git a/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp b/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp index 0cb2c547d..f308c88bc 100644 --- a/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp +++ b/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp @@ -16,10 +16,7 @@ #include "net/ChecksumValidator.h" #include "net/ApiDownload.h" -#include "net/ApiHeaderProxy.h" #include "net/NetJob.h" - -#include "modplatform/ModIndex.h" #include "settings/INISettingsObject.h" #include "ui/dialogs/CustomMessageBox.h" @@ -32,119 +29,114 @@ bool ModrinthCreationTask::abort() { - if (!canAbort()) { + if (!canAbort()) return false; - } - if (m_task) { + if (m_task) m_task->abort(); - } return InstanceCreationTask::abort(); } bool ModrinthCreationTask::updateInstance() { - auto* instanceList = APPLICATION->instances(); + auto instance_list = APPLICATION->instances(); // FIXME: How to handle situations when there's more than one install already for a given modpack? - BaseInstance* inst = nullptr; - if (auto originalId = originalInstanceID(); !originalId.isEmpty()) { - inst = instanceList->getInstanceById(originalId); + BaseInstance* inst; + if (auto original_id = originalInstanceID(); !original_id.isEmpty()) { + inst = instance_list->getInstanceById(original_id); Q_ASSERT(inst); } else { - inst = instanceList->getInstanceByManagedName(originalName()); + inst = instance_list->getInstanceByManagedName(originalName()); if (!inst) { - inst = instanceList->getInstanceById(originalName()); + inst = instance_list->getInstanceById(originalName()); - if (!inst) { + if (!inst) return false; - } } } - QString indexPath = FS::PathCombine(m_stagingPath, "modrinth.index.json"); - if (!parseManifest(indexPath, m_files, true, false)) { + QString index_path = FS::PathCombine(m_stagingPath, "modrinth.index.json"); + if (!parseManifest(index_path, m_files, true, false)) return false; - } - auto versionName = inst->getManagedPackVersionName(); + auto version_name = inst->getManagedPackVersionName(); m_root_path = QFileInfo(inst->gameRoot()).fileName(); - auto versionStr = !versionName.isEmpty() ? tr(" (version %1)").arg(versionName) : ""; + auto version_str = !version_name.isEmpty() ? tr(" (version %1)").arg(version_name) : ""; if (shouldConfirmUpdate()) { - auto shouldUpdate = askIfShouldUpdate(m_parent, versionStr); - if (shouldUpdate == ShouldUpdate::SkipUpdating) { + auto should_update = askIfShouldUpdate(m_parent, version_str); + if (should_update == ShouldUpdate::SkipUpdating) return false; - } - if (shouldUpdate == ShouldUpdate::Cancel) { + if (should_update == ShouldUpdate::Cancel) { m_abort = true; return false; } } // Remove repeated files, we don't need to download them! - QDir oldInstDir(inst->instanceRoot()); + QDir old_inst_dir(inst->instanceRoot()); - QString oldIndexFolder(FS::PathCombine(oldInstDir.absolutePath(), "mrpack")); + QString old_index_folder(FS::PathCombine(old_inst_dir.absolutePath(), "mrpack")); - QString oldIndexPath(FS::PathCombine(oldIndexFolder, "modrinth.index.json")); - QFileInfo oldIndexFile(oldIndexPath); - if (oldIndexFile.exists()) { - std::vector oldFiles; - parseManifest(oldIndexPath, oldFiles, false, false); + QString old_index_path(FS::PathCombine(old_index_folder, "modrinth.index.json")); + QFileInfo old_index_file(old_index_path); + if (old_index_file.exists()) { + std::vector old_files; + parseManifest(old_index_path, old_files, false, false); // Let's remove all duplicated, identical resources! - auto filesIterator = m_files.begin(); + auto files_iterator = m_files.begin(); begin: - while (filesIterator != m_files.end()) { - const auto& file = *filesIterator; + while (files_iterator != m_files.end()) { + auto const& file = *files_iterator; - auto oldFilesIterator = oldFiles.begin(); - while (oldFilesIterator != oldFiles.end()) { - const auto& oldFile = *oldFilesIterator; + auto old_files_iterator = old_files.begin(); + while (old_files_iterator != old_files.end()) { + auto const& old_file = *old_files_iterator; - if (oldFile.hash == file.hash) { + if (old_file.hash == file.hash) { qDebug() << "Removed file at" << file.path << "from list of downloads"; - filesIterator = m_files.erase(filesIterator); - oldFilesIterator = oldFiles.erase(oldFilesIterator); + files_iterator = m_files.erase(files_iterator); + old_files_iterator = old_files.erase(old_files_iterator); goto begin; // Sorry :c } - oldFilesIterator++; + old_files_iterator++; } - filesIterator++; + files_iterator++; } - QDir oldMinecraftDir(inst->gameRoot()); + QDir old_minecraft_dir(inst->gameRoot()); // Some files were removed from the old version, and some will be downloaded in an updated version, // so we're fine removing them! - if (!oldFiles.empty()) { - for (const auto& file : oldFiles) { - scheduleToDelete(m_parent, oldMinecraftDir, file.path, true); + if (!old_files.empty()) { + for (auto const& file : old_files) { + scheduleToDelete(m_parent, old_minecraft_dir, file.path, true); } } // We will remove all the previous overrides, to prevent duplicate files! // TODO: Currently 'overrides' will always override the stuff on update. How do we preserve unchanged overrides? // FIXME: We may want to do something about disabled mods. - auto oldOverrides = Override::readOverrides("overrides", oldIndexFolder); - for (const auto& entry : oldOverrides) { - scheduleToDelete(m_parent, oldMinecraftDir, entry); + auto old_overrides = Override::readOverrides("overrides", old_index_folder); + for (const auto& entry : old_overrides) { + scheduleToDelete(m_parent, old_minecraft_dir, entry); } - auto oldClientOverrides = Override::readOverrides("client-overrides", oldIndexFolder); - for (const auto& entry : oldClientOverrides) { - scheduleToDelete(m_parent, oldMinecraftDir, entry); + auto old_client_overrides = Override::readOverrides("client-overrides", old_index_folder); + for (const auto& entry : old_client_overrides) { + scheduleToDelete(m_parent, old_minecraft_dir, entry); } } else { // We don't have an old index file, so we may duplicate stuff! - auto* dialog = CustomMessageBox::selectable(m_parent, tr("No index file."), - tr("We couldn't find a suitable index file for the older version. This may cause some " - "of the files to be duplicated. Do you want to continue?"), - QMessageBox::Warning, QMessageBox::Ok | QMessageBox::Cancel); + auto dialog = CustomMessageBox::selectable(m_parent, tr("No index file."), + tr("We couldn't find a suitable index file for the older version. This may cause some " + "of the files to be duplicated. Do you want to continue?"), + QMessageBox::Warning, QMessageBox::Ok | QMessageBox::Cancel); if (dialog->exec() == QDialog::DialogCode::Rejected) { m_abort = true; @@ -166,40 +158,39 @@ std::unique_ptr ModrinthCreationTask::createInstance() { QEventLoop loop; - QString parentFolder(FS::PathCombine(m_stagingPath, "mrpack")); + QString parent_folder(FS::PathCombine(m_stagingPath, "mrpack")); - QString indexPath = FS::PathCombine(m_stagingPath, "modrinth.index.json"); - if (m_files.empty() && !parseManifest(indexPath, m_files, true, true)) { + QString index_path = FS::PathCombine(m_stagingPath, "modrinth.index.json"); + if (m_files.empty() && !parseManifest(index_path, m_files, true, true)) return nullptr; - } // Keep index file in case we need it some other time (like when changing versions) - QString newIndexPlace(FS::PathCombine(parentFolder, "modrinth.index.json")); - FS::ensureFilePathExists(newIndexPlace); - FS::move(indexPath, newIndexPlace); + QString new_index_place(FS::PathCombine(parent_folder, "modrinth.index.json")); + FS::ensureFilePathExists(new_index_place); + FS::move(index_path, new_index_place); auto mcPath = FS::PathCombine(m_stagingPath, m_root_path); - auto overridePath = FS::PathCombine(m_stagingPath, "overrides"); - if (QFile::exists(overridePath)) { + auto override_path = FS::PathCombine(m_stagingPath, "overrides"); + if (QFile::exists(override_path)) { // Create a list of overrides in "overrides.txt" inside mrpack/ - Override::createOverrides("overrides", parentFolder, overridePath); + Override::createOverrides("overrides", parent_folder, override_path); // Apply the overrides - if (!FS::move(overridePath, mcPath)) { + if (!FS::move(override_path, mcPath)) { setError(tr("Could not rename the overrides folder:\n") + "overrides"); return nullptr; } } // Do client overrides - auto clientOverridePath = FS::PathCombine(m_stagingPath, "client-overrides"); - if (QFile::exists(clientOverridePath)) { + auto client_override_path = FS::PathCombine(m_stagingPath, "client-overrides"); + if (QFile::exists(client_override_path)) { // Create a list of overrides in "client-overrides.txt" inside mrpack/ - Override::createOverrides("client-overrides", parentFolder, clientOverridePath); + Override::createOverrides("client-overrides", parent_folder, client_override_path); // Apply the overrides - if (!FS::overrideFolder(mcPath, clientOverridePath)) { + if (!FS::overrideFolder(mcPath, client_override_path)) { setError(tr("Could not rename the client overrides folder:\n") + "client overrides"); return nullptr; } @@ -209,27 +200,18 @@ std::unique_ptr ModrinthCreationTask::createInstance() auto instanceSettings = std::make_unique(configPath); auto instance = std::make_unique(m_globalSettings, std::move(instanceSettings), m_stagingPath); - auto* components = instance->getPackProfile(); + auto components = instance->getPackProfile(); components->buildingFromScratch(); components->setComponentVersion("net.minecraft", m_minecraft_version, true); - QString loader; - if (!m_fabric_version.isEmpty()) { + if (!m_fabric_version.isEmpty()) components->setComponentVersion("net.fabricmc.fabric-loader", m_fabric_version); - loader = ModPlatform::getModLoaderAsString(ModPlatform::ModLoaderType::Fabric); - } - if (!m_quilt_version.isEmpty()) { + if (!m_quilt_version.isEmpty()) components->setComponentVersion("org.quiltmc.quilt-loader", m_quilt_version); - loader = ModPlatform::getModLoaderAsString(ModPlatform::ModLoaderType::Quilt); - } - if (!m_forge_version.isEmpty()) { + if (!m_forge_version.isEmpty()) components->setComponentVersion("net.minecraftforge", m_forge_version); - loader = ModPlatform::getModLoaderAsString(ModPlatform::ModLoaderType::Forge); - } - if (!m_neoForge_version.isEmpty()) { + if (!m_neoForge_version.isEmpty()) components->setComponentVersion("net.neoforged", m_neoForge_version); - loader = ModPlatform::getModLoaderAsString(ModPlatform::ModLoaderType::NeoForge); - } if (m_instIcon != "default") { instance->setIconKey(m_instIcon); @@ -238,35 +220,34 @@ std::unique_ptr ModrinthCreationTask::createInstance() } // Don't add managed info to packs without an ID (most likely imported from ZIP) - if (!m_managed_id.isEmpty()) { + if (!m_managed_id.isEmpty()) instance->setManagedPack("modrinth", m_managed_id, m_managed_name, m_managed_version_id, version()); - } else { + else instance->setManagedPack("modrinth", "", name(), "", ""); - } instance->setName(name()); instance->saveNow(); auto downloadMods = makeShared(tr("Mod Download Modrinth"), APPLICATION->network()); - auto rootModpackPath = FS::PathCombine(m_stagingPath, m_root_path); - auto rootModpackUrl = QUrl::fromLocalFile(rootModpackPath); + auto root_modpack_path = FS::PathCombine(m_stagingPath, m_root_path); + auto root_modpack_url = QUrl::fromLocalFile(root_modpack_path); // TODO make this work with other sorts of resource QHash resources; for (auto& file : m_files) { auto fileName = file.path; fileName = FS::RemoveInvalidPathChars(fileName); - auto filePath = FS::PathCombine(rootModpackPath, fileName); - if (!rootModpackUrl.isParentOf(QUrl::fromLocalFile(filePath))) { + auto file_path = FS::PathCombine(root_modpack_path, fileName); + if (!root_modpack_url.isParentOf(QUrl::fromLocalFile(file_path))) { // This means we somehow got out of the root folder, so abort here to prevent exploits setError(tr("One of the files has a path that leads to an arbitrary location (%1). This is a security risk and isn't allowed.") .arg(fileName)); return nullptr; } if (fileName.startsWith("mods/")) { - auto* mod = new Mod(filePath); + auto mod = new Mod(file_path); ModDetails d; - d.mod_id = filePath; + d.mod_id = file_path; mod->setDetails(d); resources[file.hash.toHex()] = mod; } @@ -274,39 +255,29 @@ std::unique_ptr ModrinthCreationTask::createInstance() setError(tr("The file '%1' is missing a download link. This is invalid in the pack format.").arg(fileName)); return nullptr; } - qDebug() << "Will try to download" << file.downloads.front() << "to" << filePath; - - Net::ModrinthDownloadMeta meta{ - .reason = m_instance.has_value() ? "update" : "modpack", - .gameVersion = m_minecraft_version, - .loader = loader, - }; - - QUrl downloadUrl = file.downloads.dequeue(); - auto dl = Net::ApiDownload::makeFile(downloadUrl, filePath, Net::Download::Option::NoOptions, meta); + qDebug() << "Will try to download" << file.downloads.front() << "to" << file_path; + auto dl = Net::ApiDownload::makeFile(file.downloads.dequeue(), file_path); dl->addValidator(new Net::ChecksumValidator(file.hashAlgorithm, file.hash)); downloadMods->addNetAction(dl); if (!file.downloads.empty()) { // FIXME: This really needs to be put into a ConcurrentTask of // MultipleOptionsTask's , once those exist :) auto param = dl.toWeakRef(); - connect(dl.get(), &Task::failed, [&file, filePath, param, downloadMods, meta] { - QUrl fallbackUrl = file.downloads.dequeue(); - auto ndl = Net::ApiDownload::makeFile(fallbackUrl, filePath, Net::Download::Option::NoOptions, meta); + connect(dl.get(), &Task::failed, [&file, file_path, param, downloadMods] { + auto ndl = Net::ApiDownload::makeFile(file.downloads.dequeue(), file_path); ndl->addValidator(new Net::ChecksumValidator(file.hashAlgorithm, file.hash)); downloadMods->addNetAction(ndl); - if (auto shared = param.lock()) { + if (auto shared = param.lock()) shared->succeeded(); - } }); } } - bool endedWell = false; + bool ended_well = false; - connect(downloadMods.get(), &NetJob::succeeded, this, [&endedWell]() { endedWell = true; }); - connect(downloadMods.get(), &NetJob::failed, [this, &endedWell](const QString& reason) { - endedWell = false; + connect(downloadMods.get(), &NetJob::succeeded, this, [&ended_well]() { ended_well = true; }); + connect(downloadMods.get(), &NetJob::failed, [this, &ended_well](const QString& reason) { + ended_well = false; setError(reason); }); connect(downloadMods.get(), &NetJob::finished, &loop, &QEventLoop::quit); @@ -322,8 +293,8 @@ std::unique_ptr ModrinthCreationTask::createInstance() loop.exec(); - if (!endedWell) { - for (auto* resource : resources) { + if (!ended_well) { + for (auto resource : resources) { delete resource; } return nullptr; @@ -332,7 +303,7 @@ std::unique_ptr ModrinthCreationTask::createInstance() QEventLoop ensureMetaLoop; QDir folder = FS::PathCombine(instance->modsRoot(), ".index"); auto ensureMetadataTask = makeShared(resources, folder, ModPlatform::ResourceProvider::MODRINTH); - connect(ensureMetadataTask.get(), &Task::succeeded, this, [&endedWell]() { endedWell = true; }); + connect(ensureMetadataTask.get(), &Task::succeeded, this, [&ended_well]() { ended_well = true; }); connect(ensureMetadataTask.get(), &Task::finished, &ensureMetaLoop, &QEventLoop::quit); connect(ensureMetadataTask.get(), &Task::progress, [this](qint64 current, qint64 total) { setDetails(tr("%1 out of %2 complete").arg(current).arg(total)); @@ -344,38 +315,40 @@ std::unique_ptr ModrinthCreationTask::createInstance() m_task = ensureMetadataTask; ensureMetaLoop.exec(); - for (auto* resource : resources) { + for (auto resource : resources) { delete resource; } resources.clear(); // Update information of the already installed instance, if any. - if (m_instance && endedWell) { + if (m_instance && ended_well) { setAbortable(false); - auto* inst = m_instance.value(); + auto inst = m_instance.value(); // Only change the name if it didn't use a custom name, so that the previous custom name // is preserved, but if we're using the original one, we update the version string. // NOTE: This needs to come before the copyManagedPack call! if (inst->name().contains(inst->getManagedPackVersionName()) && inst->name() != instance->name()) { - if (askForChangingInstanceName(m_parent, inst->name(), instance->name()) == InstanceNameChange::ShouldChange) { + if (askForChangingInstanceName(m_parent, inst->name(), instance->name()) == InstanceNameChange::ShouldChange) inst->setName(instance->name()); - } } inst->copyManagedPack(*instance); } - if (endedWell) { + if (ended_well) { return instance; } return nullptr; } -bool ModrinthCreationTask::parseManifest(const QString& indexPath, std::vector& files, bool setInternalData, bool showOptionalDialog) +bool ModrinthCreationTask::parseManifest(const QString& index_path, + std::vector& files, + bool set_internal_data, + bool show_optional_dialog) { try { - auto doc = Json::requireDocument(indexPath); + auto doc = Json::requireDocument(index_path); auto obj = Json::requireObject(doc, "modrinth.index.json"); int formatVersion = Json::requireInteger(obj, "formatVersion", "modrinth.index.json"); if (formatVersion == 1) { @@ -384,10 +357,9 @@ bool ModrinthCreationTask::parseManifest(const QString& indexPath, std::vector createInstance() override; private: - bool parseManifest(const QString&, std::vector&, bool setInternalData = true, bool showOptionalDialog = true); + bool parseManifest(const QString&, std::vector&, bool set_internal_data = true, bool show_optional_dialog = true); private: QWidget* m_parent = nullptr; diff --git a/launcher/net/ApiDownload.cpp b/launcher/net/ApiDownload.cpp index 54d3e746e..9a5a44104 100644 --- a/launcher/net/ApiDownload.cpp +++ b/launcher/net/ApiDownload.cpp @@ -18,30 +18,28 @@ */ #include "net/ApiDownload.h" - -#include #include "net/ApiHeaderProxy.h" namespace Net { Download::Ptr ApiDownload::makeCached(QUrl url, MetaEntryPtr entry, Download::Options options) { - auto dl = Download::makeCached(std::move(url), std::move(entry), options); + auto dl = Download::makeCached(url, entry, options); dl->addHeaderProxy(std::make_unique()); return dl; } std::pair ApiDownload::makeByteArray(QUrl url, Download::Options options) { - auto [dl, response] = Download::makeByteArray(std::move(url), options); + auto [dl, response] = Download::makeByteArray(url, options); dl->addHeaderProxy(std::make_unique()); return { dl, response }; } -Download::Ptr ApiDownload::makeFile(QUrl url, QString path, Download::Options options, ModrinthDownloadMeta meta) +Download::Ptr ApiDownload::makeFile(QUrl url, QString path, Download::Options options) { - auto dl = Download::makeFile(std::move(url), std::move(path), options); - dl->addHeaderProxy(std::make_unique(std::move(meta))); + auto dl = Download::makeFile(url, path, options); + dl->addHeaderProxy(std::make_unique()); return dl; } diff --git a/launcher/net/ApiDownload.h b/launcher/net/ApiDownload.h index 033dd0e12..01a31eb17 100644 --- a/launcher/net/ApiDownload.h +++ b/launcher/net/ApiDownload.h @@ -20,17 +20,13 @@ #pragma once #include "Download.h" -#include "net/ApiHeaderProxy.h" namespace Net { namespace ApiDownload { Download::Ptr makeCached(QUrl url, MetaEntryPtr entry, Download::Options options = Download::Option::NoOptions); std::pair makeByteArray(QUrl url, Download::Options options = Download::Option::NoOptions); -Download::Ptr makeFile(QUrl url, - QString path, - Download::Options options = Download::Option::NoOptions, - ModrinthDownloadMeta meta = ModrinthDownloadMeta()); +Download::Ptr makeFile(QUrl url, QString path, Download::Options options = Download::Option::NoOptions); }; // namespace ApiDownload } // namespace Net diff --git a/launcher/net/ApiHeaderProxy.h b/launcher/net/ApiHeaderProxy.h index d12287a4e..789a6fada 100644 --- a/launcher/net/ApiHeaderProxy.h +++ b/launcher/net/ApiHeaderProxy.h @@ -23,64 +23,27 @@ #include "BuildConfig.h" #include "net/HeaderProxy.h" -#include -#include - namespace Net { -struct ModrinthDownloadMeta { - QString reason; - QString gameVersion; - QString loader; - - bool isEmpty() const { return reason.isEmpty(); } - - QByteArray toJson() const - { - QJsonObject obj; - if (!reason.isEmpty()) { - obj["reason"] = reason; - } - if (!gameVersion.isEmpty()) { - obj["game_version"] = gameVersion; - } - if (!loader.isEmpty()) { - obj["loader"] = loader; - } - return QJsonDocument(obj).toJson(QJsonDocument::Compact); - } -}; - class ApiHeaderProxy : public HeaderProxy { public: - ApiHeaderProxy() = default; - explicit ApiHeaderProxy(ModrinthDownloadMeta meta) : m_meta(std::move(meta)) {} - ~ApiHeaderProxy() override = default; + ApiHeaderProxy() : HeaderProxy() {} + virtual ~ApiHeaderProxy() = default; public: - QList headers(const QNetworkRequest& request) const override + virtual QList headers(const QNetworkRequest& request) const override { QList hdrs; - const auto host = request.url().host(); - - if (APPLICATION->capabilities() & Application::SupportsFlame && - (host == QUrl(BuildConfig.FLAME_BASE_URL).host() || host == BuildConfig.FLAME_DOWNLOAD_HOST)) { - hdrs.append({ .headerName = "x-api-key", .headerValue = APPLICATION->getFlameAPIKey().toUtf8() }); - } else if (host == QUrl(BuildConfig.MODRINTH_PROD_URL).host() || host == QUrl(BuildConfig.MODRINTH_STAGING_URL).host()) { + if (APPLICATION->capabilities() & Application::SupportsFlame && request.url().host() == QUrl(BuildConfig.FLAME_BASE_URL).host()) { + hdrs.append({ "x-api-key", APPLICATION->getFlameAPIKey().toUtf8() }); + } else if (request.url().host() == QUrl(BuildConfig.MODRINTH_PROD_URL).host() || + request.url().host() == QUrl(BuildConfig.MODRINTH_STAGING_URL).host()) { QString token = APPLICATION->getModrinthAPIToken(); - if (!token.isNull()) { - hdrs.append({ .headerName = "Authorization", .headerValue = token.toUtf8() }); - } - } - - if (host == BuildConfig.MODRINTH_DOWNLOAD_HOST && !m_meta.isEmpty()) { - hdrs.append({ .headerName = "modrinth-download-meta", .headerValue = m_meta.toJson() }); + if (!token.isNull()) + hdrs.append({ "Authorization", token.toUtf8() }); } return hdrs; }; - - private: - ModrinthDownloadMeta m_meta; }; } // namespace Net diff --git a/launcher/net/ChecksumValidator.h b/launcher/net/ChecksumValidator.h index c7906cc13..7663d5d12 100644 --- a/launcher/net/ChecksumValidator.h +++ b/launcher/net/ChecksumValidator.h @@ -38,6 +38,7 @@ #include "Validator.h" #include +#include namespace Net { class ChecksumValidator : public Validator { @@ -68,10 +69,10 @@ class ChecksumValidator : public Validator { return true; } - auto validate(QNetworkReply& reply) -> bool override + auto validate(QNetworkReply&) -> bool override { - if (!m_expected.isEmpty() && m_expected != hash()) { - qWarning() << "Checksum mismatch for URL:" << reply.url().toString() << "expected:" << m_expected << "got:" << hash(); + if (m_expected.size() && m_expected != hash()) { + qWarning() << "Checksum mismatch, download is bad."; return false; } return true; diff --git a/launcher/net/HttpMetaCache.cpp b/launcher/net/HttpMetaCache.cpp index 5c1e47dfd..6b81bfe0d 100644 --- a/launcher/net/HttpMetaCache.cpp +++ b/launcher/net/HttpMetaCache.cpp @@ -182,7 +182,7 @@ auto HttpMetaCache::evictAll() -> bool } map.entry_list.clear(); // AND all return codes together so the result is true iff all runs of deletePath() are true - ret &= FS::deleteContents(map.base_path); + ret &= FS::deletePath(map.base_path); } return ret; } diff --git a/launcher/net/NetJob.cpp b/launcher/net/NetJob.cpp index 3dd1c09cf..dae149ab3 100644 --- a/launcher/net/NetJob.cpp +++ b/launcher/net/NetJob.cpp @@ -69,15 +69,11 @@ void NetJob::executeNextSubTask() // We're finished, check for failures and retry if we can (up to 3 times) if (isRunning() && m_queue.isEmpty() && m_doing.isEmpty() && !m_failed.isEmpty() && m_try < 3) { m_try += 1; - m_failed.removeIf([this](QHash::iterator task) { - // there is no point in retying on 404 Not Found - if (static_cast(task->get())->replyStatusCode() == 404) { - return false; - } - m_done.remove(task->get()); - m_queue.enqueue(*task); - return true; - }); + while (!m_failed.isEmpty()) { + auto task = m_failed.take(*m_failed.keyBegin()); + m_done.remove(task.get()); + m_queue.enqueue(task); + } } ConcurrentTask::executeNextSubTask(); } @@ -104,18 +100,13 @@ auto NetJob::canAbort() const -> bool auto NetJob::abort() -> bool { + bool fullyAborted = true; + // fail all downloads on the queue for (auto task : m_queue) m_failed.insert(task.get(), task); m_queue.clear(); - if (m_doing.isEmpty()) { - // no downloads to abort, NetJob is not running - return true; - } - - bool fullyAborted = true; - // abort active downloads auto toKill = m_doing.values(); for (auto part : toKill) { diff --git a/launcher/net/NetUtils.h b/launcher/net/NetUtils.h index 67ebc9685..cd517bcca 100644 --- a/launcher/net/NetUtils.h +++ b/launcher/net/NetUtils.h @@ -40,18 +40,4 @@ inline bool isApplicationError(QNetworkReply::NetworkError x) QNetworkReply::UnknownContentError }; return errors.contains(x); } - -// 500 class errors, see https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/500 -// microsoft may send these error codes when services (auth) are down. -// We treat this as a reason to launch in offline mode. -inline bool isServerError(QNetworkReply::NetworkError x) -{ - static QSet errors = { QNetworkReply::InternalServerError, - QNetworkReply::OperationNotImplementedError, - QNetworkReply::ServiceUnavailableError, // 503 | seen in logs in 2026 - //QNetworkReply::GatewayTimeoutError, // 504 | seen in logs in 2024 - // Qt doesn't have it mapped. Unknown covers it - QNetworkReply::UnknownServerError }; - return errors.contains(x); -} } // namespace Net diff --git a/launcher/resources/multimc/16x16/new.png b/launcher/resources/multimc/16x16/new.png new file mode 100644 index 000000000..dfde06f61 Binary files /dev/null and b/launcher/resources/multimc/16x16/new.png differ diff --git a/launcher/screenshots/ImgurUpload.cpp b/launcher/screenshots/ImgurUpload.cpp index dd41fc340..e6ba372ed 100644 --- a/launcher/screenshots/ImgurUpload.cpp +++ b/launcher/screenshots/ImgurUpload.cpp @@ -118,7 +118,7 @@ auto ImgurUpload::Sink::finalize(QNetworkReply&) -> Task::State Net::NetRequest::Ptr ImgurUpload::make(ScreenShot::Ptr m_shot) { auto up = makeShared(m_shot->m_file); - up->m_url = BuildConfig.IMGUR_BASE_URL + "image"; + up->m_url = std::move(BuildConfig.IMGUR_BASE_URL + "image"); up->m_sink.reset(new Sink(m_shot)); up->addHeaderProxy(std::make_unique(QList{ { "Authorization", QString("Client-ID %1").arg(BuildConfig.IMGUR_CLIENT_ID).toUtf8() }, { "Accept", "application/json" } })); diff --git a/launcher/settings/INIFile.cpp b/launcher/settings/INIFile.cpp index a1d1c01d9..75e888938 100644 --- a/launcher/settings/INIFile.cpp +++ b/launcher/settings/INIFile.cpp @@ -35,8 +35,6 @@ */ #include "settings/INIFile.h" - -#include #include #include @@ -64,10 +62,11 @@ bool INIFile::saveFile(QString fileName) _settings_obj.sync(); if (auto status = _settings_obj.status(); status != QSettings::Status::NoError) { + // Shouldn't be possible! + Q_ASSERT(status != QSettings::Status::FormatError); + if (status == QSettings::Status::AccessError) - qCritical() << "An access error occurred while saving INI file" << fileName << "(is the file read-only?)"; - if (ASSERT_NEVER(status == QSettings::Status::FormatError)) - qCritical() << "A format error occurred while saving INI file" << fileName << "(this shouldn't be possible!)"; + qCritical() << "An access error occurred (e.g. trying to write to a read-only file)."; return false; } @@ -179,9 +178,9 @@ bool INIFile::loadFile(QString fileName) if (auto status = _settings_obj.status(); status != QSettings::Status::NoError) { if (status == QSettings::Status::AccessError) - qCritical() << "An access error occurred while loading INI file" << fileName; + qCritical() << "An access error occurred (e.g. trying to write to a read-only file)."; if (status == QSettings::Status::FormatError) - qCritical() << "A format error occurred while loading INI file" << fileName << "(is the file malformed or corrupted?)"; + qCritical() << "A format error occurred (e.g. loading a malformed INI file)."; return false; } if (!_settings_obj.value("ConfigVersion").isValid()) { diff --git a/launcher/tasks/Task.cpp b/launcher/tasks/Task.cpp index 5857a0663..a54b4e7c2 100644 --- a/launcher/tasks/Task.cpp +++ b/launcher/tasks/Task.cpp @@ -48,13 +48,6 @@ Task::Task(bool show_debug) : m_show_debug(show_debug) setAutoDelete(false); } -Task::~Task() -{ - if (isRunning()) { - qCWarning(taskLogC) << "Task" << describe() << "disposed while running!"; - } -} - void Task::setStatus(const QString& new_status) { if (m_status != new_status) { diff --git a/launcher/tasks/Task.h b/launcher/tasks/Task.h index 38c09da90..94fb57783 100644 --- a/launcher/tasks/Task.h +++ b/launcher/tasks/Task.h @@ -94,7 +94,7 @@ class Task : public QObject, public QRunnable { public: explicit Task(bool show_debug_log = true); - ~Task() override; + virtual ~Task() = default; bool isRunning() const; bool isFinished() const; @@ -165,7 +165,7 @@ class Task : public QObject, public QRunnable { //! used by external code to ask the task to abort virtual bool abort() { - if (canAbort() && isRunning()) + if (canAbort()) emitAborted(); return canAbort(); } diff --git a/launcher/translations/POTranslator.cpp b/launcher/translations/POTranslator.cpp index 0bd3638e6..458ebd230 100644 --- a/launcher/translations/POTranslator.cpp +++ b/launcher/translations/POTranslator.cpp @@ -183,7 +183,8 @@ void POTranslatorPrivate::reload() nextFuzzy = true; } } else if (line.startsWith('"')) { - QByteArray* out = nullptr; + QByteArray temp; + QByteArray* out = &temp; switch (mode) { case Mode::First: diff --git a/launcher/translations/TranslationsModel.cpp b/launcher/translations/TranslationsModel.cpp index 7f905608b..dea7241b2 100644 --- a/launcher/translations/TranslationsModel.cpp +++ b/launcher/translations/TranslationsModel.cpp @@ -36,9 +36,13 @@ #include "TranslationsModel.h" +#include #include -#include -#include +#include +#include +#include +#include +#include #include "BuildConfig.h" #include "FileSystem.h" @@ -51,26 +55,18 @@ #include "Application.h" #include "settings/SettingsObject.h" -static constexpr QLatin1String g_defaultLangCode("en_US"); +const static QLatin1String defaultLangCode("en_US"); -namespace { -enum class FileType : std::uint8_t { None, Qm, Po }; - -QString getSystemLocaleName() -{ - return QLocale::system().name(); -} - -QString getSystemLanguage() -{ - return getSystemLocaleName().split('_').front(); -} -} // namespace +enum class FileType { NONE, QM, PO }; struct Language { - Language() : updated(true) {} - - explicit Language(QString _key) : key(std::move(_key)), updated(key == g_defaultLangCode) { locale = QLocale(key); } + Language() { updated = true; } + Language(const QString& _key) + { + key = _key; + locale = QLocale(key); + updated = (key == defaultLangCode); + } QString languageName() const { @@ -102,12 +98,12 @@ struct Language { float percentTranslated() const { if (total == 0) { - return 100.0F; + return 100.0f; } - return 100.0F * static_cast(translated) / static_cast(total); + return 100.0f * float(translated) / float(total); } - void setTranslationStats(const unsigned _translated, const unsigned _untranslated, const unsigned _fuzzy) + void setTranslationStats(unsigned _translated, unsigned _untranslated, unsigned _fuzzy) { translated = _translated; untranslated = _untranslated; @@ -119,18 +115,18 @@ struct Language { bool isIdenticalTo(const Language& other) const { - return (key == other.key && fileName == other.fileName && fileSize == other.fileSize && fileSha1 == other.fileSha1 && + return (key == other.key && file_name == other.file_name && file_size == other.file_size && file_sha1 == other.file_sha1 && translated == other.translated && fuzzy == other.fuzzy && total == other.fuzzy && localFileType == other.localFileType); } - Language& apply(const Language& other) + Language& apply(Language& other) { if (!isOfSameNameAs(other)) { return *this; } - fileName = other.fileName; - fileSize = other.fileSize; - fileSha1 = other.fileSha1; + file_name = other.file_name; + file_size = other.file_size; + file_sha1 = other.file_sha1; translated = other.translated; fuzzy = other.fuzzy; total = other.total; @@ -142,44 +138,47 @@ struct Language { QLocale locale; bool updated; - QString fileName = QString(); - std::size_t fileSize = 0; - QString fileSha1 = QString(); + QString file_name = QString(); + std::size_t file_size = 0; + QString file_sha1 = QString(); unsigned translated = 0; unsigned untranslated = 0; unsigned fuzzy = 0; unsigned total = 0; - FileType localFileType = FileType::None; + FileType localFileType = FileType::NONE; }; struct TranslationsModel::Private { QDir m_dir; // initial state is just english - QList m_languages = { Language(g_defaultLangCode) }; + QList m_languages = { Language(defaultLangCode) }; - QString m_selectedLanguage = g_defaultLangCode; - std::unique_ptr m_qtTranslator; - std::unique_ptr m_appTranslator; + QString m_selectedLanguage = defaultLangCode; + std::unique_ptr m_qt_translator; + std::unique_ptr m_app_translator; - Net::Download* m_indexTask = nullptr; + Net::Download* m_index_task; QString m_downloadingTranslation; - NetJob::Ptr m_downloadJob; - NetJob::Ptr m_indexJob; + NetJob::Ptr m_dl_job; + NetJob::Ptr m_index_job; QString m_nextDownload; - QFileSystemWatcher* watcher = nullptr; + std::unique_ptr m_po_translator; + QFileSystemWatcher* watcher; - bool m_noLanguageSet = false; + const QString m_system_locale = QLocale::system().name(); + const QString m_system_language = m_system_locale.split('_').front(); + + bool no_language_set = false; }; -TranslationsModel::TranslationsModel(const QString& path, QObject* parent) : QAbstractListModel(parent) +TranslationsModel::TranslationsModel(QString path, QObject* parent) : QAbstractListModel(parent) { - d = std::make_unique(); + d.reset(new Private); d->m_dir.setPath(path); - d->m_selectedLanguage = APPLICATION->settings()->get("Language").toString(); FS::ensureFolderPathExists(path); reloadLocalFiles(); @@ -188,12 +187,12 @@ TranslationsModel::TranslationsModel(const QString& path, QObject* parent) : QAb d->watcher->addPath(d->m_dir.canonicalPath()); } -TranslationsModel::~TranslationsModel() = default; +TranslationsModel::~TranslationsModel() {} void TranslationsModel::translationDirChanged(const QString& path) { qDebug() << "Dir changed:" << path; - if (!d->m_noLanguageSet) { + if (!d->no_language_set) { reloadLocalFiles(); } selectLanguage(selectedLanguage()); @@ -202,21 +201,25 @@ void TranslationsModel::translationDirChanged(const QString& path) void TranslationsModel::indexReceived() { qDebug() << "Got translations index!"; - d->m_indexJob.reset(); - reloadLocalFiles(); + d->m_index_job.reset(); - if (d->m_noLanguageSet) { - auto language = getSystemLocaleName(); + if (d->no_language_set) { + reloadLocalFiles(); + + auto language = d->m_system_locale; if (!findLanguageAsOptional(language).has_value()) { - language = getSystemLanguage(); + language = d->m_system_language; } selectLanguage(language); + if (selectedLanguage() != defaultLangCode) { + updateLanguage(selectedLanguage()); + } APPLICATION->settings()->set("Language", selectedLanguage()); - d->m_noLanguageSet = false; + d->no_language_set = false; } - if (selectedLanguage() != g_defaultLangCode) { - updateLanguage(selectedLanguage()); + else if (d->m_selectedLanguage != defaultLangCode) { + downloadTranslation(d->m_selectedLanguage); } } @@ -232,27 +235,27 @@ void readIndex(const QString& path, QMap& languages) } try { - auto toplevelDoc = Json::requireDocument(data); - auto doc = Json::requireObject(toplevelDoc); - auto fileType = Json::requireString(doc, "file_type"); - if (fileType != "MMC-TRANSLATION-INDEX") { - qCritical() << "Translations Download Failed: index file is of unknown file type" << fileType; + auto toplevel_doc = Json::requireDocument(data); + auto doc = Json::requireObject(toplevel_doc); + auto file_type = Json::requireString(doc, "file_type"); + if (file_type != "MMC-TRANSLATION-INDEX") { + qCritical() << "Translations Download Failed: index file is of unknown file type" << file_type; return; } auto version = Json::requireInteger(doc, "version"); if (version > 2) { - qCritical() << "Translations Download Failed: index file is of unknown format version" << fileType; + qCritical() << "Translations Download Failed: index file is of unknown format version" << file_type; return; } auto langObjs = Json::requireObject(doc, "languages"); - for (auto iter = langObjs.begin(); iter != langObjs.end(); ++iter) { + for (auto iter = langObjs.begin(); iter != langObjs.end(); iter++) { Language lang(iter.key()); auto langObj = Json::requireObject(iter.value()); lang.setTranslationStats(langObj["translated"].toInt(), langObj["untranslated"].toInt(), langObj["fuzzy"].toInt()); - lang.fileName = Json::requireString(langObj, "file"); - lang.fileSha1 = Json::requireString(langObj, "sha1"); - lang.fileSize = Json::requireInteger(langObj, "size"); + lang.file_name = Json::requireString(langObj, "file"); + lang.file_sha1 = Json::requireString(langObj, "sha1"); + lang.file_size = Json::requireInteger(langObj, "size"); languages.insert(lang.key, lang); } @@ -264,25 +267,20 @@ void readIndex(const QString& path, QMap& languages) void TranslationsModel::reloadLocalFiles() { - QMap languages = { { g_defaultLangCode, Language(g_defaultLangCode) } }; + QMap languages = { { defaultLangCode, Language(defaultLangCode) } }; - const auto indexPath = d->m_dir.absoluteFilePath("index_v2.json"); - if (!QFileInfo::exists(indexPath)) { - downloadIndex(); - return; - } - readIndex(indexPath, languages); + readIndex(d->m_dir.absoluteFilePath("index_v2.json"), languages); auto entries = d->m_dir.entryInfoList({ "mmc_*.qm", "*.po" }, QDir::Files | QDir::NoDotAndDotDot); for (auto& entry : entries) { auto completeSuffix = entry.completeSuffix(); QString langCode; - FileType fileType = FileType::None; + FileType fileType = FileType::NONE; if (completeSuffix == "qm") { langCode = entry.baseName().remove(0, 4); - fileType = FileType::Qm; + fileType = FileType::QM; } else if (completeSuffix == "po") { langCode = entry.baseName(); - fileType = FileType::Po; + fileType = FileType::PO; } else { continue; } @@ -290,14 +288,13 @@ void TranslationsModel::reloadLocalFiles() auto langIter = languages.find(langCode); if (langIter != languages.end()) { auto& language = *langIter; - // TODO: use std::to_underlying in C++23 - if (static_cast(fileType) > static_cast(language.localFileType)) { + if (int(fileType) > int(language.localFileType)) { language.localFileType = fileType; } } else { - if (fileType == FileType::Po) { + if (fileType == FileType::PO) { Language localFound(langCode); - localFound.localFileType = FileType::Po; + localFound.localFileType = FileType::PO; languages.insert(langCode, localFound); } } @@ -317,7 +314,7 @@ void TranslationsModel::reloadLocalFiles() emit dataChanged(index(row), index(row)); languages.remove(language.key); } - ++iter; + iter++; } else { beginRemoveRows(QModelIndex(), row, row); iter = d->m_languages.erase(iter); @@ -332,38 +329,34 @@ void TranslationsModel::reloadLocalFiles() for (auto& language : languages) { d->m_languages.append(language); } - - const auto comp = [systemLocale = getSystemLocaleName(), systemLanguage = getSystemLanguage()](const Language& a, const Language& b) { + std::sort(d->m_languages.begin(), d->m_languages.end(), [this](const Language& a, const Language& b) { if (a.key != b.key) { - if (a.key == systemLocale || a.key == systemLanguage) { + if (a.key == d->m_system_locale || a.key == d->m_system_language) { return true; } - if (b.key == systemLocale || b.key == systemLanguage) { + if (b.key == d->m_system_locale || b.key == d->m_system_language) { return false; } } return a.languageName().toLower() < b.languageName().toLower(); - }; - std::ranges::sort(d->m_languages, comp); + }); endInsertRows(); } namespace { -enum class Column : std::uint8_t { Language, Completeness }; +enum class Column { Language, Completeness }; } -QVariant TranslationsModel::data(const QModelIndex& index, const int role) const +QVariant TranslationsModel::data(const QModelIndex& index, int role) const { - if (!index.isValid()) { - return {}; - } + if (!index.isValid()) + return QVariant(); - const int row = index.row(); - const auto column = static_cast(index.column()); + int row = index.row(); + auto column = static_cast(index.column()); - if (row < 0 || row >= d->m_languages.size()) { - return {}; - } + if (row < 0 || row >= d->m_languages.size()) + return QVariant(); auto& lang = d->m_languages[row]; switch (role) { @@ -385,11 +378,11 @@ QVariant TranslationsModel::data(const QModelIndex& index, const int role) const case Qt::UserRole: return lang.key; default: - return {}; + return QVariant(); } } -QVariant TranslationsModel::headerData(int section, const Qt::Orientation orientation, const int role) const +QVariant TranslationsModel::headerData(int section, Qt::Orientation orientation, int role) const { auto column = static_cast(section); if (role == Qt::DisplayRole) { @@ -424,50 +417,49 @@ int TranslationsModel::columnCount([[maybe_unused]] const QModelIndex& parent) c return 2; } -QList::Iterator TranslationsModel::findLanguage(const QString& key) const +QList::Iterator TranslationsModel::findLanguage(const QString& key) { - return std::ranges::find_if(d->m_languages, [key](const Language& lang) { return lang.key == key; }); + return std::find_if(d->m_languages.begin(), d->m_languages.end(), [key](Language& lang) { return lang.key == key; }); } -std::optional TranslationsModel::findLanguageAsOptional(const QString& key) const +std::optional TranslationsModel::findLanguageAsOptional(const QString& key) { auto found = findLanguage(key); - if (found != d->m_languages.end()) { + if (found != d->m_languages.end()) return *found; - } return {}; } -void TranslationsModel::setUseSystemLocale(const bool useSystemLocale) const +void TranslationsModel::setUseSystemLocale(bool useSystemLocale) { APPLICATION->settings()->set("UseSystemLocale", useSystemLocale); - QLocale::setDefault(useSystemLocale ? QLocale::system() : QLocale(selectedLanguage())); + QLocale::setDefault(QLocale(useSystemLocale ? QString::fromStdString(std::locale().name()) : defaultLangCode)); } -bool TranslationsModel::selectLanguage(QString key) const +bool TranslationsModel::selectLanguage(QString key) { QString& langCode = key; auto langPtr = findLanguageAsOptional(key); if (langCode.isEmpty()) { - d->m_noLanguageSet = true; + d->no_language_set = true; } if (!langPtr.has_value()) { - qWarning() << "Selected invalid language" << key << ", defaulting to" << g_defaultLangCode; - langCode = g_defaultLangCode; + qWarning() << "Selected invalid language" << key << ", defaulting to" << defaultLangCode; + langCode = defaultLangCode; } else { langCode = langPtr->key; } // uninstall existing translators if there are any - if (d->m_appTranslator) { - QCoreApplication::removeTranslator(d->m_appTranslator.get()); - d->m_appTranslator.reset(); + if (d->m_app_translator) { + QCoreApplication::removeTranslator(d->m_app_translator.get()); + d->m_app_translator.reset(); } - if (d->m_qtTranslator) { - QCoreApplication::removeTranslator(d->m_qtTranslator.get()); - d->m_qtTranslator.reset(); + if (d->m_qt_translator) { + QCoreApplication::removeTranslator(d->m_qt_translator.get()); + d->m_qt_translator.reset(); } /* @@ -475,11 +467,11 @@ bool TranslationsModel::selectLanguage(QString key) const * In a multithreaded application, the default locale should be set at application startup, before any non-GUI threads are created. * This function is not reentrant. */ - const bool useSystemLocale = APPLICATION->settings()->get("UseSystemLocale").toBool(); - QLocale::setDefault(useSystemLocale ? QLocale::system() : QLocale(langCode)); + QLocale::setDefault( + QLocale(APPLICATION->settings()->get("UseSystemLocale").toBool() ? QString::fromStdString(std::locale().name()) : langCode)); // if it's the default UI language, finish - if (langCode == g_defaultLangCode) { + if (langCode == defaultLangCode) { d->m_selectedLanguage = langCode; return true; } @@ -487,88 +479,89 @@ bool TranslationsModel::selectLanguage(QString key) const // otherwise install new translations bool successful = false; // FIXME: this is likely never present. FIX IT. - d->m_qtTranslator = std::make_unique(); - if (d->m_qtTranslator->load("qt_" + langCode, QLibraryInfo::path(QLibraryInfo::TranslationsPath))) { + d->m_qt_translator.reset(new QTranslator()); + if (d->m_qt_translator->load("qt_" + langCode, QLibraryInfo::path(QLibraryInfo::TranslationsPath))) { qDebug() << "Loading Qt Language File for" << langCode.toLocal8Bit().constData() << "..."; - if (!QCoreApplication::installTranslator(d->m_qtTranslator.get())) { + if (!QCoreApplication::installTranslator(d->m_qt_translator.get())) { qCritical() << "Loading Qt Language File failed."; - d->m_qtTranslator.reset(); + d->m_qt_translator.reset(); } else { successful = true; } } else { - d->m_qtTranslator.reset(); + d->m_qt_translator.reset(); } - if (langPtr->localFileType == FileType::Po) { + if (langPtr->localFileType == FileType::PO) { qDebug() << "Loading Application Language File for" << langCode.toLocal8Bit().constData() << "..."; - d->m_appTranslator = std::make_unique(FS::PathCombine(d->m_dir.path(), langCode + ".po")); - if (!d->m_appTranslator->isEmpty()) { - if (!QCoreApplication::installTranslator(d->m_appTranslator.get())) { + auto poTranslator = new POTranslator(FS::PathCombine(d->m_dir.path(), langCode + ".po")); + if (!poTranslator->isEmpty()) { + if (!QCoreApplication::installTranslator(poTranslator)) { + delete poTranslator; qCritical() << "Installing Application Language File failed."; - d->m_appTranslator.reset(); } else { + d->m_app_translator.reset(poTranslator); successful = true; } } else { qCritical() << "Loading Application Language File failed."; - d->m_appTranslator.reset(); + d->m_app_translator.reset(); } - } else if (langPtr->localFileType == FileType::Qm) { - d->m_appTranslator = std::make_unique(); - if (d->m_appTranslator->load("mmc_" + langCode, d->m_dir.path())) { + } else if (langPtr->localFileType == FileType::QM) { + d->m_app_translator.reset(new QTranslator()); + if (d->m_app_translator->load("mmc_" + langCode, d->m_dir.path())) { qDebug() << "Loading Application Language File for" << langCode.toLocal8Bit().constData() << "..."; - if (!QCoreApplication::installTranslator(d->m_appTranslator.get())) { + if (!QCoreApplication::installTranslator(d->m_app_translator.get())) { qCritical() << "Installing Application Language File failed."; - d->m_appTranslator.reset(); + d->m_app_translator.reset(); } else { successful = true; } } else { - d->m_appTranslator.reset(); + d->m_app_translator.reset(); } } else { - d->m_appTranslator.reset(); + d->m_app_translator.reset(); } d->m_selectedLanguage = langCode; return successful; } -QModelIndex TranslationsModel::selectedIndex() const +QModelIndex TranslationsModel::selectedIndex() { auto found = findLanguage(d->m_selectedLanguage); if (found != d->m_languages.end()) { return index(std::distance(d->m_languages.begin(), found), 0, QModelIndex()); } - return {}; + return QModelIndex(); } -QString TranslationsModel::selectedLanguage() const +QString TranslationsModel::selectedLanguage() { return d->m_selectedLanguage; } void TranslationsModel::downloadIndex() { - if (d->m_indexJob || d->m_downloadJob) { + if (d->m_index_job || d->m_dl_job) { return; } qDebug() << "Downloading Translations Index..."; - d->m_indexJob.reset(new NetJob("Translations Index", APPLICATION->network())); - const MetaEntryPtr entry = APPLICATION->metacache()->resolveEntry("translations", "index_v2.json"); + d->m_index_job.reset(new NetJob("Translations Index", APPLICATION->network())); + MetaEntryPtr entry = APPLICATION->metacache()->resolveEntry("translations", "index_v2.json"); entry->setStale(true); auto task = Net::Download::makeCached(QUrl(BuildConfig.TRANSLATION_FILES_URL + "index_v2.json"), entry); - d->m_indexTask = task.get(); - d->m_indexJob->addNetAction(task); - d->m_indexJob->setAskRetry(false); - connect(d->m_indexJob.get(), &NetJob::failed, this, &TranslationsModel::indexFailed); - connect(d->m_indexJob.get(), &NetJob::succeeded, this, &TranslationsModel::indexReceived); - d->m_indexJob->start(); + d->m_index_task = task.get(); + d->m_index_job->addNetAction(task); + d->m_index_job->setAskRetry(false); + connect(d->m_index_job.get(), &NetJob::failed, this, &TranslationsModel::indexFailed); + connect(d->m_index_job.get(), &NetJob::succeeded, this, &TranslationsModel::indexReceived); + d->m_index_job->start(); } -void TranslationsModel::updateLanguage(const QString& key) +void TranslationsModel::updateLanguage(QString key) { - if (key == g_defaultLangCode) { + if (key == defaultLangCode) { qWarning() << "Cannot update builtin language" << key; return; } @@ -582,9 +575,9 @@ void TranslationsModel::updateLanguage(const QString& key) } } -void TranslationsModel::downloadTranslation(const QString& key) +void TranslationsModel::downloadTranslation(QString key) { - if (d->m_downloadJob) { + if (d->m_dl_job) { d->m_nextDownload = key; return; } @@ -595,21 +588,21 @@ void TranslationsModel::downloadTranslation(const QString& key) } d->m_downloadingTranslation = key; - const MetaEntryPtr entry = APPLICATION->metacache()->resolveEntry("translations", "mmc_" + key + ".qm"); + MetaEntryPtr entry = APPLICATION->metacache()->resolveEntry("translations", "mmc_" + key + ".qm"); entry->setStale(true); - auto dl = Net::Download::makeCached(QUrl(BuildConfig.TRANSLATION_FILES_URL + lang->fileName), entry); - dl->addValidator(new Net::ChecksumValidator(QCryptographicHash::Sha1, lang->fileSha1)); - dl->setProgress(dl->getProgress(), lang->fileSize); + auto dl = Net::Download::makeCached(QUrl(BuildConfig.TRANSLATION_FILES_URL + lang->file_name), entry); + dl->addValidator(new Net::ChecksumValidator(QCryptographicHash::Sha1, lang->file_sha1)); + dl->setProgress(dl->getProgress(), lang->file_size); - d->m_downloadJob.reset(new NetJob("Translation for " + key, APPLICATION->network())); - d->m_downloadJob->addNetAction(dl); - d->m_downloadJob->setAskRetry(false); + d->m_dl_job.reset(new NetJob("Translation for " + key, APPLICATION->network())); + d->m_dl_job->addNetAction(dl); + d->m_dl_job->setAskRetry(false); - connect(d->m_downloadJob.get(), &NetJob::succeeded, this, &TranslationsModel::dlGood); - connect(d->m_downloadJob.get(), &NetJob::failed, this, &TranslationsModel::dlFailed); + connect(d->m_dl_job.get(), &NetJob::succeeded, this, &TranslationsModel::dlGood); + connect(d->m_dl_job.get(), &NetJob::failed, this, &TranslationsModel::dlFailed); - d->m_downloadJob->start(); + d->m_dl_job->start(); } void TranslationsModel::downloadNext() @@ -620,10 +613,10 @@ void TranslationsModel::downloadNext() } } -void TranslationsModel::dlFailed(const QString& reason) +void TranslationsModel::dlFailed(QString reason) { qCritical() << "Translations Download Failed:" << reason; - d->m_downloadJob.reset(); + d->m_dl_job.reset(); downloadNext(); } @@ -634,12 +627,12 @@ void TranslationsModel::dlGood() if (d->m_downloadingTranslation == d->m_selectedLanguage) { selectLanguage(d->m_selectedLanguage); } - d->m_downloadJob.reset(); + d->m_dl_job.reset(); downloadNext(); } -void TranslationsModel::indexFailed(const QString& reason) const +void TranslationsModel::indexFailed(QString reason) { qCritical() << "Translations Index Download Failed:" << reason; - d->m_indexJob.reset(); + d->m_index_job.reset(); } diff --git a/launcher/translations/TranslationsModel.h b/launcher/translations/TranslationsModel.h index 1dd0b601c..945e689fc 100644 --- a/launcher/translations/TranslationsModel.h +++ b/launcher/translations/TranslationsModel.h @@ -24,38 +24,38 @@ struct Language; class TranslationsModel : public QAbstractListModel { Q_OBJECT public: - explicit TranslationsModel(const QString& path, QObject* parent = nullptr); - ~TranslationsModel() override; + explicit TranslationsModel(QString path, QObject* parent = 0); + virtual ~TranslationsModel(); + + QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; + QVariant headerData(int section, Qt::Orientation orientation, int role) const override; + int rowCount(const QModelIndex& parent = QModelIndex()) const override; + int columnCount(const QModelIndex& parent) const override; + + bool selectLanguage(QString key); + void updateLanguage(QString key); + QModelIndex selectedIndex(); + QString selectedLanguage(); + + void downloadIndex(); + void setUseSystemLocale(bool useSystemLocale); + + private: + QList::Iterator findLanguage(const QString& key); + std::optional findLanguageAsOptional(const QString& key); + void reloadLocalFiles(); + void downloadTranslation(QString key); + void downloadNext(); // hide copy constructor TranslationsModel(const TranslationsModel&) = delete; // hide assign op TranslationsModel& operator=(const TranslationsModel&) = delete; - QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; // NOLINT(*-default-arguments) - QVariant headerData(int section, Qt::Orientation orientation, int role) const override; - int rowCount(const QModelIndex& parent = QModelIndex()) const override; // NOLINT(*-default-arguments) - bool selectLanguage(QString key) const; - void updateLanguage(const QString& key); - QModelIndex selectedIndex() const; - QString selectedLanguage() const; - - void downloadIndex(); - void setUseSystemLocale(bool useSystemLocale) const; - - private: - int columnCount(const QModelIndex& parent) const override; - - QList::Iterator findLanguage(const QString& key) const; - std::optional findLanguageAsOptional(const QString& key) const; - void reloadLocalFiles(); - void downloadTranslation(const QString& key); - void downloadNext(); - private slots: void indexReceived(); - void indexFailed(const QString& reason) const; - void dlFailed(const QString& reason); + void indexFailed(QString reason); + void dlFailed(QString reason); void dlGood(); void translationDirChanged(const QString& path); diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp index 1bdcd3f68..f4c170eb8 100644 --- a/launcher/ui/MainWindow.cpp +++ b/launcher/ui/MainWindow.cpp @@ -105,7 +105,6 @@ #include "ui/dialogs/NewInstanceDialog.h" #include "ui/dialogs/NewsDialog.h" #include "ui/dialogs/ProgressDialog.h" -#include "ui/dialogs/skins/SkinManageDialog.h" #include "ui/instanceview/InstanceDelegate.h" #include "ui/instanceview/InstanceProxyModel.h" #include "ui/instanceview/InstanceView.h" @@ -181,7 +180,7 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent), ui(new Ui::MainWi ui->instanceToolBar->insertSeparator(ui->actionLaunchInstance); // restore the instance toolbar settings - const auto setting_name = QString("WideBarVisibility_%1").arg(ui->instanceToolBar->objectName()); + auto const setting_name = QString("WideBarVisibility_%1").arg(ui->instanceToolBar->objectName()); instanceToolbarSetting = APPLICATION->settings()->getOrRegisterSetting(setting_name); ui->instanceToolBar->setVisibilityState(QByteArray::fromBase64(instanceToolbarSetting->get().toString().toUtf8())); @@ -397,7 +396,6 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent), ui(new Ui::MainWi // Shouldn't have to use lambdas here like this, but if I don't, the compiler throws a fit. // Template hell sucks... connect(APPLICATION->accounts(), &AccountList::defaultAccountChanged, [this] { defaultAccountChanged(); }); - connect(APPLICATION->accounts(), &AccountList::listActivityChanged, [this] { defaultAccountChanged(); }); connect(APPLICATION->accounts(), &AccountList::listChanged, [this] { defaultAccountChanged(); }); // Show initial account @@ -655,9 +653,6 @@ void MainWindow::repopulateAccountsMenu() auto accounts = APPLICATION->accounts(); MinecraftAccountPtr defaultAccount = accounts->defaultAccount(); - - bool canChangeSkin = defaultAccount && (defaultAccount->accountType() == AccountType::MSA) && !defaultAccount->isActive(); - ui->actionManageSkins->setEnabled(canChangeSkin); QString active_profileId = ""; if (defaultAccount) { @@ -714,7 +709,6 @@ void MainWindow::repopulateAccountsMenu() connect(ui->actionNoDefaultAccount, &QAction::triggered, this, &MainWindow::changeActiveAccount); ui->accountsMenu->addSeparator(); - ui->accountsMenu->addAction(ui->actionManageSkins); ui->accountsMenu->addAction(ui->actionManageAccounts); accountsButtonMenu->addActions(ui->accountsMenu->actions()); @@ -937,9 +931,6 @@ void MainWindow::processURLs(QList urls) { // NOTE: This loop only processes one dropped file! for (auto& url : urls) { - if (url.isEmpty() || url.toString().trimmed().isEmpty()) - continue; - qDebug() << "Processing" << url; // The isLocalFile() check below doesn't work as intended without an explicit scheme. @@ -951,7 +942,9 @@ void MainWindow::processURLs(QList urls) QUrl local_url; if (!url.isLocalFile()) { // download the remote resource and identify - const bool isExternalURLImport = (url.host().toLower() == "import") || (url.path().startsWith("/import", Qt::CaseInsensitive)); + const bool isExternalURLImport = + (url.host().toLower() == "import") || + (url.path().startsWith("/import", Qt::CaseInsensitive)); QUrl dl_url; if (url.scheme() == "curseforge" || (url.scheme() == BuildConfig.LAUNCHER_APP_BINARY_NAME && url.host() == "install")) { @@ -959,7 +952,7 @@ void MainWindow::processURLs(QList urls) // format of url curseforge://install?addonId=IDHERE&fileId=IDHERE // format of url binaryname://install?platform=curseforge&addonId=IDHERE&fileId=IDHERE QUrlQuery query(url); - + // check if this is a binaryname:// url if (url.scheme() == BuildConfig.LAUNCHER_APP_BINARY_NAME) { // check this is an curseforge platform request @@ -1022,7 +1015,8 @@ void MainWindow::processURLs(QList urls) receivedData.insert(it->first, it->second); emit APPLICATION->oauthReplyRecieved(receivedData); continue; - } else if ((url.scheme() == "prismlauncher" || url.scheme() == BuildConfig.LAUNCHER_APP_BINARY_NAME) && isExternalURLImport) { + } else if ((url.scheme() == "prismlauncher" || url.scheme() == BuildConfig.LAUNCHER_APP_BINARY_NAME) + && isExternalURLImport) { // PrismLauncher URL protocol modpack import // works for any prism fork // preferred import format: prismlauncher://import?url=ENCODED @@ -1041,6 +1035,7 @@ void MainWindow::processURLs(QList urls) // alternative import format: prismlauncher://import/ENCODED if (encodedTarget.isEmpty()) { + QString p = path; if (p.startsWith("/import/", Qt::CaseInsensitive)) { @@ -1055,9 +1050,12 @@ void MainWindow::processURLs(QList urls) } if (encodedTarget.isEmpty()) { - CustomMessageBox::selectable(this, tr("Error"), tr("Invalid import link: missing 'url' parameter."), - QMessageBox::Critical) - ->show(); + CustomMessageBox::selectable( + this, + tr("Error"), + tr("Invalid import link: missing 'url' parameter."), + QMessageBox::Critical + )->show(); continue; } @@ -1067,15 +1065,23 @@ void MainWindow::processURLs(QList urls) // Validate: only allow http(s) if (!target.isValid() || (target.scheme() != "https" && target.scheme() != "http")) { - CustomMessageBox::selectable(this, tr("Error"), tr("Invalid import link: URL must be http(s)."), QMessageBox::Critical) - ->show(); + CustomMessageBox::selectable( + this, + tr("Error"), + tr("Invalid import link: URL must be http(s)."), + QMessageBox::Critical + )->show(); continue; } const auto res = QMessageBox::question( - this, tr("Install modpack"), - tr("Do you want to download and import a modpack from:\n%1\n\nURL:\n%2").arg(target.host(), target.toString()), - QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes); + this, + tr("Install modpack"), + tr("Do you want to download and import a modpack from:\n%1\n\nURL:\n%2") + .arg(target.host(), target.toString()), + QMessageBox::Yes | QMessageBox::No, + QMessageBox::Yes + ); if (res != QMessageBox::Yes) { continue; } @@ -1119,11 +1125,6 @@ void MainWindow::processURLs(QList urls) auto localFileName = QDir::toNativeSeparators(local_url.toLocalFile()); QFileInfo localFileInfo(localFileName); - if (localFileName.isEmpty() || !localFileInfo.exists()) { - qDebug() << "Ignoring invalid path" << localFileName; - continue; - } - auto type = ResourceUtils::identify(localFileInfo); if (ModPlatform::ResourceTypeUtils::VALID_RESOURCES.count(type) == 0) { // probably instance/modpack @@ -1395,16 +1396,6 @@ void MainWindow::on_actionEditInstance_triggered() } } -void MainWindow::on_actionManageSkins_triggered() -{ - auto account = APPLICATION->accounts()->defaultAccount(); - - if (account && (account->accountType() == AccountType::MSA) && !account->isActive()) { - SkinManageDialog dialog(this, account); - dialog.exec(); - } -} - void MainWindow::on_actionManageAccounts_triggered() { APPLICATION->ShowGlobalSettings(this, "accounts"); diff --git a/launcher/ui/MainWindow.h b/launcher/ui/MainWindow.h index 80860deef..7dcba885a 100644 --- a/launcher/ui/MainWindow.h +++ b/launcher/ui/MainWindow.h @@ -130,8 +130,6 @@ class MainWindow : public QMainWindow { void on_actionSettings_triggered(); - void on_actionManageSkins_triggered(); - void on_actionManageAccounts_triggered(); void on_actionReportBug_triggered(); diff --git a/launcher/ui/MainWindow.ui b/launcher/ui/MainWindow.ui index e9b9aa442..353788518 100644 --- a/launcher/ui/MainWindow.ui +++ b/launcher/ui/MainWindow.ui @@ -322,14 +322,6 @@ QAction::PreferencesRole - - - - - - Manage &Skins... - - @@ -528,7 +520,7 @@ Close the current window - QAction::MenuRole::NoRole + QAction::QuitRole diff --git a/launcher/ui/dialogs/ExportToModListDialog.cpp b/launcher/ui/dialogs/ExportToModListDialog.cpp index a782a9190..e8873f9b4 100644 --- a/launcher/ui/dialogs/ExportToModListDialog.cpp +++ b/launcher/ui/dialogs/ExportToModListDialog.cpp @@ -214,8 +214,6 @@ void ExportToModListDialog::addExtra(ExportToModList::OptionalData option) case ExportToModList::FileName: ui->templateText->insertPlainText("{filename}"); break; - case ExportToModList::None: - break; } } void ExportToModListDialog::enableCustom(bool enabled) diff --git a/launcher/ui/dialogs/IconPickerDialog.cpp b/launcher/ui/dialogs/IconPickerDialog.cpp index b2269cc70..b56e95dba 100644 --- a/launcher/ui/dialogs/IconPickerDialog.cpp +++ b/launcher/ui/dialogs/IconPickerDialog.cpp @@ -30,106 +30,26 @@ #include "icons/IconList.h" #include "icons/IconUtils.h" -class IconProxyModel : public QSortFilterProxyModel -{ -public: - explicit IconProxyModel(QObject* parent = nullptr) : QSortFilterProxyModel(parent) - { - } - - void setCategory(IconPickerDialog::IconPickerCategory category) - { - if (m_category == category) - return; - m_category = category; - invalidateFilter(); - } - -protected: - bool filterAcceptsRow(int source_row, const QModelIndex& source_parent) const override - { - if (!QSortFilterProxyModel::filterAcceptsRow(source_row, source_parent)) - return false; - - if (m_category == IconPickerDialog::Any) - return true; - - auto model = static_cast(sourceModel()); - QModelIndex index = model->index(source_row, 0, source_parent); - QString key = model->data(index, Qt::UserRole).toString(); - const MMCIcon* icon = model->icon(key); - - if (!icon) - return false; - - bool isModpack = false; - bool isBuiltin = icon->isBuiltIn(); - bool isLegacy = isBuiltin && icon->name().endsWith("_legacy", Qt::CaseInsensitive); - - if (!isBuiltin) { - const QString& name = icon->name(); - if (name.startsWith("curseforge_", Qt::CaseInsensitive) || - name.startsWith("modrinth_", Qt::CaseInsensitive) || - name.startsWith("ftb_", Qt::CaseInsensitive) || - name.startsWith("technic_", Qt::CaseInsensitive) || - name.startsWith("atl_", Qt::CaseInsensitive)) { - isModpack = true; - } - } - - switch (m_category) { - case IconPickerDialog::Legacy: - return isBuiltin && isLegacy; - case IconPickerDialog::Modpacks: - return isModpack; - case IconPickerDialog::Modern: - return isBuiltin && !isLegacy; - case IconPickerDialog::Custom: - return !isBuiltin && !isModpack; - default: - return true; - } - } - -private: - IconPickerDialog::IconPickerCategory m_category = IconPickerDialog::Any; -}; - IconPickerDialog::IconPickerDialog(QWidget* parent) : QDialog(parent), ui(new Ui::IconPickerDialog) { ui->setupUi(this); setWindowModality(Qt::WindowModal); - static const QString context_text[] = { - tr("All"), - tr("Modern"), - tr("Legacy"), - tr("Modpacks"), - tr("Custom"), - }; - static const IconPickerCategory context_id[] = { - Any, - Modern, - Legacy, - Modpacks, - Custom, - }; - const int cnt = sizeof(context_text) / sizeof(context_text[0]); - for (int i = 0; i < cnt; ++i) { - ui->contextCombo->addItem(context_text[i], context_id[i]); - if (i == 0) { - ui->contextCombo->insertSeparator(i + 1); - } - } + searchBar = new QLineEdit(this); + searchBar->setPlaceholderText(tr("Search...")); + ui->verticalLayout->insertWidget(0, searchBar); - proxyModel = new IconProxyModel(this); + proxyModel = new QSortFilterProxyModel(this); proxyModel->setSourceModel(APPLICATION->icons()); proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive); ui->iconView->setModel(proxyModel); auto contentsWidget = ui->iconView; + contentsWidget->setViewMode(QListView::IconMode); contentsWidget->setFlow(QListView::LeftToRight); contentsWidget->setIconSize(QSize(48, 48)); + contentsWidget->setMovement(QListView::Static); + contentsWidget->setResizeMode(QListView::Adjust); contentsWidget->setSelectionMode(QAbstractItemView::SingleSelection); contentsWidget->setSpacing(5); contentsWidget->setWordWrap(false); @@ -166,11 +86,7 @@ IconPickerDialog::IconPickerDialog(QWidget* parent) : QDialog(parent), ui(new Ui auto buttonFolder = ui->buttonBox->addButton(tr("Open Folder"), QDialogButtonBox::ResetRole); connect(buttonFolder, &QPushButton::clicked, this, &IconPickerDialog::openFolder); - connect(ui->searchLine, &QLineEdit::textChanged, this, &IconPickerDialog::filterIcons); - connect(ui->contextCombo, &QComboBox::currentIndexChanged, this, [this](int index) { - IconPickerCategory category = static_cast(ui->contextCombo->itemData(index).toInt()); - filterIconsByCategory(category); - }); + connect(searchBar, &QLineEdit::textChanged, this, &IconPickerDialog::filterIcons); // Prevent incorrect indices from e.g. filesystem changes connect(APPLICATION->icons(), &IconList::iconUpdated, this, [this]() { proxyModel->invalidate(); }); } @@ -266,8 +182,3 @@ void IconPickerDialog::filterIcons(const QString& query) { proxyModel->setFilterFixedString(query); } - -void IconPickerDialog::filterIconsByCategory(IconPickerCategory category) -{ - static_cast(proxyModel)->setCategory(category); -} diff --git a/launcher/ui/dialogs/IconPickerDialog.h b/launcher/ui/dialogs/IconPickerDialog.h index 063f9b905..db1315338 100644 --- a/launcher/ui/dialogs/IconPickerDialog.h +++ b/launcher/ui/dialogs/IconPickerDialog.h @@ -32,15 +32,6 @@ class IconPickerDialog : public QDialog { int execWithSelection(QString selection); QString selectedIconKey; - enum IconPickerCategory { - Any, - Modern, - Legacy, - Modpacks, - Custom, - }; - Q_ENUM(IconPickerCategory) - protected: virtual bool eventFilter(QObject*, QEvent*); @@ -58,5 +49,4 @@ class IconPickerDialog : public QDialog { void removeSelectedIcon(); void openFolder(); void filterIcons(const QString& text); - void filterIconsByCategory(IconPickerCategory); }; diff --git a/launcher/ui/dialogs/IconPickerDialog.ui b/launcher/ui/dialogs/IconPickerDialog.ui index 948e7043f..c548edfb7 100644 --- a/launcher/ui/dialogs/IconPickerDialog.ui +++ b/launcher/ui/dialogs/IconPickerDialog.ui @@ -15,64 +15,7 @@ - - - - - - - Icon category - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Search Icons... - - - true - - - - - - - - - - - - 60 - 60 - - - - QListView::Static - - - QListView::Adjust - - - QListView::IconMode - - - true - - + diff --git a/launcher/ui/dialogs/InstallLoaderDialog.cpp b/launcher/ui/dialogs/InstallLoaderDialog.cpp index deb5358fb..2e9abe631 100644 --- a/launcher/ui/dialogs/InstallLoaderDialog.cpp +++ b/launcher/ui/dialogs/InstallLoaderDialog.cpp @@ -101,12 +101,12 @@ InstallLoaderDialog::InstallLoaderDialog(PackProfile* profile, const QString& ui buttonLayout->setContentsMargins(0, 0, 6, 6); #endif auto refreshButton = new QPushButton(tr("&Refresh"), this); - connect(refreshButton, &QPushButton::clicked, this, [this] { pageCast(container->selectedPage())->loadList(true); }); + connect(refreshButton, &QPushButton::clicked, this, [this] { pageCast(container->selectedPage())->loadList(); }); buttonLayout->addWidget(refreshButton); buttons->setOrientation(Qt::Horizontal); buttons->setStandardButtons(QDialogButtonBox::Cancel | QDialogButtonBox::Ok); - buttons->button(QDialogButtonBox::Ok)->setText(tr("OK")); + buttons->button(QDialogButtonBox::Ok)->setText(tr("Ok")); buttons->button(QDialogButtonBox::Cancel)->setText(tr("Cancel")); connect(buttons, &QDialogButtonBox::accepted, this, &QDialog::accept); connect(buttons, &QDialogButtonBox::rejected, this, &QDialog::reject); diff --git a/launcher/ui/dialogs/ProgressDialog.cpp b/launcher/ui/dialogs/ProgressDialog.cpp index 0a453bda5..6aa0b4bdf 100644 --- a/launcher/ui/dialogs/ProgressDialog.cpp +++ b/launcher/ui/dialogs/ProgressDialog.cpp @@ -252,7 +252,10 @@ void ProgressDialog::changeStepProgress(TaskStepProgress const& task_progress) task_bar->setValue(mapped_current); task_bar->setStatus(task_progress.status); task_bar->setDetails(task_progress.details); - task_bar->setVisible(!task_progress.isDone()); + + if (task_progress.isDone()) { + task_bar->setVisible(false); + } } void ProgressDialog::changeProgress(qint64 current, qint64 total) diff --git a/launcher/ui/dialogs/ResourceDownloadDialog.cpp b/launcher/ui/dialogs/ResourceDownloadDialog.cpp index bcb30c761..002f85e0f 100644 --- a/launcher/ui/dialogs/ResourceDownloadDialog.cpp +++ b/launcher/ui/dialogs/ResourceDownloadDialog.cpp @@ -22,7 +22,6 @@ #include #include -#include #include "Application.h" #include "ResourceDownloadTask.h" @@ -50,12 +49,11 @@ namespace ResourceDownload { -ResourceDownloadDialog::ResourceDownloadDialog(QWidget* parent, ResourceFolderModel* baseModel, bool suppressInitialSearch) +ResourceDownloadDialog::ResourceDownloadDialog(QWidget* parent, ResourceFolderModel* base_model) : QDialog(parent) - , m_base_model(baseModel) + , m_base_model(base_model) , m_buttons(QDialogButtonBox::Help | QDialogButtonBox::Ok | QDialogButtonBox::Cancel) , m_vertical_layout(this) - , m_suppressInitialSearch(suppressInitialSearch) { setObjectName(QStringLiteral("ResourceDownloadDialog")); @@ -63,35 +61,34 @@ ResourceDownloadDialog::ResourceDownloadDialog(QWidget* parent, ResourceFolderMo setWindowIcon(QIcon::fromTheme("new")); -// small margins look ugly on macOS on modal windows -#ifndef Q_OS_MACOS + // small margins look ugly on macOS on modal windows + #ifndef Q_OS_MACOS m_buttons.setContentsMargins(0, 0, 6, 6); -#endif + #endif // Bonk Qt over its stupid head and make sure it understands which button is the default one... // See: https://stackoverflow.com/questions/24556831/qbuttonbox-set-default-button - auto* okButton = m_buttons.button(QDialogButtonBox::Ok); - okButton->setEnabled(false); - okButton->setDefault(true); - okButton->setAutoDefault(true); - okButton->setText(tr("Review and confirm")); - okButton->setShortcut(tr("Ctrl+Return")); + auto OkButton = m_buttons.button(QDialogButtonBox::Ok); + OkButton->setEnabled(false); + OkButton->setDefault(true); + OkButton->setAutoDefault(true); + OkButton->setText(tr("Review and confirm")); + OkButton->setShortcut(tr("Ctrl+Return")); - auto* cancelButton = m_buttons.button(QDialogButtonBox::Cancel); - cancelButton->setDefault(false); - cancelButton->setAutoDefault(false); + auto CancelButton = m_buttons.button(QDialogButtonBox::Cancel); + CancelButton->setDefault(false); + CancelButton->setAutoDefault(false); - auto* helpButton = m_buttons.button(QDialogButtonBox::Help); - helpButton->setDefault(false); - helpButton->setAutoDefault(false); + auto HelpButton = m_buttons.button(QDialogButtonBox::Help); + HelpButton->setDefault(false); + HelpButton->setAutoDefault(false); setWindowModality(Qt::WindowModal); } void ResourceDownloadDialog::accept() { - if (!geometrySaveKey().isEmpty()) { + if (!geometrySaveKey().isEmpty()) APPLICATION->settings()->set(geometrySaveKey(), QString::fromUtf8(saveGeometry().toBase64())); - } QDialog::accept(); } @@ -111,9 +108,8 @@ void ResourceDownloadDialog::reject() } } - if (!geometrySaveKey().isEmpty()) { + if (!geometrySaveKey().isEmpty()) APPLICATION->settings()->set(geometrySaveKey(), QString::fromUtf8(saveGeometry().toBase64())); - } QDialog::reject(); } @@ -122,10 +118,10 @@ void ResourceDownloadDialog::reject() // won't work with subclasses if we put it in this ctor. void ResourceDownloadDialog::initializeContainer() { -// small margins look ugly on macOS on modal windows -#ifndef Q_OS_MACOS + // small margins look ugly on macOS on modal windows + #ifndef Q_OS_MACOS layout()->setContentsMargins(0, 0, 0, 0); -#endif + #endif m_container = new PageContainer(this, {}, this); m_container->setSizePolicy(QSizePolicy::Policy::Preferred, QSizePolicy::Policy::Expanding); @@ -139,28 +135,28 @@ void ResourceDownloadDialog::initializeContainer() void ResourceDownloadDialog::connectButtons() { - auto* okButton = m_buttons.button(QDialogButtonBox::Ok); - okButton->setToolTip( + auto OkButton = m_buttons.button(QDialogButtonBox::Ok); + OkButton->setToolTip( tr("Opens a new popup to review your selected %1 and confirm your selection. Shortcut: Ctrl+Return").arg(resourcesString())); - connect(okButton, &QPushButton::clicked, this, &ResourceDownloadDialog::confirm); + connect(OkButton, &QPushButton::clicked, this, &ResourceDownloadDialog::confirm); - auto* cancelButton = m_buttons.button(QDialogButtonBox::Cancel); - connect(cancelButton, &QPushButton::clicked, this, &ResourceDownloadDialog::reject); + auto CancelButton = m_buttons.button(QDialogButtonBox::Cancel); + connect(CancelButton, &QPushButton::clicked, this, &ResourceDownloadDialog::reject); - auto* helpButton = m_buttons.button(QDialogButtonBox::Help); - connect(helpButton, &QPushButton::clicked, m_container, &PageContainer::help); + auto HelpButton = m_buttons.button(QDialogButtonBox::Help); + connect(HelpButton, &QPushButton::clicked, m_container, &PageContainer::help); } void ResourceDownloadDialog::confirm() { - auto* confirmDialog = ReviewMessageBox::create(this, tr("Confirm %1 to download").arg(resourcesString())); - confirmDialog->retranslateUi(resourcesString()); + auto confirm_dialog = ReviewMessageBox::create(this, tr("Confirm %1 to download").arg(resourcesString())); + confirm_dialog->retranslateUi(resourcesString()); QHash dependencyExtraInfo; QStringList depNames; if (auto task = getModDependenciesTask(); task) { connect(task.get(), &Task::failed, this, - [this](const QString& reason) { CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->exec(); }); + [this](QString reason) { CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->exec(); }); auto weak = task.toWeakRef(); connect(task.get(), &Task::succeeded, this, [this, weak]() { @@ -174,77 +170,72 @@ void ResourceDownloadDialog::confirm() }); // Check for updates - ProgressDialog progressDialog(this); - progressDialog.setSkipButton(true, tr("Abort")); - progressDialog.setWindowTitle(tr("Checking for dependencies...")); - auto ret = progressDialog.execWithTask(task.get()); + ProgressDialog progress_dialog(this); + progress_dialog.setSkipButton(true, tr("Abort")); + progress_dialog.setWindowTitle(tr("Checking for dependencies...")); + auto ret = progress_dialog.execWithTask(task.get()); // If the dialog was skipped / some download error happened if (ret == QDialog::DialogCode::Rejected) { QMetaObject::invokeMethod(this, "reject", Qt::QueuedConnection); return; + } else { + for (auto dep : task->getDependecies()) { + addResource(dep->pack, dep->version); + depNames << dep->pack->name; + } + dependencyExtraInfo = task->getExtraInfo(); } - for (const auto& dep : task->getDependecies()) { - addResource(dep->pack, dep->version, "dependency"); - depNames << dep->pack->name; - } - dependencyExtraInfo = task->getExtraInfo(); } auto selected = getTasks(); - std::ranges::sort(selected, [](const DownloadTaskPtr& a, const DownloadTaskPtr& b) { + std::sort(selected.begin(), selected.end(), [](const DownloadTaskPtr& a, const DownloadTaskPtr& b) { return QString::compare(a->getName(), b->getName(), Qt::CaseInsensitive) < 0; }); for (auto& task : selected) { auto extraInfo = dependencyExtraInfo.value(task->getPack()->addonId.toString()); - confirmDialog->appendResource({ .name = task->getName(), - .filename = task->getFilename(), - .provider = ModPlatform::ProviderCapabilities::name(task->getProvider()), - .required_by = extraInfo.required_by, - .version_type = task->getVersion().version_type.toString(), - .enabled = !extraInfo.maybe_installed }); + confirm_dialog->appendResource({ task->getName(), task->getFilename(), ModPlatform::ProviderCapabilities::name(task->getProvider()), + extraInfo.required_by, task->getVersion().version_type.toString(), !extraInfo.maybe_installed }); } - if (confirmDialog->exec() != 0) { - auto deselected = confirmDialog->deselectedResources(); - for (auto* page : m_container->getPages()) { - auto* res = static_cast(page); - for (const auto& name : deselected) { + if (confirm_dialog->exec()) { + auto deselected = confirm_dialog->deselectedResources(); + for (auto page : m_container->getPages()) { + auto res = static_cast(page); + for (auto name : deselected) res->removeResourceFromPage(name); - } } this->accept(); } else { - for (const auto& name : depNames) { + for (auto name : depNames) removeResource(name); - } } } bool ResourceDownloadDialog::selectPage(QString pageId) { - return m_container->selectPage(std::move(pageId)); + return m_container->selectPage(pageId); } ResourcePage* ResourceDownloadDialog::selectedPage() { - auto* result = dynamic_cast(m_container->selectedPage()); + ResourcePage* result = dynamic_cast(m_container->selectedPage()); Q_ASSERT(result != nullptr); return result; } -void ResourceDownloadDialog::addResource(ModPlatform::IndexedPack::Ptr pack, ModPlatform::IndexedVersion& ver, QString downloadReason) +void ResourceDownloadDialog::addResource(ModPlatform::IndexedPack::Ptr pack, ModPlatform::IndexedVersion& ver) { removeResource(pack->name); - selectedPage()->addResourceToPage(pack, ver, getBaseModel(), std::move(downloadReason)); + selectedPage()->addResourceToPage(pack, ver, getBaseModel()); setButtonStatus(); } -void ResourceDownloadDialog::removeResource(const QString& packName) +void ResourceDownloadDialog::removeResource(const QString& pack_name) { - for (auto* page : m_container->getPages()) { - static_cast(page)->removeResourceFromPage(packName); + for (auto page : m_container->getPages()) { + static_cast(page)->removeResourceFromPage(pack_name); } setButtonStatus(); } @@ -252,18 +243,18 @@ void ResourceDownloadDialog::removeResource(const QString& packName) void ResourceDownloadDialog::setButtonStatus() { auto selected = false; - for (auto* page : m_container->getPages()) { - auto* res = static_cast(page); + for (auto page : m_container->getPages()) { + auto res = static_cast(page); selected = selected || res->hasSelectedPacks(); } m_buttons.button(QDialogButtonBox::Ok)->setEnabled(selected); } -QList ResourceDownloadDialog::getTasks() +const QList ResourceDownloadDialog::getTasks() { QList selected; - for (auto* page : m_container->getPages()) { - auto* res = static_cast(page); + for (auto page : m_container->getPages()) { + auto res = static_cast(page); selected.append(res->selectedPacks()); } return selected; @@ -271,34 +262,28 @@ QList ResourceDownloadDialog::getTasks( void ResourceDownloadDialog::selectedPageChanged(BasePage* previous, BasePage* selected) { - // If previous is null (first selection), nothing to sync - if (!previous) { - return; - } - - auto* prevPage = dynamic_cast(previous); - if (!prevPage) { + auto* prev_page = dynamic_cast(previous); + if (!prev_page) { qCritical() << "Page '" << previous->displayName() << "' in ResourceDownloadDialog is not a ResourcePage!"; return; } // Same effect as having a global search bar - auto* result = dynamic_cast(selected); + ResourcePage* result = dynamic_cast(selected); Q_ASSERT(result != nullptr); - result->setSearchTerm(prevPage->getSearchTerm()); + result->setSearchTerm(prev_page->getSearchTerm()); } -ModDownloadDialog::ModDownloadDialog(QWidget* parent, ModFolderModel* mods, BaseInstance* instance, bool suppressInitialSearch) - : ResourceDownloadDialog(parent, mods, suppressInitialSearch), m_instance(instance) +ModDownloadDialog::ModDownloadDialog(QWidget* parent, ModFolderModel* mods, BaseInstance* instance) + : ResourceDownloadDialog(parent, mods), m_instance(instance) { setWindowTitle(dialogTitle()); initializeContainer(); connectButtons(); - if (!geometrySaveKey().isEmpty()) { + if (!geometrySaveKey().isEmpty()) restoreGeometry(QByteArray::fromBase64(APPLICATION->settings()->get(geometrySaveKey()).toString().toUtf8())); - } } QList ModDownloadDialog::getPages() @@ -307,16 +292,10 @@ QList ModDownloadDialog::getPages() auto loaders = static_cast(m_instance)->getPackProfile()->getSupportedModLoaders().value(); - if (ModrinthAPI::validateModLoaders(loaders)) { - auto* page = ModrinthModPage::create(this, *m_instance); - page->setSuppressInitialSearch(m_suppressInitialSearch); - pages.append(page); - } - if (APPLICATION->capabilities() & Application::SupportsFlame && FlameAPI::validateModLoaders(loaders)) { - auto* page = FlameModPage::create(this, *m_instance); - page->setSuppressInitialSearch(m_suppressInitialSearch); - pages.append(page); - } + if (ModrinthAPI::validateModLoaders(loaders)) + pages.append(ModrinthModPage::create(this, *m_instance)); + if (APPLICATION->capabilities() & Application::SupportsFlame && FlameAPI::validateModLoaders(loaders)) + pages.append(FlameModPage::create(this, *m_instance)); return pages; } @@ -324,9 +303,9 @@ QList ModDownloadDialog::getPages() GetModDependenciesTask::Ptr ModDownloadDialog::getModDependenciesTask() { if (!APPLICATION->settings()->get("ModDependenciesDisabled").toBool()) { // dependencies - if (auto* model = dynamic_cast(getBaseModel()); model) { + if (auto model = dynamic_cast(getBaseModel()); model) { QList> selectedVers; - for (const auto& selected : getTasks()) { + for (auto& selected : getTasks()) { selectedVers.append(std::make_shared(selected->getPack(), selected->getVersion())); } @@ -336,97 +315,70 @@ GetModDependenciesTask::Ptr ModDownloadDialog::getModDependenciesTask() return nullptr; } -ResourcePackDownloadDialog::ResourcePackDownloadDialog(QWidget* parent, - ResourcePackFolderModel* resourcePacks, - BaseInstance* instance, - bool suppressInitialSearch) - : ResourceDownloadDialog(parent, resourcePacks, suppressInitialSearch), m_instance(instance) +ResourcePackDownloadDialog::ResourcePackDownloadDialog(QWidget* parent, ResourcePackFolderModel* resource_packs, BaseInstance* instance) + : ResourceDownloadDialog(parent, resource_packs), m_instance(instance) { setWindowTitle(dialogTitle()); initializeContainer(); connectButtons(); - if (!geometrySaveKey().isEmpty()) { + if (!geometrySaveKey().isEmpty()) restoreGeometry(QByteArray::fromBase64(APPLICATION->settings()->get(geometrySaveKey()).toString().toUtf8())); - } } QList ResourcePackDownloadDialog::getPages() { QList pages; - auto* modrinthPage = ModrinthResourcePackPage::create(this, *m_instance); - modrinthPage->setSuppressInitialSearch(m_suppressInitialSearch); - pages.append(modrinthPage); - if (APPLICATION->capabilities() & Application::SupportsFlame) { - auto* flamePage = FlameResourcePackPage::create(this, *m_instance); - flamePage->setSuppressInitialSearch(m_suppressInitialSearch); - pages.append(flamePage); - } + pages.append(ModrinthResourcePackPage::create(this, *m_instance)); + if (APPLICATION->capabilities() & Application::SupportsFlame) + pages.append(FlameResourcePackPage::create(this, *m_instance)); return pages; } -TexturePackDownloadDialog::TexturePackDownloadDialog(QWidget* parent, - TexturePackFolderModel* resourcePacks, - BaseInstance* instance, - bool suppressInitialSearch) - : ResourceDownloadDialog(parent, resourcePacks, suppressInitialSearch), m_instance(instance) +TexturePackDownloadDialog::TexturePackDownloadDialog(QWidget* parent, TexturePackFolderModel* resource_packs, BaseInstance* instance) + : ResourceDownloadDialog(parent, resource_packs), m_instance(instance) { setWindowTitle(dialogTitle()); initializeContainer(); connectButtons(); - if (!geometrySaveKey().isEmpty()) { + if (!geometrySaveKey().isEmpty()) restoreGeometry(QByteArray::fromBase64(APPLICATION->settings()->get(geometrySaveKey()).toString().toUtf8())); - } } QList TexturePackDownloadDialog::getPages() { QList pages; - auto* modrinthPage = ModrinthTexturePackPage::create(this, *m_instance); - modrinthPage->setSuppressInitialSearch(m_suppressInitialSearch); - pages.append(modrinthPage); - if (APPLICATION->capabilities() & Application::SupportsFlame) { - auto* flamePage = FlameTexturePackPage::create(this, *m_instance); - flamePage->setSuppressInitialSearch(m_suppressInitialSearch); - pages.append(flamePage); - } + pages.append(ModrinthTexturePackPage::create(this, *m_instance)); + if (APPLICATION->capabilities() & Application::SupportsFlame) + pages.append(FlameTexturePackPage::create(this, *m_instance)); return pages; } -ShaderPackDownloadDialog::ShaderPackDownloadDialog(QWidget* parent, - ShaderPackFolderModel* shaders, - BaseInstance* instance, - bool suppressInitialSearch) - : ResourceDownloadDialog(parent, shaders, suppressInitialSearch), m_instance(instance) +ShaderPackDownloadDialog::ShaderPackDownloadDialog(QWidget* parent, ShaderPackFolderModel* shaders, BaseInstance* instance) + : ResourceDownloadDialog(parent, shaders), m_instance(instance) { setWindowTitle(dialogTitle()); initializeContainer(); connectButtons(); - if (!geometrySaveKey().isEmpty()) { + if (!geometrySaveKey().isEmpty()) restoreGeometry(QByteArray::fromBase64(APPLICATION->settings()->get(geometrySaveKey()).toString().toUtf8())); - } } QList ShaderPackDownloadDialog::getPages() { QList pages; - auto* modrinthPage = ModrinthShaderPackPage::create(this, *m_instance); - modrinthPage->setSuppressInitialSearch(m_suppressInitialSearch); - pages.append(modrinthPage); - if (APPLICATION->capabilities() & Application::SupportsFlame) { - auto* flamePage = FlameShaderPackPage::create(this, *m_instance); - flamePage->setSuppressInitialSearch(m_suppressInitialSearch); - pages.append(flamePage); - } + pages.append(ModrinthShaderPackPage::create(this, *m_instance)); + if (APPLICATION->capabilities() & Application::SupportsFlame) + pages.append(FlameShaderPackPage::create(this, *m_instance)); return pages; } @@ -440,41 +392,31 @@ void ResourceDownloadDialog::setResourceMetadata(const std::shared_ptrname)); m_container->hidePageList(); m_buttons.hide(); - auto* page = selectedPage(); + auto page = selectedPage(); page->openProject(meta->project_id); } -DataPackDownloadDialog::DataPackDownloadDialog(QWidget* parent, - DataPackFolderModel* dataPacks, - BaseInstance* instance, - bool suppressInitialSearch) - : ResourceDownloadDialog(parent, dataPacks, suppressInitialSearch), m_instance(instance) +DataPackDownloadDialog::DataPackDownloadDialog(QWidget* parent, DataPackFolderModel* data_packs, BaseInstance* instance) + : ResourceDownloadDialog(parent, data_packs), m_instance(instance) { setWindowTitle(dialogTitle()); initializeContainer(); connectButtons(); - if (!geometrySaveKey().isEmpty()) { + if (!geometrySaveKey().isEmpty()) restoreGeometry(QByteArray::fromBase64(APPLICATION->settings()->get(geometrySaveKey()).toByteArray())); - } } QList DataPackDownloadDialog::getPages() { QList pages; - auto* modrinthPage = ModrinthDataPackPage::create(this, *m_instance); - modrinthPage->setSuppressInitialSearch(m_suppressInitialSearch); - pages.append(modrinthPage); - if (APPLICATION->capabilities() & Application::SupportsFlame) { - auto* flamePage = FlameDataPackPage::create(this, *m_instance); - flamePage->setSuppressInitialSearch(m_suppressInitialSearch); - pages.append(flamePage); - } + pages.append(ModrinthDataPackPage::create(this, *m_instance)); + if (APPLICATION->capabilities() & Application::SupportsFlame) + pages.append(FlameDataPackPage::create(this, *m_instance)); return pages; } diff --git a/launcher/ui/dialogs/ResourceDownloadDialog.h b/launcher/ui/dialogs/ResourceDownloadDialog.h index bea6c7689..a85a85a09 100644 --- a/launcher/ui/dialogs/ResourceDownloadDialog.h +++ b/launcher/ui/dialogs/ResourceDownloadDialog.h @@ -51,7 +51,7 @@ class ResourceDownloadDialog : public QDialog, public BasePageProvider { public: using DownloadTaskPtr = shared_qobject_ptr; - ResourceDownloadDialog(QWidget* parent, ResourceFolderModel* baseModel, bool suppressInitialSearch = false); + ResourceDownloadDialog(QWidget* parent, ResourceFolderModel* base_model); void initializeContainer(); void connectButtons(); @@ -64,10 +64,10 @@ class ResourceDownloadDialog : public QDialog, public BasePageProvider { bool selectPage(QString pageId); ResourcePage* selectedPage(); - void addResource(ModPlatform::IndexedPack::Ptr, ModPlatform::IndexedVersion&, QString downloadReason = "standalone"); + void addResource(ModPlatform::IndexedPack::Ptr, ModPlatform::IndexedVersion&); void removeResource(const QString&); - QList getTasks(); + const QList getTasks(); ResourceFolderModel* getBaseModel() const { return m_base_model; } void setResourceMetadata(const std::shared_ptr& meta); @@ -94,16 +94,13 @@ class ResourceDownloadDialog : public QDialog, public BasePageProvider { QDialogButtonBox m_buttons; QVBoxLayout m_vertical_layout; - - protected: - bool m_suppressInitialSearch = false; }; class ModDownloadDialog final : public ResourceDownloadDialog { Q_OBJECT public: - explicit ModDownloadDialog(QWidget* parent, ModFolderModel* mods, BaseInstance* instance, bool suppressInitialSearch = false); + explicit ModDownloadDialog(QWidget* parent, ModFolderModel* mods, BaseInstance* instance); ~ModDownloadDialog() override = default; //: String that gets appended to the mod download dialog title ("Download " + resourcesString()) @@ -121,10 +118,7 @@ class ResourcePackDownloadDialog final : public ResourceDownloadDialog { Q_OBJECT public: - explicit ResourcePackDownloadDialog(QWidget* parent, - ResourcePackFolderModel* resourcePacks, - BaseInstance* instance, - bool suppressInitialSearch = false); + explicit ResourcePackDownloadDialog(QWidget* parent, ResourcePackFolderModel* resource_packs, BaseInstance* instance); ~ResourcePackDownloadDialog() override = default; //: String that gets appended to the resource pack download dialog title ("Download " + resourcesString()) @@ -141,10 +135,7 @@ class TexturePackDownloadDialog final : public ResourceDownloadDialog { Q_OBJECT public: - explicit TexturePackDownloadDialog(QWidget* parent, - TexturePackFolderModel* resourcePacks, - BaseInstance* instance, - bool suppressInitialSearch = false); + explicit TexturePackDownloadDialog(QWidget* parent, TexturePackFolderModel* resource_packs, BaseInstance* instance); ~TexturePackDownloadDialog() override = default; //: String that gets appended to the texture pack download dialog title ("Download " + resourcesString()) @@ -161,10 +152,7 @@ class ShaderPackDownloadDialog final : public ResourceDownloadDialog { Q_OBJECT public: - explicit ShaderPackDownloadDialog(QWidget* parent, - ShaderPackFolderModel* shaders, - BaseInstance* instance, - bool suppressInitialSearch = false); + explicit ShaderPackDownloadDialog(QWidget* parent, ShaderPackFolderModel* shader_packs, BaseInstance* instance); ~ShaderPackDownloadDialog() override = default; //: String that gets appended to the shader pack download dialog title ("Download " + resourcesString()) @@ -181,10 +169,7 @@ class DataPackDownloadDialog final : public ResourceDownloadDialog { Q_OBJECT public: - explicit DataPackDownloadDialog(QWidget* parent, - DataPackFolderModel* dataPacks, - BaseInstance* instance, - bool suppressInitialSearch = false); + explicit DataPackDownloadDialog(QWidget* parent, DataPackFolderModel* data_packs, BaseInstance* instance); ~DataPackDownloadDialog() override = default; //: String that gets appended to the data pack download dialog title ("Download " + resourcesString()) diff --git a/launcher/ui/dialogs/ResourceUpdateDialog.cpp b/launcher/ui/dialogs/ResourceUpdateDialog.cpp index e9776c660..99b01c35d 100644 --- a/launcher/ui/dialogs/ResourceUpdateDialog.cpp +++ b/launcher/ui/dialogs/ResourceUpdateDialog.cpp @@ -29,12 +29,10 @@ #include -namespace { -std::vector mcVersions(BaseInstance* inst) +static std::vector mcVersions(BaseInstance* inst) { return { static_cast(inst)->getPackProfile()->getComponent("net.minecraft")->getVersion() }; } -} // namespace ResourceUpdateDialog::ResourceUpdateDialog(QWidget* parent, BaseInstance* instance, @@ -60,8 +58,8 @@ ResourceUpdateDialog::ResourceUpdateDialog(QWidget* parent, void ResourceUpdateDialog::checkCandidates() { // Ensure mods have valid metadata - auto wentWell = ensureMetadata(); - if (!wentWell) { + auto went_well = ensureMetadata(); + if (!went_well) { m_aborted = true; return; } @@ -75,12 +73,12 @@ void ResourceUpdateDialog::checkCandidates() text += tr("Mod name: %1
File name: %2
Reason: %3

").arg(mod->name(), mod->fileinfo().fileName(), reason); } - ScrollMessageBox messageDialog(m_parent, tr("Metadata generation failed"), - tr("Could not generate metadata for the following resources:
" - "Do you wish to proceed without those resources?"), - text); - messageDialog.setModal(true); - if (messageDialog.exec() == QDialog::Rejected) { + ScrollMessageBox message_dialog(m_parent, tr("Metadata generation failed"), + tr("Could not generate metadata for the following resources:
" + "Do you wish to proceed without those resources?"), + text); + message_dialog.setModal(true); + if (message_dialog.exec() == QDialog::Rejected) { m_aborted = true; QMetaObject::invokeMethod(this, "reject", Qt::QueuedConnection); return; @@ -89,41 +87,40 @@ void ResourceUpdateDialog::checkCandidates() auto versions = mcVersions(m_instance); - SequentialTask checkTask(tr("Checking for updates")); + SequentialTask check_task(tr("Checking for updates")); if (!m_modrinthToUpdate.empty()) { m_modrinthCheckTask.reset(new ModrinthCheckUpdate(m_modrinthToUpdate, versions, m_loadersList, m_resourceModel)); connect(m_modrinthCheckTask.get(), &CheckUpdateTask::checkFailed, this, - [this](Resource* resource, const QString& reason, const QUrl& recoverUrl) { - m_failedCheckUpdate.append({ resource, reason, recoverUrl }); + [this](Resource* resource, QString reason, QUrl recover_url) { + m_failedCheckUpdate.append({ resource, reason, recover_url }); }); - checkTask.addTask(m_modrinthCheckTask); + check_task.addTask(m_modrinthCheckTask); } if (!m_flameToUpdate.empty()) { m_flameCheckTask.reset(new FlameCheckUpdate(m_flameToUpdate, versions, m_loadersList, m_resourceModel)); - connect(m_flameCheckTask.get(), &CheckUpdateTask::checkFailed, this, - [this](Resource* resource, const QString& reason, const QUrl& recoverUrl) { - m_failedCheckUpdate.append({ resource, reason, recoverUrl }); - }); - checkTask.addTask(m_flameCheckTask); + connect(m_flameCheckTask.get(), &CheckUpdateTask::checkFailed, this, [this](Resource* resource, QString reason, QUrl recover_url) { + m_failedCheckUpdate.append({ resource, reason, recover_url }); + }); + check_task.addTask(m_flameCheckTask); } - connect(&checkTask, &Task::failed, this, - [this](const QString& reason) { CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->exec(); }); + connect(&check_task, &Task::failed, this, + [this](QString reason) { CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->exec(); }); - connect(&checkTask, &Task::succeeded, this, [this, &checkTask]() { - QStringList warnings = checkTask.warnings(); + connect(&check_task, &Task::succeeded, this, [this, &check_task]() { + QStringList warnings = check_task.warnings(); if (warnings.count()) { CustomMessageBox::selectable(this, tr("Warnings"), warnings.join('\n'), QMessageBox::Warning)->exec(); } }); // Check for updates - ProgressDialog progressDialog(m_parent); - progressDialog.setSkipButton(true, tr("Abort")); - progressDialog.setWindowTitle(tr("Checking for updates...")); - auto ret = progressDialog.execWithTask(&checkTask); + ProgressDialog progress_dialog(m_parent); + progress_dialog.setSkipButton(true, tr("Abort")); + progress_dialog.setWindowTitle(tr("Checking for updates...")); + auto ret = progress_dialog.execWithTask(&check_task); // If the dialog was skipped / some download error happened if (ret == QDialog::DialogCode::Rejected) { @@ -136,8 +133,8 @@ void ResourceUpdateDialog::checkCandidates() // Add found updates for Modrinth if (m_modrinthCheckTask) { - auto modrinthUpdates = m_modrinthCheckTask->getUpdates(); - for (auto& updatable : modrinthUpdates) { + auto modrinth_updates = m_modrinthCheckTask->getUpdates(); + for (auto& updatable : modrinth_updates) { qDebug() << QString("Mod %1 has an update available!").arg(updatable.name); appendResource(updatable); @@ -148,8 +145,8 @@ void ResourceUpdateDialog::checkCandidates() // Add found updated for Flame if (m_flameCheckTask) { - auto flameUpdates = m_flameCheckTask->getUpdates(); - for (auto& updatable : flameUpdates) { + auto flame_updates = m_flameCheckTask->getUpdates(); + for (auto& updatable : flame_updates) { qDebug() << QString("Mod %1 has an update available!").arg(updatable.name); appendResource(updatable); @@ -164,35 +161,33 @@ void ResourceUpdateDialog::checkCandidates() for (const auto& failed : m_failedCheckUpdate) { const auto& mod = std::get<0>(failed); const auto& reason = std::get<1>(failed); - const auto& recoverUrl = std::get<2>(failed); + const auto& recover_url = std::get<2>(failed); qDebug() << mod->name() << "failed to check for updates!"; text += tr("Mod name: %1").arg(mod->name()) + "
"; - if (!reason.isEmpty()) { + if (!reason.isEmpty()) text += tr("Reason: %1").arg(reason) + "
"; - } - if (!recoverUrl.isEmpty()) { + if (!recover_url.isEmpty()) //: %1 is the link to download it manually text += tr("Possible solution: Getting the latest version manually:
%1
") - .arg(QString("%1").arg(recoverUrl.toString())); - } + .arg(QString("%1").arg(recover_url.toString())); text += "
"; } - ScrollMessageBox messageDialog(m_parent, tr("Failed to check for updates"), - tr("Could not check or get the following resources for updates:
" - "Do you wish to proceed without those resources?"), - text, "Disable unavailable mods"); - messageDialog.setModal(true); - if (messageDialog.exec() == QDialog::Rejected) { + ScrollMessageBox message_dialog(m_parent, tr("Failed to check for updates"), + tr("Could not check or get the following resources for updates:
" + "Do you wish to proceed without those resources?"), + text, "Disable unavailable mods"); + message_dialog.setModal(true); + if (message_dialog.exec() == QDialog::Rejected) { m_aborted = true; QMetaObject::invokeMethod(this, "reject", Qt::QueuedConnection); return; } // Disable unavailable mods - if (messageDialog.isOptionChecked()) { + if (message_dialog.isOptionChecked()) { for (const auto& failed : m_failedCheckUpdate) { const auto& mod = std::get<0>(failed); mod->enable(EnableAction::DISABLE); @@ -201,10 +196,10 @@ void ResourceUpdateDialog::checkCandidates() } if (m_includeDeps && !APPLICATION->settings()->get("ModDependenciesDisabled").toBool()) { // dependencies - auto* modModel = dynamic_cast(m_resourceModel); + auto* mod_model = dynamic_cast(m_resourceModel); - if (modModel != nullptr) { - auto depTask = makeShared(m_instance, modModel, selectedVers); + if (mod_model != nullptr) { + auto depTask = makeShared(m_instance, mod_model, selectedVers); connect(depTask.get(), &Task::failed, this, [this](const QString& reason) { CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->exec(); @@ -220,10 +215,10 @@ void ResourceUpdateDialog::checkCandidates() } }); - ProgressDialog progressDialogDeps(m_parent); - progressDialogDeps.setSkipButton(true, tr("Abort")); - progressDialogDeps.setWindowTitle(tr("Checking for dependencies...")); - auto dret = progressDialogDeps.execWithTask(depTask.get()); + ProgressDialog progress_dialog_deps(m_parent); + progress_dialog_deps.setSkipButton(true, tr("Abort")); + progress_dialog_deps.setWindowTitle(tr("Checking for dependencies...")); + auto dret = progress_dialog_deps.execWithTask(depTask.get()); // If the dialog was skipped / some download error happened if (dret == QDialog::DialogCode::Rejected) { @@ -231,20 +226,19 @@ void ResourceUpdateDialog::checkCandidates() QMetaObject::invokeMethod(this, "reject", Qt::QueuedConnection); return; } - static FlameAPI s_api; + static FlameAPI api; auto dependencyExtraInfo = depTask->getExtraInfo(); for (const auto& dep : depTask->getDependecies()) { auto changelog = dep->version.changelog; - if (dep->pack->provider == ModPlatform::ResourceProvider::FLAME) { - changelog = s_api.getModFileChangelog(dep->version.addonId.toInt(), dep->version.fileId.toInt()); - } - auto downloadTask = makeShared(dep->pack, dep->version, m_resourceModel, true, "dependency"); + if (dep->pack->provider == ModPlatform::ResourceProvider::FLAME) + changelog = api.getModFileChangelog(dep->version.addonId.toInt(), dep->version.fileId.toInt()); + auto download_task = makeShared(dep->pack, dep->version, m_resourceModel); auto extraInfo = dependencyExtraInfo.value(dep->version.addonId.toString()); CheckUpdateTask::Update updatable = { dep->pack->name, dep->version.hash, tr("Not installed"), dep->version.version, dep->version.version_type, - changelog, dep->pack->provider, downloadTask, !extraInfo.maybe_installed + changelog, dep->pack->provider, download_task, !extraInfo.maybe_installed }; appendResource(updatable, extraInfo.required_by); @@ -270,58 +264,56 @@ void ResourceUpdateDialog::checkCandidates() } } - if (m_aborted || m_noUpdates) { + if (m_aborted || m_noUpdates) QMetaObject::invokeMethod(this, "reject", Qt::QueuedConnection); - } } // Part 1: Ensure we have a valid metadata auto ResourceUpdateDialog::ensureMetadata() -> bool { - auto indexDir2 = indexDir(); + auto index_dir = indexDir(); SequentialTask seq(tr("Looking for metadata")); // A better use of data structures here could remove the need for this QHash - QHash shouldTryOthers; - QList modrinthTmp; - QList flameTmp; + QHash should_try_others; + QList modrinth_tmp; + QList flame_tmp; - bool confirmRest = false; - bool tryOthersRest = false; - bool skipRest = false; - ModPlatform::ResourceProvider providerRest = ModPlatform::ResourceProvider::MODRINTH; + bool confirm_rest = false; + bool try_others_rest = false; + bool skip_rest = false; + ModPlatform::ResourceProvider provider_rest = ModPlatform::ResourceProvider::MODRINTH; // adds resource to list based on provider - auto addToTmp = [&modrinthTmp, &flameTmp](Resource* resource, ModPlatform::ResourceProvider p) { + auto addToTmp = [&modrinth_tmp, &flame_tmp](Resource* resource, ModPlatform::ResourceProvider p) { switch (p) { case ModPlatform::ResourceProvider::MODRINTH: - modrinthTmp.push_back(resource); + modrinth_tmp.push_back(resource); break; case ModPlatform::ResourceProvider::FLAME: - flameTmp.push_back(resource); + flame_tmp.push_back(resource); break; } }; // ask the user on what provider to seach for the mod first - for (auto* candidate : m_candidates) { - if (candidate->status() != ResourceStatus::NoMetadata) { + for (auto candidate : m_candidates) { + if (candidate->status() != ResourceStatus::NO_METADATA) { onMetadataEnsured(candidate); continue; } - if (skipRest) { + if (skip_rest) continue; - } if (candidate->type() == ResourceType::FOLDER) { continue; } - if (confirmRest) { - addToTmp(candidate, providerRest); - shouldTryOthers.insert(candidate->internalId(), tryOthersRest); + if (confirm_rest) { + addToTmp(candidate, provider_rest); + should_try_others.insert(candidate->internal_id(), try_others_rest); continue; } @@ -334,73 +326,68 @@ auto ResourceUpdateDialog::ensureMetadata() -> bool auto response = chooser.getResponse(); - if (response.skip_all) { - skipRest = true; - } + if (response.skip_all) + skip_rest = true; if (response.confirm_all) { - confirmRest = true; - providerRest = response.chosen; - tryOthersRest = response.try_others; + confirm_rest = true; + provider_rest = response.chosen; + try_others_rest = response.try_others; } - shouldTryOthers.insert(candidate->internalId(), response.try_others); + should_try_others.insert(candidate->internal_id(), response.try_others); - if (confirmed) { + if (confirmed) addToTmp(candidate, response.chosen); - } } // prepare task for the modrinth mods - if (!modrinthTmp.empty()) { - auto modrinthTask = makeShared(modrinthTmp, indexDir2, ModPlatform::ResourceProvider::MODRINTH); - connect(modrinthTask.get(), &EnsureMetadataTask::metadataReady, [this](Resource* candidate) { onMetadataEnsured(candidate); }); - connect(modrinthTask.get(), &EnsureMetadataTask::metadataFailed, [this, &shouldTryOthers](Resource* candidate) { - onMetadataFailed(candidate, shouldTryOthers.find(candidate->internalId()).value(), ModPlatform::ResourceProvider::MODRINTH); + if (!modrinth_tmp.empty()) { + auto modrinth_task = makeShared(modrinth_tmp, index_dir, ModPlatform::ResourceProvider::MODRINTH); + connect(modrinth_task.get(), &EnsureMetadataTask::metadataReady, [this](Resource* candidate) { onMetadataEnsured(candidate); }); + connect(modrinth_task.get(), &EnsureMetadataTask::metadataFailed, [this, &should_try_others](Resource* candidate) { + onMetadataFailed(candidate, should_try_others.find(candidate->internal_id()).value(), ModPlatform::ResourceProvider::MODRINTH); }); - connect(modrinthTask.get(), &EnsureMetadataTask::failed, - [this](const QString& reason) { CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->exec(); }); + connect(modrinth_task.get(), &EnsureMetadataTask::failed, + [this](QString reason) { CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->exec(); }); - if (modrinthTask->getHashingTask()) { - seq.addTask(modrinthTask->getHashingTask()); - } + if (modrinth_task->getHashingTask()) + seq.addTask(modrinth_task->getHashingTask()); - seq.addTask(modrinthTask); + seq.addTask(modrinth_task); } // prepare task for the flame mods - if (!flameTmp.empty()) { - auto flameTask = makeShared(flameTmp, indexDir2, ModPlatform::ResourceProvider::FLAME); - connect(flameTask.get(), &EnsureMetadataTask::metadataReady, [this](Resource* candidate) { onMetadataEnsured(candidate); }); - connect(flameTask.get(), &EnsureMetadataTask::metadataFailed, [this, &shouldTryOthers](Resource* candidate) { - onMetadataFailed(candidate, shouldTryOthers.find(candidate->internalId()).value(), ModPlatform::ResourceProvider::FLAME); + if (!flame_tmp.empty()) { + auto flame_task = makeShared(flame_tmp, index_dir, ModPlatform::ResourceProvider::FLAME); + connect(flame_task.get(), &EnsureMetadataTask::metadataReady, [this](Resource* candidate) { onMetadataEnsured(candidate); }); + connect(flame_task.get(), &EnsureMetadataTask::metadataFailed, [this, &should_try_others](Resource* candidate) { + onMetadataFailed(candidate, should_try_others.find(candidate->internal_id()).value(), ModPlatform::ResourceProvider::FLAME); }); - connect(flameTask.get(), &EnsureMetadataTask::failed, - [this](const QString& reason) { CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->exec(); }); + connect(flame_task.get(), &EnsureMetadataTask::failed, + [this](QString reason) { CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->exec(); }); - if (flameTask->getHashingTask()) { - seq.addTask(flameTask->getHashingTask()); - } + if (flame_task->getHashingTask()) + seq.addTask(flame_task->getHashingTask()); - seq.addTask(flameTask); + seq.addTask(flame_task); } seq.addTask(m_secondTryMetadata); // execute all the tasks - ProgressDialog checkingDialog(m_parent); - checkingDialog.setSkipButton(true, tr("Abort")); - checkingDialog.setWindowTitle(tr("Generating metadata...")); - auto retMetadata = checkingDialog.execWithTask(&seq); + ProgressDialog checking_dialog(m_parent); + checking_dialog.setSkipButton(true, tr("Abort")); + checking_dialog.setWindowTitle(tr("Generating metadata...")); + auto ret_metadata = checking_dialog.execWithTask(&seq); - return (retMetadata != QDialog::DialogCode::Rejected); + return (ret_metadata != QDialog::DialogCode::Rejected); } void ResourceUpdateDialog::onMetadataEnsured(Resource* resource) { // When the mod is a folder, for instance - if (!resource->metadata()) { + if (!resource->metadata()) return; - } switch (resource->metadata()->provider) { case ModPlatform::ResourceProvider::MODRINTH: @@ -424,12 +411,12 @@ ModPlatform::ResourceProvider next(ModPlatform::ResourceProvider p) return ModPlatform::ResourceProvider::FLAME; } -void ResourceUpdateDialog::onMetadataFailed(Resource* resource, bool tryOthers, ModPlatform::ResourceProvider firstChoice) +void ResourceUpdateDialog::onMetadataFailed(Resource* resource, bool try_others, ModPlatform::ResourceProvider first_choice) { - if (tryOthers) { - auto indexDir2 = indexDir(); + if (try_others) { + auto index_dir = indexDir(); - auto task = makeShared(resource, indexDir2, next(firstChoice)); + auto task = makeShared(resource, index_dir, next(first_choice)); connect(task.get(), &EnsureMetadataTask::metadataReady, [this](Resource* candidate) { onMetadataEnsured(candidate); }); connect(task.get(), &EnsureMetadataTask::metadataFailed, [this](Resource* candidate) { onMetadataFailed(candidate, false); }); connect(task.get(), &EnsureMetadataTask::failed, @@ -449,57 +436,57 @@ void ResourceUpdateDialog::onMetadataFailed(Resource* resource, bool tryOthers, } } -void ResourceUpdateDialog::appendResource(const CheckUpdateTask::Update& info, QStringList requiredBy) +void ResourceUpdateDialog::appendResource(CheckUpdateTask::Update const& info, QStringList requiredBy) { - auto* itemTop = new QTreeWidgetItem(ui->modTreeWidget); - itemTop->setCheckState(0, info.enabled ? Qt::CheckState::Checked : Qt::CheckState::Unchecked); + auto item_top = new QTreeWidgetItem(ui->modTreeWidget); + item_top->setCheckState(0, info.enabled ? Qt::CheckState::Checked : Qt::CheckState::Unchecked); if (!info.enabled) { - itemTop->setToolTip(0, tr("Mod was disabled as it may be already installed.")); + item_top->setToolTip(0, tr("Mod was disabled as it may be already installed.")); } - itemTop->setText(0, info.name); - itemTop->setExpanded(true); + item_top->setText(0, info.name); + item_top->setExpanded(true); - auto* providerItem = new QTreeWidgetItem(itemTop); - QString providerName = ModPlatform::ProviderCapabilities::readableName(info.provider); - providerItem->setText(0, tr("Provider: %1").arg(providerName)); - providerItem->setData(0, Qt::UserRole, providerName); + auto provider_item = new QTreeWidgetItem(item_top); + QString provider_name = ModPlatform::ProviderCapabilities::readableName(info.provider); + provider_item->setText(0, tr("Provider: %1").arg(provider_name)); + provider_item->setData(0, Qt::UserRole, provider_name); - auto* oldVersionItem = new QTreeWidgetItem(itemTop); - oldVersionItem->setText(0, tr("Old version: %1").arg(info.oldVersion)); - oldVersionItem->setData(0, Qt::UserRole, info.oldVersion); + auto old_version_item = new QTreeWidgetItem(item_top); + old_version_item->setText(0, tr("Old version: %1").arg(info.old_version)); + old_version_item->setData(0, Qt::UserRole, info.old_version); - auto* newVersionItem = new QTreeWidgetItem(itemTop); - newVersionItem->setText(0, tr("New version: %1").arg(info.newVersion)); - newVersionItem->setData(0, Qt::UserRole, info.newVersion); + auto new_version_item = new QTreeWidgetItem(item_top); + new_version_item->setText(0, tr("New version: %1").arg(info.new_version)); + new_version_item->setData(0, Qt::UserRole, info.new_version); - if (info.newVersionType.has_value()) { - auto* newVersionTypeItem = new QTreeWidgetItem(itemTop); - newVersionTypeItem->setText(0, tr("New Version Type: %1").arg(info.newVersionType.value().toString())); - newVersionTypeItem->setData(0, Qt::UserRole, info.newVersionType.value().toString()); + if (info.new_version_type.has_value()) { + auto new_version_type_item = new QTreeWidgetItem(item_top); + new_version_type_item->setText(0, tr("New Version Type: %1").arg(info.new_version_type.value().toString())); + new_version_type_item->setData(0, Qt::UserRole, info.new_version_type.value().toString()); } if (!requiredBy.isEmpty()) { - auto* requiredByItem = new QTreeWidgetItem(itemTop); + auto requiredByItem = new QTreeWidgetItem(item_top); if (requiredBy.length() == 1) { requiredByItem->setText(0, tr("Required by: %1").arg(requiredBy.back())); requiredByItem->setData(0, Qt::UserRole, requiredBy.back()); } else { requiredByItem->setText(0, tr("Required by:")); - for (const auto& req : requiredBy) { - auto* reqItem = new QTreeWidgetItem(requiredByItem); + for (auto req : requiredBy) { + auto reqItem = new QTreeWidgetItem(requiredByItem); reqItem->setText(0, req); } } ui->toggleDepsButton->show(); - m_deps << itemTop; + m_deps << item_top; } - auto* changelogItem = new QTreeWidgetItem(itemTop); - changelogItem->setText(0, tr("Changelog of the latest version")); + auto changelog_item = new QTreeWidgetItem(item_top); + changelog_item->setText(0, tr("Changelog of the latest version")); - auto* changelog = new QTreeWidgetItem(changelogItem); - auto* changelogArea = new QTextBrowser(); + auto changelog = new QTreeWidgetItem(changelog_item); + auto changelog_area = new QTextBrowser(); QString text = info.changelog; changelog->setData(0, Qt::UserRole, text); @@ -507,14 +494,14 @@ void ResourceUpdateDialog::appendResource(const CheckUpdateTask::Update& info, Q text = markdownToHTML(info.changelog.toUtf8()); } - changelogArea->setHtml(StringUtils::htmlListPatch(text)); - changelogArea->setOpenExternalLinks(true); - changelogArea->setLineWrapMode(QTextBrowser::LineWrapMode::WidgetWidth); - changelogArea->setVerticalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAsNeeded); + changelog_area->setHtml(StringUtils::htmlListPatch(text)); + changelog_area->setOpenExternalLinks(true); + changelog_area->setLineWrapMode(QTextBrowser::LineWrapMode::WidgetWidth); + changelog_area->setVerticalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAsNeeded); - ui->modTreeWidget->setItemWidget(changelog, 0, changelogArea); + ui->modTreeWidget->setItemWidget(changelog, 0, changelog_area); - ui->modTreeWidget->addTopLevelItem(itemTop); + ui->modTreeWidget->addTopLevelItem(item_top); } auto ResourceUpdateDialog::getTasks() -> const QList diff --git a/launcher/ui/dialogs/ResourceUpdateDialog.h b/launcher/ui/dialogs/ResourceUpdateDialog.h index 9de1ee246..ea81aeb7a 100644 --- a/launcher/ui/dialogs/ResourceUpdateDialog.h +++ b/launcher/ui/dialogs/ResourceUpdateDialog.h @@ -39,7 +39,7 @@ class ResourceUpdateDialog final : public ReviewMessageBox { private slots: void onMetadataEnsured(Resource* resource); void onMetadataFailed(Resource* resource, - bool tryOthers = false, + bool try_others = false, ModPlatform::ResourceProvider firstChoice = ModPlatform::ResourceProvider::MODRINTH); private: diff --git a/launcher/ui/dialogs/VersionSelectDialog.cpp b/launcher/ui/dialogs/VersionSelectDialog.cpp index db9b08096..30377288b 100644 --- a/launcher/ui/dialogs/VersionSelectDialog.cpp +++ b/launcher/ui/dialogs/VersionSelectDialog.cpp @@ -69,7 +69,7 @@ VersionSelectDialog::VersionSelectDialog(BaseVersionList* vlist, QString title, m_buttonBox->setOrientation(Qt::Horizontal); m_buttonBox->setStandardButtons(QDialogButtonBox::Cancel | QDialogButtonBox::Ok); - m_buttonBox->button(QDialogButtonBox::Ok)->setText(tr("OK")); + m_buttonBox->button(QDialogButtonBox::Ok)->setText(tr("Ok")); m_buttonBox->button(QDialogButtonBox::Cancel)->setText(tr("Cancel")); m_horizontalLayout->addWidget(m_buttonBox); @@ -144,7 +144,7 @@ BaseVersion::Ptr VersionSelectDialog::selectedVersion() const void VersionSelectDialog::on_refreshButton_clicked() { - m_versionWidget->loadList(true); + m_versionWidget->loadList(); } void VersionSelectDialog::setExactFilter(BaseVersionList::ModelRoles role, QString filter) diff --git a/launcher/ui/instanceview/InstanceProxyModel.cpp b/launcher/ui/instanceview/InstanceProxyModel.cpp index f28149a56..ab6bef696 100644 --- a/launcher/ui/instanceview/InstanceProxyModel.cpp +++ b/launcher/ui/instanceview/InstanceProxyModel.cpp @@ -62,11 +62,6 @@ bool InstanceProxyModel::subSortLessThan(const QModelIndex& left, const QModelIn QString sortMode = APPLICATION->settings()->get("InstSortMode").toString(); if (sortMode == "LastLaunch") { return pdataLeft->lastLaunch() > pdataRight->lastLaunch(); - } else if (sortMode == "Playtime") { - if (pdataLeft->totalTimePlayed() == pdataRight->totalTimePlayed()) { - return m_naturalSort.compare(pdataLeft->name(), pdataRight->name()) < 0; - } - return pdataLeft->totalTimePlayed() > pdataRight->totalTimePlayed(); } else { return m_naturalSort.compare(pdataLeft->name(), pdataRight->name()) < 0; } diff --git a/launcher/ui/instanceview/InstanceView.cpp b/launcher/ui/instanceview/InstanceView.cpp index 9a24b7990..aff61cb3b 100644 --- a/launcher/ui/instanceview/InstanceView.cpp +++ b/launcher/ui/instanceview/InstanceView.cpp @@ -511,7 +511,8 @@ void InstanceView::paintEvent([[maybe_unused]] QPaintEvent* event) int wpWidth = viewport()->width(); option.rect.setWidth(wpWidth); - for (auto* category : m_groups) { + for (int i = 0; i < m_groups.size(); ++i) { + VisualGroup* category = m_groups.at(i); int y = category->verticalPosition(); y -= verticalOffset(); QRect backup = option.rect; @@ -521,6 +522,7 @@ void InstanceView::paintEvent([[maybe_unused]] QPaintEvent* event) option.rect.setLeft(m_leftMargin); option.rect.setRight(wpWidth - m_rightMargin); category->drawHeader(&painter, option); + y += category->totalHeight() + m_categoryMargin; option.rect = backup; } diff --git a/launcher/ui/java/InstallJavaDialog.cpp b/launcher/ui/java/InstallJavaDialog.cpp index fd8e43398..81ffcfa83 100644 --- a/launcher/ui/java/InstallJavaDialog.cpp +++ b/launcher/ui/java/InstallJavaDialog.cpp @@ -121,8 +121,8 @@ class InstallJavaPage : public QWidget, public BasePage { void selectSearch() { javaVersionSelect->selectSearch(); } void loadList() { - majorVersionSelect->loadList(true); - javaVersionSelect->loadList(true); + majorVersionSelect->loadList(); + javaVersionSelect->loadList(); } public slots: diff --git a/launcher/ui/java/VersionList.cpp b/launcher/ui/java/VersionList.cpp index 7a4e84f33..f958f064f 100644 --- a/launcher/ui/java/VersionList.cpp +++ b/launcher/ui/java/VersionList.cpp @@ -33,9 +33,9 @@ VersionList::VersionList(Meta::Version::Ptr version, QObject* parent) : BaseVers sortVersions(); } -Task::Ptr VersionList::getLoadTask(bool forceReload) +Task::Ptr VersionList::getLoadTask() { - auto task = m_version->loadTask(Net::Mode::Online, forceReload); + auto task = m_version->loadTask(Net::Mode::Online); connect(task.get(), &Task::finished, this, &VersionList::sortVersions); return task; } diff --git a/launcher/ui/java/VersionList.h b/launcher/ui/java/VersionList.h index cf8a7448d..d334ed564 100644 --- a/launcher/ui/java/VersionList.h +++ b/launcher/ui/java/VersionList.h @@ -30,7 +30,7 @@ class VersionList : public BaseVersionList { public: explicit VersionList(Meta::Version::Ptr m_version, QObject* parent = 0); - Task::Ptr getLoadTask(bool forceReload = false) override; + Task::Ptr getLoadTask() override; bool isLoaded() override; const BaseVersion::Ptr at(int i) const override; int count() const override; diff --git a/launcher/ui/pages/global/APIPage.cpp b/launcher/ui/pages/global/APIPage.cpp index 4ed05f98e..c399df469 100644 --- a/launcher/ui/pages/global/APIPage.cpp +++ b/launcher/ui/pages/global/APIPage.cpp @@ -143,7 +143,6 @@ void APIPage::loadSettings() ui->msaClientID->setText(msaClientID); QString metaURL = s->get("MetaURLOverride").toString(); ui->metaURL->setText(metaURL); - ui->metaRefreshOnLaunchCB->setCheckState(s->get("MetaRefreshOnLaunch").toBool() ? Qt::Checked : Qt::Unchecked); QString resourceURL = s->get("ResourceURLOverride").toString(); ui->resourceURL->setText(resourceURL); QString fmlLibsURL = s->get("LegacyFMLLibsURLOverride").toString(); @@ -195,7 +194,6 @@ void APIPage::applySettings() s->set("FallbackMRBlockedMods", ui->FallbackMRBlockedMods->checkState()); s->set("MetaURLOverride", metaURL.toString()); - s->set("MetaRefreshOnLaunch", ui->metaRefreshOnLaunchCB->checkState() == Qt::Checked); s->set("ResourceURLOverride", resourceURL.toString()); s->set("LegacyFMLLibsURLOverride", fmlLibsURL.toString()); QString flameKey = ui->flameKey->text(); diff --git a/launcher/ui/pages/global/APIPage.ui b/launcher/ui/pages/global/APIPage.ui index 25d78a04d..7d759d256 100644 --- a/launcher/ui/pages/global/APIPage.ui +++ b/launcher/ui/pages/global/APIPage.ui @@ -32,9 +32,9 @@ 0 - 0 - 825 - 1236 + -262 + 820 + 908 @@ -126,13 +126,6 @@
- - - - Refresh on launch - - -
diff --git a/launcher/ui/pages/global/LauncherPage.cpp b/launcher/ui/pages/global/LauncherPage.cpp index 1e1fed8f8..d6d15a2c4 100644 --- a/launcher/ui/pages/global/LauncherPage.cpp +++ b/launcher/ui/pages/global/LauncherPage.cpp @@ -62,9 +62,7 @@ enum InstSortMode { // Sort alphabetically by name. Sort_Name, // Sort by which instance was launched most recently. - Sort_LastLaunch, - // Sort by which instance has the most playtime. - Sort_Playtime, + Sort_LastLaunch }; LauncherPage::LauncherPage(QWidget* parent) : QWidget(parent), ui(new Ui::LauncherPage) @@ -73,7 +71,6 @@ LauncherPage::LauncherPage(QWidget* parent) : QWidget(parent), ui(new Ui::Launch ui->sortingModeGroup->setId(ui->sortByNameBtn, Sort_Name); ui->sortingModeGroup->setId(ui->sortLastLaunchedBtn, Sort_LastLaunch); - ui->sortingModeGroup->setId(ui->sortByPlaytimeBtn, Sort_Playtime); loadSettings(); @@ -93,12 +90,12 @@ bool LauncherPage::apply() void LauncherPage::on_instDirBrowseBtn_clicked() { - QString rawDir = QFileDialog::getExistingDirectory(this, tr("Instance Folder"), ui->instDirTextBox->text()); + QString raw_dir = QFileDialog::getExistingDirectory(this, tr("Instance Folder"), ui->instDirTextBox->text()); // do not allow current dir - it's dirty. Do not allow dirs that don't exist - if (!rawDir.isEmpty() && QDir(rawDir).exists()) { - QString cookedDir = FS::NormalizePath(rawDir); - if (FS::checkProblemticPathJava(QDir(cookedDir))) { + if (!raw_dir.isEmpty() && QDir(raw_dir).exists()) { + QString cooked_dir = FS::NormalizePath(raw_dir); + if (FS::checkProblemticPathJava(QDir(cooked_dir))) { QMessageBox warning; warning.setText( tr("You're trying to specify an instance folder which\'s path " @@ -111,9 +108,9 @@ void LauncherPage::on_instDirBrowseBtn_clicked() warning.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel); int result = warning.exec(); if (result == QMessageBox::Ok) { - ui->instDirTextBox->setText(cookedDir); + ui->instDirTextBox->setText(cooked_dir); } - } else if (DesktopServices::isFlatpak() && rawDir.startsWith("/run/user")) { + } else if (DesktopServices::isFlatpak() && raw_dir.startsWith("/run/user")) { QMessageBox warning; warning.setText(tr("You're trying to specify an instance folder " "which was granted temporarily via Flatpak.\n" @@ -126,64 +123,64 @@ void LauncherPage::on_instDirBrowseBtn_clicked() warning.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel); int result = warning.exec(); if (result == QMessageBox::Ok) { - ui->instDirTextBox->setText(cookedDir); + ui->instDirTextBox->setText(cooked_dir); } } else { - ui->instDirTextBox->setText(cookedDir); + ui->instDirTextBox->setText(cooked_dir); } } } void LauncherPage::on_iconsDirBrowseBtn_clicked() { - QString rawDir = QFileDialog::getExistingDirectory(this, tr("Icons Folder"), ui->iconsDirTextBox->text()); + QString raw_dir = QFileDialog::getExistingDirectory(this, tr("Icons Folder"), ui->iconsDirTextBox->text()); // do not allow current dir - it's dirty. Do not allow dirs that don't exist - if (!rawDir.isEmpty() && QDir(rawDir).exists()) { - QString cookedDir = FS::NormalizePath(rawDir); - ui->iconsDirTextBox->setText(cookedDir); + if (!raw_dir.isEmpty() && QDir(raw_dir).exists()) { + QString cooked_dir = FS::NormalizePath(raw_dir); + ui->iconsDirTextBox->setText(cooked_dir); } } void LauncherPage::on_modsDirBrowseBtn_clicked() { - QString rawDir = QFileDialog::getExistingDirectory(this, tr("Mods Folder"), ui->modsDirTextBox->text()); + QString raw_dir = QFileDialog::getExistingDirectory(this, tr("Mods Folder"), ui->modsDirTextBox->text()); // do not allow current dir - it's dirty. Do not allow dirs that don't exist - if (!rawDir.isEmpty() && QDir(rawDir).exists()) { - QString cookedDir = FS::NormalizePath(rawDir); - ui->modsDirTextBox->setText(cookedDir); + if (!raw_dir.isEmpty() && QDir(raw_dir).exists()) { + QString cooked_dir = FS::NormalizePath(raw_dir); + ui->modsDirTextBox->setText(cooked_dir); } } void LauncherPage::on_downloadsDirBrowseBtn_clicked() { - QString rawDir = QFileDialog::getExistingDirectory(this, tr("Downloads Folder"), ui->downloadsDirTextBox->text()); + QString raw_dir = QFileDialog::getExistingDirectory(this, tr("Downloads Folder"), ui->downloadsDirTextBox->text()); - if (!rawDir.isEmpty() && QDir(rawDir).exists()) { - QString cookedDir = FS::NormalizePath(rawDir); - ui->downloadsDirTextBox->setText(cookedDir); + if (!raw_dir.isEmpty() && QDir(raw_dir).exists()) { + QString cooked_dir = FS::NormalizePath(raw_dir); + ui->downloadsDirTextBox->setText(cooked_dir); } } void LauncherPage::on_javaDirBrowseBtn_clicked() { - QString rawDir = QFileDialog::getExistingDirectory(this, tr("Java Folder"), ui->javaDirTextBox->text()); + QString raw_dir = QFileDialog::getExistingDirectory(this, tr("Java Folder"), ui->javaDirTextBox->text()); - if (!rawDir.isEmpty() && QDir(rawDir).exists()) { - QString cookedDir = FS::NormalizePath(rawDir); - ui->javaDirTextBox->setText(cookedDir); + if (!raw_dir.isEmpty() && QDir(raw_dir).exists()) { + QString cooked_dir = FS::NormalizePath(raw_dir); + ui->javaDirTextBox->setText(cooked_dir); } } void LauncherPage::on_skinsDirBrowseBtn_clicked() { - QString rawDir = QFileDialog::getExistingDirectory(this, tr("Skins Folder"), ui->skinsDirTextBox->text()); + QString raw_dir = QFileDialog::getExistingDirectory(this, tr("Skins Folder"), ui->skinsDirTextBox->text()); // do not allow current dir - it's dirty. Do not allow dirs that don't exist - if (!rawDir.isEmpty() && QDir(rawDir).exists()) { - QString cookedDir = FS::NormalizePath(rawDir); - ui->skinsDirTextBox->setText(cookedDir); + if (!raw_dir.isEmpty() && QDir(raw_dir).exists()) { + QString cooked_dir = FS::NormalizePath(raw_dir); + ui->skinsDirTextBox->setText(cooked_dir); } } @@ -194,7 +191,7 @@ void LauncherPage::on_metadataEnableBtn_clicked() void LauncherPage::applySettings() { - auto* s = APPLICATION->settings(); + auto s = APPLICATION->settings(); // Updates if (APPLICATION->updater()) { @@ -230,9 +227,6 @@ void LauncherPage::applySettings() case Sort_LastLaunch: s->set("InstSortMode", "LastLaunch"); break; - case Sort_Playtime: - s->set("InstSortMode", "Playtime"); - break; case Sort_Name: default: s->set("InstSortMode", "Name"); @@ -252,11 +246,10 @@ void LauncherPage::applySettings() s->set("ModDependenciesDisabled", !ui->dependenciesEnableBtn->isChecked()); s->set("ShowModIncompat", ui->showModIncompatCheckBox->isChecked()); s->set("SkipModpackUpdatePrompt", !ui->modpackUpdatePromptBtn->isChecked()); - s->set("DownloadGameFilesDuringInstanceCreation", ui->downloadGameFilesBtn->isChecked()); } void LauncherPage::loadSettings() { - auto* s = APPLICATION->settings(); + auto s = APPLICATION->settings(); // Updates if (APPLICATION->updater()) { ui->autoUpdateCheckBox->setChecked(APPLICATION->updater()->getAutomaticallyChecksForUpdates()); @@ -288,8 +281,6 @@ void LauncherPage::loadSettings() QString sortMode = s->get("InstSortMode").toString(); if (sortMode == "LastLaunch") { ui->sortLastLaunchedBtn->setChecked(true); - } else if (sortMode == "Playtime"){ - ui->sortByPlaytimeBtn->setChecked(true); } else { ui->sortByNameBtn->setChecked(true); } @@ -305,7 +296,6 @@ void LauncherPage::loadSettings() ui->dependenciesEnableBtn->setChecked(!s->get("ModDependenciesDisabled").toBool()); ui->showModIncompatCheckBox->setChecked(s->get("ShowModIncompat").toBool()); ui->modpackUpdatePromptBtn->setChecked(!s->get("SkipModpackUpdatePrompt").toBool()); - ui->downloadGameFilesBtn->setChecked(s->get("DownloadGameFilesDuringInstanceCreation").toBool()); } void LauncherPage::retranslate() diff --git a/launcher/ui/pages/global/LauncherPage.ui b/launcher/ui/pages/global/LauncherPage.ui index c98cb1032..f5cfacf96 100644 --- a/launcher/ui/pages/global/LauncherPage.ui +++ b/launcher/ui/pages/global/LauncherPage.ui @@ -83,16 +83,6 @@ - - - - By total time &played - - - sortingModeGroup - - - @@ -261,12 +251,12 @@ - - Folder where Prism Launcher stores automatically downloaded Java versions. Do NOT set this to your system Java installation. - &Auto Java Download: + + Folder where Prism Launcher stores automatically downloaded Java versions. Do NOT set this to your system Java installation. + javaDirTextBox @@ -454,25 +444,6 @@ - - - - Instance Creation - - - - - - Downloads required game files while creating the instance. Disable this to skip the initial download and fetch files when the instance is launched instead. - - - Download game files during instance creation - - - - - - @@ -683,12 +654,6 @@ scrollArea - sortByNameBtn - sortLastLaunchedBtn - sortByPlaytimeBtn - askToRenameDirBtn - alwaysRenameDirBtn - neverRenameDirBtn preferMenuBarCheckBox autoUpdateCheckBox updateIntervalSpinBox @@ -708,9 +673,7 @@ downloadsDirMoveCheckBox metadataEnableBtn dependenciesEnableBtn - showModIncompatCheckBox modpackUpdatePromptBtn - downloadGameFilesBtn lineLimitSpinBox checkStopLogging numberOfConcurrentTasksSpinBox diff --git a/launcher/ui/pages/instance/DataPackPage.cpp b/launcher/ui/pages/instance/DataPackPage.cpp index eb59fbb1e..fb07a768b 100644 --- a/launcher/ui/pages/instance/DataPackPage.cpp +++ b/launcher/ui/pages/instance/DataPackPage.cpp @@ -39,9 +39,9 @@ DataPackPage::DataPackPage(BaseInstance* instance, DataPackFolderModel* model, Q connect(ui->actionUpdateItem, &QAction::triggered, this, &DataPackPage::updateDataPacks); ui->actionsToolbar->insertActionBefore(ui->actionAddItem, ui->actionUpdateItem); - auto* updateMenu = new QMenu(this); + auto updateMenu = new QMenu(this); - auto* update = updateMenu->addAction(ui->actionUpdateItem->text()); + auto update = updateMenu->addAction(ui->actionUpdateItem->text()); connect(update, &QAction::triggered, this, &DataPackPage::updateDataPacks); updateMenu->addAction(ui->actionResetItemMetadata); @@ -64,9 +64,8 @@ void DataPackPage::updateFrame(const QModelIndex& current, [[maybe_unused]] cons void DataPackPage::downloadDataPacks() { - if (m_instance->typeName() != "Minecraft") { + if (m_instance->typeName() != "Minecraft") return; // this is a null instance or a legacy instance - } m_downloadDialog = new ResourceDownload::DataPackDownloadDialog(this, m_model, m_instance); connect(this, &QObject::destroyed, m_downloadDialog, &QDialog::close); @@ -77,9 +76,9 @@ void DataPackPage::downloadDataPacks() void DataPackPage::downloadDialogFinished(int result) { - if (result != 0) { - auto* tasks = new ConcurrentTask(tr("Download Data Packs"), APPLICATION->settings()->get("NumberOfConcurrentDownloads").toInt()); - connect(tasks, &Task::failed, [this, tasks](const QString& reason) { + if (result) { + auto tasks = new ConcurrentTask(tr("Download Data Packs"), APPLICATION->settings()->get("NumberOfConcurrentDownloads").toInt()); + connect(tasks, &Task::failed, [this, tasks](QString reason) { CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->show(); tasks->deleteLater(); }); @@ -89,9 +88,8 @@ void DataPackPage::downloadDialogFinished(int result) }); connect(tasks, &Task::succeeded, [this, tasks]() { QStringList warnings = tasks->warnings(); - if (warnings.count()) { + if (warnings.count()) CustomMessageBox::selectable(this, tr("Warnings"), warnings.join('\n'), QMessageBox::Warning)->show(); - } tasks->deleteLater(); }); @@ -110,16 +108,14 @@ void DataPackPage::downloadDialogFinished(int result) m_model->update(); } - if (m_downloadDialog) { + if (m_downloadDialog) m_downloadDialog->deleteLater(); - } } void DataPackPage::updateDataPacks() { - if (m_instance->typeName() != "Minecraft") { + if (m_instance->typeName() != "Minecraft") return; // this is a null instance or a legacy instance - } if (APPLICATION->settings()->get("ModMetadataDisabled").toBool()) { QMessageBox::critical(this, tr("Error"), tr("Data pack updates are unavailable when metadata is disabled!")); @@ -134,29 +130,27 @@ void DataPackPage::updateDataPacks() QMessageBox::Warning, QMessageBox::Yes | QMessageBox::No, QMessageBox::No) ->exec(); - if (response != QMessageBox::Yes) { + if (response != QMessageBox::Yes) return; - } } auto selection = m_filterModel->mapSelectionToSource(ui->treeView->selectionModel()->selection()).indexes(); - auto modsList = m_model->selectedResources(selection); - bool useAll = modsList.empty(); - if (useAll) { - modsList = m_model->allResources(); - } + auto mods_list = m_model->selectedResources(selection); + bool use_all = mods_list.empty(); + if (use_all) + mods_list = m_model->allResources(); - ResourceUpdateDialog updateDialog(this, m_instance, m_model, modsList, false, { ModPlatform::ModLoaderType::DataPack }); - updateDialog.checkCandidates(); + ResourceUpdateDialog update_dialog(this, m_instance, m_model, mods_list, false, { ModPlatform::ModLoaderType::DataPack }); + update_dialog.checkCandidates(); - if (updateDialog.aborted()) { + if (update_dialog.aborted()) { CustomMessageBox::selectable(this, tr("Aborted"), tr("The data pack updater was aborted!"), QMessageBox::Warning)->show(); return; } - if (updateDialog.noUpdates()) { - QString message{ tr("'%1' is up-to-date! :)").arg(modsList.front()->name()) }; - if (modsList.size() > 1) { - if (useAll) { + if (update_dialog.noUpdates()) { + QString message{ tr("'%1' is up-to-date! :)").arg(mods_list.front()->name()) }; + if (mods_list.size() > 1) { + if (use_all) { message = tr("All data packs are up-to-date! :)"); } else { message = tr("All selected data packs are up-to-date! :)"); @@ -166,9 +160,9 @@ void DataPackPage::updateDataPacks() return; } - if (updateDialog.exec() != 0) { - auto* tasks = new ConcurrentTask("Download Data Packs", APPLICATION->settings()->get("NumberOfConcurrentDownloads").toInt()); - connect(tasks, &Task::failed, [this, tasks](const QString& reason) { + if (update_dialog.exec()) { + auto tasks = new ConcurrentTask("Download Data Packs", APPLICATION->settings()->get("NumberOfConcurrentDownloads").toInt()); + connect(tasks, &Task::failed, [this, tasks](QString reason) { CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->show(); tasks->deleteLater(); }); @@ -184,7 +178,7 @@ void DataPackPage::updateDataPacks() tasks->deleteLater(); }); - for (const auto& task : updateDialog.getTasks()) { + for (auto task : update_dialog.getTasks()) { tasks->addTask(task); } @@ -200,9 +194,8 @@ void DataPackPage::deleteDataPackMetadata() { auto selection = m_filterModel->mapSelectionToSource(ui->treeView->selectionModel()->selection()).indexes(); auto selectionCount = m_model->selectedDataPacks(selection).length(); - if (selectionCount == 0) { + if (selectionCount == 0) return; - } if (selectionCount > 1) { auto response = CustomMessageBox::selectable(this, tr("Confirm Removal"), tr("You are about to remove the metadata for %1 data packs.\n" @@ -211,9 +204,8 @@ void DataPackPage::deleteDataPackMetadata() QMessageBox::Warning, QMessageBox::Yes | QMessageBox::No, QMessageBox::No) ->exec(); - if (response != QMessageBox::Yes) { + if (response != QMessageBox::Yes) return; - } } m_model->deleteMetadata(selection); @@ -221,9 +213,8 @@ void DataPackPage::deleteDataPackMetadata() void DataPackPage::changeDataPackVersion() { - if (m_instance->typeName() != "Minecraft") { + if (m_instance->typeName() != "Minecraft") return; // this is a null instance or a legacy instance - } if (APPLICATION->settings()->get("ModMetadataDisabled").toBool()) { QMessageBox::critical(this, tr("Error"), tr("Data pack updates are unavailable when metadata is disabled!")); @@ -232,21 +223,19 @@ void DataPackPage::changeDataPackVersion() const QModelIndexList rows = ui->treeView->selectionModel()->selectedRows(); - if (rows.count() != 1) { + if (rows.count() != 1) return; - } Resource& resource = m_model->at(m_filterModel->mapToSource(rows[0]).row()); - if (resource.metadata() == nullptr) { + if (resource.metadata() == nullptr) return; - } - ResourceDownload::DataPackDownloadDialog mdownload(this, m_model, m_instance, true); + ResourceDownload::DataPackDownloadDialog mdownload(this, m_model, m_instance); mdownload.setResourceMetadata(resource.metadata()); - if (mdownload.exec() != 0) { - auto* tasks = new ConcurrentTask("Download Data Packs", APPLICATION->settings()->get("NumberOfConcurrentDownloads").toInt()); - connect(tasks, &Task::failed, [this, tasks](const QString& reason) { + if (mdownload.exec()) { + auto tasks = new ConcurrentTask("Download Data Packs", APPLICATION->settings()->get("NumberOfConcurrentDownloads").toInt()); + connect(tasks, &Task::failed, [this, tasks](QString reason) { CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->show(); tasks->deleteLater(); }); @@ -256,9 +245,8 @@ void DataPackPage::changeDataPackVersion() }); connect(tasks, &Task::succeeded, [this, tasks]() { QStringList warnings = tasks->warnings(); - if (warnings.count()) { + if (warnings.count()) CustomMessageBox::selectable(this, tr("Warnings"), warnings.join('\n'), QMessageBox::Warning)->show(); - } tasks->deleteLater(); }); @@ -277,15 +265,14 @@ void DataPackPage::changeDataPackVersion() GlobalDataPackPage::GlobalDataPackPage(MinecraftInstance* instance, QWidget* parent) : QWidget(parent), m_instance(instance) { - auto* layout = new QVBoxLayout(this); + auto layout = new QVBoxLayout(this); layout->setContentsMargins(0, 0, 0, 0); setLayout(layout); connect(instance->settings()->getSetting("GlobalDataPacksEnabled").get(), &Setting::SettingChanged, this, [this] { updateContent(); - if (m_container != nullptr) { + if (m_container != nullptr) m_container->refreshContainer(); - } }); connect(instance->settings()->getSetting("GlobalDataPacksPath").get(), &Setting::SettingChanged, this, @@ -294,27 +281,24 @@ GlobalDataPackPage::GlobalDataPackPage(MinecraftInstance* instance, QWidget* par QString GlobalDataPackPage::displayName() const { - if (m_underlyingPage == nullptr) { + if (m_underlyingPage == nullptr) return {}; - } return m_underlyingPage->displayName(); } QIcon GlobalDataPackPage::icon() const { - if (m_underlyingPage == nullptr) { + if (m_underlyingPage == nullptr) return {}; - } return m_underlyingPage->icon(); } QString GlobalDataPackPage::helpPage() const { - if (m_underlyingPage == nullptr) { + if (m_underlyingPage == nullptr) return {}; - } return m_underlyingPage->helpPage(); } @@ -331,24 +315,21 @@ bool GlobalDataPackPage::apply() void GlobalDataPackPage::openedImpl() { - if (m_underlyingPage != nullptr) { + if (m_underlyingPage != nullptr) m_underlyingPage->openedImpl(); - } } void GlobalDataPackPage::closedImpl() { - if (m_underlyingPage != nullptr) { + if (m_underlyingPage != nullptr) m_underlyingPage->closedImpl(); - } } void GlobalDataPackPage::updateContent() { if (m_underlyingPage != nullptr) { - if (m_container->selectedPage() == this) { + if (m_container->selectedPage() == this) m_underlyingPage->closedImpl(); - } m_underlyingPage->apply(); @@ -363,9 +344,8 @@ void GlobalDataPackPage::updateContent() m_underlyingPage->setParentContainer(m_container); m_underlyingPage->updateExtraInfo = [this](QString id, QString value) { updateExtraInfo(std::move(id), std::move(value)); }; - if (m_container->selectedPage() == this) { + if (m_container->selectedPage() == this) m_underlyingPage->openedImpl(); - } layout()->addWidget(m_underlyingPage); } diff --git a/launcher/ui/pages/instance/ManagedPackPage.cpp b/launcher/ui/pages/instance/ManagedPackPage.cpp index d2683fa92..777dfbaa1 100644 --- a/launcher/ui/pages/instance/ManagedPackPage.cpp +++ b/launcher/ui/pages/instance/ManagedPackPage.cpp @@ -128,7 +128,7 @@ ManagedPackPage::ManagedPackPage(BaseInstance* inst, InstanceWindow* instance_wi QDesktopServices::openUrl(url); }); - connect(ui->urlLine, &QLineEdit::textChanged, this, [this](QString text) { m_inst->settings()->set("ManagedPackURL", text.trimmed()); }); + connect(ui->urlLine, &QLineEdit::textChanged, this, [this](QString text) { m_inst->settings()->set("ManagedPackURL", text); }); } ManagedPackPage::~ManagedPackPage() @@ -147,7 +147,7 @@ void ManagedPackPage::openedImpl() ui->updateToVersionLabel->setText(tr("URL:")); ui->updateButton->setText(tr("Update Pack")); ui->updateButton->setDisabled(false); - ui->urlLine->setText(m_inst->settings()->get("ManagedPackURL").toString().trimmed()); + ui->urlLine->setText(m_inst->settings()->get("ManagedPackURL").toString()); ui->packName->setText(m_inst->name()); ui->changelogTextBrowser->setText(tr("This is a local modpack.\n" @@ -357,7 +357,7 @@ void ManagedPackPage::onUpdateTaskCompleted(bool did_succeed) const void ModrinthManagedPackPage::update() { - auto customURL = m_inst->settings()->get("ManagedPackURL").toString().trimmed(); + auto customURL = m_inst->settings()->get("ManagedPackURL").toString(); if (m_inst->getManagedPackID().isEmpty() && !customURL.isEmpty()) { updatePack(customURL); return; @@ -486,7 +486,7 @@ void FlameManagedPackPage::suggestVersion() void FlameManagedPackPage::update() { - auto customURL = m_inst->settings()->get("ManagedPackURL").toString().trimmed(); + auto customURL = m_inst->settings()->get("ManagedPackURL").toString(); if (m_inst->getManagedPackID().isEmpty() && !customURL.isEmpty()) { updatePack(customURL); return; diff --git a/launcher/ui/pages/instance/ModFolderPage.cpp b/launcher/ui/pages/instance/ModFolderPage.cpp index 99c78647c..7ba72a9b0 100644 --- a/launcher/ui/pages/instance/ModFolderPage.cpp +++ b/launcher/ui/pages/instance/ModFolderPage.cpp @@ -81,9 +81,9 @@ ModFolderPage::ModFolderPage(BaseInstance* inst, ModFolderModel* model, QWidget* connect(ui->actionUpdateItem, &QAction::triggered, this, &ModFolderPage::updateMods); ui->actionsToolbar->insertActionBefore(ui->actionAddItem, ui->actionUpdateItem); - auto* updateMenu = new QMenu(this); + auto updateMenu = new QMenu(this); - auto* update = updateMenu->addAction(tr("Check for Updates")); + auto update = updateMenu->addAction(tr("Check for Updates")); connect(update, &QAction::triggered, this, &ModFolderPage::updateMods); updateMenu->addAction(ui->actionVerifyItemDependencies); @@ -134,9 +134,8 @@ void ModFolderPage::removeItems(const QItemSelection& selection) QMessageBox::Warning, QMessageBox::Yes | QMessageBox::No, QMessageBox::No) ->exec(); - if (response != QMessageBox::Yes) { + if (response != QMessageBox::Yes) return; - } } auto indexes = selection.indexes(); @@ -162,11 +161,10 @@ void ModFolderPage::removeItems(const QItemSelection& selection) void ModFolderPage::downloadMods() { - if (m_instance->typeName() != "Minecraft") { + if (m_instance->typeName() != "Minecraft") return; // this is a null instance or a legacy instance - } - auto* profile = static_cast(m_instance)->getPackProfile(); + auto profile = static_cast(m_instance)->getPackProfile(); if (!profile->getModLoaders().has_value()) { if (handleNoModLoader()) { return; @@ -182,9 +180,9 @@ void ModFolderPage::downloadMods() void ModFolderPage::downloadDialogFinished(int result) { - if (result != 0) { - auto* tasks = new ConcurrentTask(tr("Download Mods"), APPLICATION->settings()->get("NumberOfConcurrentDownloads").toInt()); - connect(tasks, &Task::failed, [this, tasks](const QString& reason) { + if (result) { + auto tasks = new ConcurrentTask(tr("Download Mods"), APPLICATION->settings()->get("NumberOfConcurrentDownloads").toInt()); + connect(tasks, &Task::failed, [this, tasks](QString reason) { CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->show(); tasks->deleteLater(); }); @@ -194,9 +192,8 @@ void ModFolderPage::downloadDialogFinished(int result) }); connect(tasks, &Task::succeeded, [this, tasks]() { QStringList warnings = tasks->warnings(); - if (warnings.count()) { + if (warnings.count()) CustomMessageBox::selectable(this, tr("Warnings"), warnings.join('\n'), QMessageBox::Warning)->show(); - } tasks->deleteLater(); }); @@ -215,18 +212,16 @@ void ModFolderPage::downloadDialogFinished(int result) m_model->update(); } - if (m_downloadDialog) { + if (m_downloadDialog) m_downloadDialog->deleteLater(); - } } void ModFolderPage::updateMods(bool includeDeps) { - if (m_instance->typeName() != "Minecraft") { + if (m_instance->typeName() != "Minecraft") return; // this is a null instance or a legacy instance - } - auto* profile = static_cast(m_instance)->getPackProfile(); + auto profile = static_cast(m_instance)->getPackProfile(); if (!profile->getModLoaders().has_value()) { if (handleNoModLoader()) { return; @@ -245,29 +240,27 @@ void ModFolderPage::updateMods(bool includeDeps) QMessageBox::Warning, QMessageBox::Yes | QMessageBox::No, QMessageBox::No) ->exec(); - if (response != QMessageBox::Yes) { + if (response != QMessageBox::Yes) return; - } } auto selection = m_filterModel->mapSelectionToSource(ui->treeView->selectionModel()->selection()).indexes(); - auto modsList = m_model->selectedResources(selection); - bool useAll = modsList.empty(); - if (useAll) { - modsList = m_model->allResources(); - } + auto mods_list = m_model->selectedResources(selection); + bool use_all = mods_list.empty(); + if (use_all) + mods_list = m_model->allResources(); - ResourceUpdateDialog updateDialog(this, m_instance, m_model, modsList, includeDeps, profile->getModLoadersList()); - updateDialog.checkCandidates(); + ResourceUpdateDialog update_dialog(this, m_instance, m_model, mods_list, includeDeps, profile->getModLoadersList()); + update_dialog.checkCandidates(); - if (updateDialog.aborted()) { + if (update_dialog.aborted()) { CustomMessageBox::selectable(this, tr("Aborted"), tr("The mod updater was aborted!"), QMessageBox::Warning)->show(); return; } - if (updateDialog.noUpdates()) { - QString message{ tr("'%1' is up-to-date! :)").arg(modsList.front()->name()) }; - if (modsList.size() > 1) { - if (useAll) { + if (update_dialog.noUpdates()) { + QString message{ tr("'%1' is up-to-date! :)").arg(mods_list.front()->name()) }; + if (mods_list.size() > 1) { + if (use_all) { message = tr("All mods are up-to-date! :)"); } else { message = tr("All selected mods are up-to-date! :)"); @@ -277,9 +270,9 @@ void ModFolderPage::updateMods(bool includeDeps) return; } - if (updateDialog.exec() != 0) { - auto* tasks = new ConcurrentTask("Download Mods", APPLICATION->settings()->get("NumberOfConcurrentDownloads").toInt()); - connect(tasks, &Task::failed, [this, tasks](const QString& reason) { + if (update_dialog.exec()) { + auto tasks = new ConcurrentTask("Download Mods", APPLICATION->settings()->get("NumberOfConcurrentDownloads").toInt()); + connect(tasks, &Task::failed, [this, tasks](QString reason) { CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->show(); tasks->deleteLater(); }); @@ -295,7 +288,7 @@ void ModFolderPage::updateMods(bool includeDeps) tasks->deleteLater(); }); - for (const auto& task : updateDialog.getTasks()) { + for (auto task : update_dialog.getTasks()) { tasks->addTask(task); } @@ -311,9 +304,8 @@ void ModFolderPage::deleteModMetadata() { auto selection = m_filterModel->mapSelectionToSource(ui->treeView->selectionModel()->selection()).indexes(); auto selectionCount = m_model->selectedMods(selection).length(); - if (selectionCount == 0) { + if (selectionCount == 0) return; - } if (selectionCount > 1) { auto response = CustomMessageBox::selectable(this, tr("Confirm Removal"), tr("You are about to remove the metadata for %1 mods.\n" @@ -322,9 +314,8 @@ void ModFolderPage::deleteModMetadata() QMessageBox::Warning, QMessageBox::Yes | QMessageBox::No, QMessageBox::No) ->exec(); - if (response != QMessageBox::Yes) { + if (response != QMessageBox::Yes) return; - } } m_model->deleteMetadata(selection); @@ -332,11 +323,10 @@ void ModFolderPage::deleteModMetadata() void ModFolderPage::changeModVersion() { - if (m_instance->typeName() != "Minecraft") { + if (m_instance->typeName() != "Minecraft") return; // this is a null instance or a legacy instance - } - auto* profile = static_cast(m_instance)->getPackProfile(); + auto profile = static_cast(m_instance)->getPackProfile(); if (!profile->getModLoaders().has_value()) { if (handleNoModLoader()) { return; @@ -347,16 +337,15 @@ void ModFolderPage::changeModVersion() return; } auto selection = m_filterModel->mapSelectionToSource(ui->treeView->selectionModel()->selection()).indexes(); - auto modsList = m_model->selectedMods(selection); - if (modsList.length() != 1 || modsList[0]->metadata() == nullptr) { + auto mods_list = m_model->selectedMods(selection); + if (mods_list.length() != 1 || mods_list[0]->metadata() == nullptr) return; - } - m_downloadDialog = new ResourceDownload::ModDownloadDialog(this, m_model, m_instance, true); + m_downloadDialog = new ResourceDownload::ModDownloadDialog(this, m_model, m_instance); connect(this, &QObject::destroyed, m_downloadDialog, &QDialog::close); connect(m_downloadDialog, &QDialog::finished, this, &ModFolderPage::downloadDialogFinished); - m_downloadDialog->setResourceMetadata((*modsList.begin())->metadata()); + m_downloadDialog->setResourceMetadata((*mods_list.begin())->metadata()); m_downloadDialog->open(); } @@ -364,21 +353,20 @@ void ModFolderPage::exportModMetadata() { auto selection = m_filterModel->mapSelectionToSource(ui->treeView->selectionModel()->selection()).indexes(); auto selectedMods = m_model->selectedMods(selection); - if (selectedMods.length() == 0) { + if (selectedMods.length() == 0) selectedMods = m_model->allMods(); - } - std::ranges::sort(selectedMods, [](const Mod* a, const Mod* b) { return a->name() < b->name(); }); + std::sort(selectedMods.begin(), selectedMods.end(), [](const Mod* a, const Mod* b) { return a->name() < b->name(); }); ExportToModListDialog dlg(m_instance->name(), selectedMods, this); dlg.exec(); } CoreModFolderPage::CoreModFolderPage(BaseInstance* inst, ModFolderModel* mods, QWidget* parent) : ModFolderPage(inst, mods, parent) { - auto* mcInst = dynamic_cast(m_instance); + auto mcInst = dynamic_cast(m_instance); if (mcInst) { - auto* version = mcInst->getPackProfile(); - if ((version != nullptr) && version->getComponent("net.minecraftforge") && version->getComponent("net.minecraft")) { + auto version = mcInst->getPackProfile(); + if (version && version->getComponent("net.minecraftforge") && version->getComponent("net.minecraft")) { auto minecraftCmp = version->getComponent("net.minecraft"); if (!minecraftCmp->m_loaded) { version->reload(Net::Mode::Offline); @@ -401,15 +389,13 @@ CoreModFolderPage::CoreModFolderPage(BaseInstance* inst, ModFolderModel* mods, Q bool CoreModFolderPage::shouldDisplay() const { if (ModFolderPage::shouldDisplay()) { - auto* inst = dynamic_cast(m_instance); - if (!inst) { + auto inst = dynamic_cast(m_instance); + if (!inst) return true; - } - auto* version = inst->getPackProfile(); - if ((version == nullptr) || !version->getComponent("net.minecraftforge") || !version->getComponent("net.minecraft")) { + auto version = inst->getPackProfile(); + if (!version || !version->getComponent("net.minecraftforge") || !version->getComponent("net.minecraft")) return false; - } auto minecraftCmp = version->getComponent("net.minecraft"); return minecraftCmp->m_loaded && minecraftCmp->getReleaseDateTime() < g_VersionFilterData.legacyCutoffDate; } @@ -426,22 +412,31 @@ bool NilModFolderPage::shouldDisplay() const // Helper function so this doesn't need to be duplicated 3 times inline bool ModFolderPage::handleNoModLoader() { - int resp = QMessageBox::question( - this, ModFolderPage::tr("Missing Mod Loader"), - ModFolderPage::tr("You need to install a compatible mod loader before installing mods. Would you like to do so?"), - QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes); - if (resp == QMessageBox::Yes) { - // Should be safe - auto* profile = static_cast(this->m_instance)->getPackProfile(); - InstallLoaderDialog dialog(profile, QString(), this); - bool ret = dialog.exec() != 0; - this->m_container->refreshContainer(); + int resp = + QMessageBox::question(this, this->tr("Missing Mod Loader"), + this->tr("You need to install a compatible mod loader before installing mods. Would you like to do so?"), + QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes); + switch (resp) { + case QMessageBox::Yes: { + // Should be safe + auto profile = static_cast(this->m_instance)->getPackProfile(); + InstallLoaderDialog dialog(profile, QString(), this); + bool ret = dialog.exec(); + this->m_container->refreshContainer(); - // returning negation of dialog.exec which'll be true if the install loader dialog got canceled/closed - // and false if the user went through and installed a loader - return !ret; + // returning negation of dialog.exec which'll be true if the install loader dialog got canceled/closed + // and false if the user went through and installed a loader + return !ret; + } + case QMessageBox::No: { + // Nothing happens the dialog is already closing + // returning true so the caller doesn't go and continue with opening it's dialog without a mod loader + return true; + } + default: { + // Unreachable + // returning true as a safety measure + return true; + } } - // Nothing happens the dialog is already closing - // returning true so the caller doesn't go and continue with opening it's dialog without a mod loader - return true; } diff --git a/launcher/ui/pages/instance/OtherLogsPage.cpp b/launcher/ui/pages/instance/OtherLogsPage.cpp index b9f943777..19a9db04f 100644 --- a/launcher/ui/pages/instance/OtherLogsPage.cpp +++ b/launcher/ui/pages/instance/OtherLogsPage.cpp @@ -277,15 +277,12 @@ void OtherLogsPage::reload() MessageLevel last = MessageLevel::Unknown; auto handleLine = [this, &last](QString line) { - if (!line.isEmpty() && line.back() == '\n') { - line.resize(line.size() - 1); - } - if (!line.isEmpty() && line.back() == '\r') { - line.resize(line.size() - 1); - } - if (line.isEmpty()) { + if (line.isEmpty()) return false; - } + if (line.back() == '\n') + line.resize(line.size() - 1); + if (line.back() == '\r') + line.resize(line.size() - 1); MessageLevel level = MessageLevel::Unknown; QString lineTemp = line; // don't edit out the time and level for clarity diff --git a/launcher/ui/pages/instance/ResourcePackPage.cpp b/launcher/ui/pages/instance/ResourcePackPage.cpp index e4709ab2b..eb085e29b 100644 --- a/launcher/ui/pages/instance/ResourcePackPage.cpp +++ b/launcher/ui/pages/instance/ResourcePackPage.cpp @@ -56,9 +56,9 @@ ResourcePackPage::ResourcePackPage(MinecraftInstance* instance, ResourcePackFold connect(ui->actionUpdateItem, &QAction::triggered, this, &ResourcePackPage::updateResourcePacks); ui->actionsToolbar->insertActionBefore(ui->actionAddItem, ui->actionUpdateItem); - auto* updateMenu = new QMenu(this); + auto updateMenu = new QMenu(this); - auto* update = updateMenu->addAction(ui->actionUpdateItem->text()); + auto update = updateMenu->addAction(ui->actionUpdateItem->text()); connect(update, &QAction::triggered, this, &ResourcePackPage::updateResourcePacks); updateMenu->addAction(ui->actionResetItemMetadata); @@ -75,15 +75,14 @@ void ResourcePackPage::updateFrame(const QModelIndex& current, [[maybe_unused]] { auto sourceCurrent = m_filterModel->mapToSource(current); int row = sourceCurrent.row(); - auto& rp = m_model->at(row); + auto& rp = static_cast(m_model->at(row)); ui->frame->updateWithResourcePack(rp); } void ResourcePackPage::downloadResourcePacks() { - if (m_instance->typeName() != "Minecraft") { + if (m_instance->typeName() != "Minecraft") return; // this is a null instance or a legacy instance - } m_downloadDialog = new ResourceDownload::ResourcePackDownloadDialog(this, m_model, m_instance); connect(this, &QObject::destroyed, m_downloadDialog, &QDialog::close); @@ -94,9 +93,9 @@ void ResourcePackPage::downloadResourcePacks() void ResourcePackPage::downloadDialogFinished(int result) { - if (result != 0) { - auto* tasks = new ConcurrentTask("Download Resource Pack", APPLICATION->settings()->get("NumberOfConcurrentDownloads").toInt()); - connect(tasks, &Task::failed, [this, tasks](const QString& reason) { + if (result) { + auto tasks = new ConcurrentTask("Download Resource Pack", APPLICATION->settings()->get("NumberOfConcurrentDownloads").toInt()); + connect(tasks, &Task::failed, [this, tasks](QString reason) { CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->show(); tasks->deleteLater(); }); @@ -106,9 +105,8 @@ void ResourcePackPage::downloadDialogFinished(int result) }); connect(tasks, &Task::succeeded, [this, tasks]() { QStringList warnings = tasks->warnings(); - if (warnings.count()) { + if (warnings.count()) CustomMessageBox::selectable(this, tr("Warnings"), warnings.join('\n'), QMessageBox::Warning)->show(); - } tasks->deleteLater(); }); @@ -127,16 +125,14 @@ void ResourcePackPage::downloadDialogFinished(int result) m_model->update(); } - if (m_downloadDialog) { + if (m_downloadDialog) m_downloadDialog->deleteLater(); - } } void ResourcePackPage::updateResourcePacks() { - if (m_instance->typeName() != "Minecraft") { + if (m_instance->typeName() != "Minecraft") return; // this is a null instance or a legacy instance - } if (APPLICATION->settings()->get("ModMetadataDisabled").toBool()) { QMessageBox::critical(this, tr("Error"), tr("Resource pack updates are unavailable when metadata is disabled!")); @@ -151,29 +147,27 @@ void ResourcePackPage::updateResourcePacks() QMessageBox::Warning, QMessageBox::Yes | QMessageBox::No, QMessageBox::No) ->exec(); - if (response != QMessageBox::Yes) { + if (response != QMessageBox::Yes) return; - } } auto selection = m_filterModel->mapSelectionToSource(ui->treeView->selectionModel()->selection()).indexes(); - auto modsList = m_model->selectedResources(selection); - bool useAll = modsList.empty(); - if (useAll) { - modsList = m_model->allResources(); - } + auto mods_list = m_model->selectedResources(selection); + bool use_all = mods_list.empty(); + if (use_all) + mods_list = m_model->allResources(); - ResourceUpdateDialog updateDialog(this, m_instance, m_model, modsList, false); - updateDialog.checkCandidates(); + ResourceUpdateDialog update_dialog(this, m_instance, m_model, mods_list, false); + update_dialog.checkCandidates(); - if (updateDialog.aborted()) { + if (update_dialog.aborted()) { CustomMessageBox::selectable(this, tr("Aborted"), tr("The resource pack updater was aborted!"), QMessageBox::Warning)->show(); return; } - if (updateDialog.noUpdates()) { - QString message{ tr("'%1' is up-to-date! :)").arg(modsList.front()->name()) }; - if (modsList.size() > 1) { - if (useAll) { + if (update_dialog.noUpdates()) { + QString message{ tr("'%1' is up-to-date! :)").arg(mods_list.front()->name()) }; + if (mods_list.size() > 1) { + if (use_all) { message = tr("All resource packs are up-to-date! :)"); } else { message = tr("All selected resource packs are up-to-date! :)"); @@ -183,9 +177,9 @@ void ResourcePackPage::updateResourcePacks() return; } - if (updateDialog.exec() != 0) { - auto* tasks = new ConcurrentTask("Download Resource Packs", APPLICATION->settings()->get("NumberOfConcurrentDownloads").toInt()); - connect(tasks, &Task::failed, [this, tasks](const QString& reason) { + if (update_dialog.exec()) { + auto tasks = new ConcurrentTask("Download Resource Packs", APPLICATION->settings()->get("NumberOfConcurrentDownloads").toInt()); + connect(tasks, &Task::failed, [this, tasks](QString reason) { CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->show(); tasks->deleteLater(); }); @@ -201,7 +195,7 @@ void ResourcePackPage::updateResourcePacks() tasks->deleteLater(); }); - for (const auto& task : updateDialog.getTasks()) { + for (auto task : update_dialog.getTasks()) { tasks->addTask(task); } @@ -217,9 +211,8 @@ void ResourcePackPage::deleteResourcePackMetadata() { auto selection = m_filterModel->mapSelectionToSource(ui->treeView->selectionModel()->selection()).indexes(); auto selectionCount = m_model->selectedResourcePacks(selection).length(); - if (selectionCount == 0) { + if (selectionCount == 0) return; - } if (selectionCount > 1) { auto response = CustomMessageBox::selectable(this, tr("Confirm Removal"), tr("You are about to remove the metadata for %1 resource packs.\n" @@ -228,9 +221,8 @@ void ResourcePackPage::deleteResourcePackMetadata() QMessageBox::Warning, QMessageBox::Yes | QMessageBox::No, QMessageBox::No) ->exec(); - if (response != QMessageBox::Yes) { + if (response != QMessageBox::Yes) return; - } } m_model->deleteMetadata(selection); @@ -238,9 +230,8 @@ void ResourcePackPage::deleteResourcePackMetadata() void ResourcePackPage::changeResourcePackVersion() { - if (m_instance->typeName() != "Minecraft") { + if (m_instance->typeName() != "Minecraft") return; // this is a null instance or a legacy instance - } if (APPLICATION->settings()->get("ModMetadataDisabled").toBool()) { QMessageBox::critical(this, tr("Error"), tr("Resource pack updates are unavailable when metadata is disabled!")); @@ -249,17 +240,15 @@ void ResourcePackPage::changeResourcePackVersion() const QModelIndexList rows = ui->treeView->selectionModel()->selectedRows(); - if (rows.count() != 1) { + if (rows.count() != 1) return; - } Resource& resource = m_model->at(m_filterModel->mapToSource(rows[0]).row()); - if (resource.metadata() == nullptr) { + if (resource.metadata() == nullptr) return; - } - m_downloadDialog = new ResourceDownload::ResourcePackDownloadDialog(this, m_model, m_instance, true); + m_downloadDialog = new ResourceDownload::ResourcePackDownloadDialog(this, m_model, m_instance); connect(this, &QObject::destroyed, m_downloadDialog, &QDialog::close); connect(m_downloadDialog, &QDialog::finished, this, &ResourcePackPage::downloadDialogFinished); diff --git a/launcher/ui/pages/instance/ScreenshotsPage.cpp b/launcher/ui/pages/instance/ScreenshotsPage.cpp index 71dc7218e..70647bed7 100644 --- a/launcher/ui/pages/instance/ScreenshotsPage.cpp +++ b/launcher/ui/pages/instance/ScreenshotsPage.cpp @@ -45,6 +45,7 @@ #include #include #include +#include #include #include #include @@ -52,8 +53,6 @@ #include #include #include -#include -#include #include #include "settings/SettingsObject.h" @@ -71,14 +70,9 @@ #include "RWStorage.h" class ScreenshotsFSModel : public QFileSystemModel { - public: - bool canDropMimeData(const QMimeData* data, - const Qt::DropAction action, - const int row, - const int column, - const QModelIndex& parent) const override + bool canDropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent) const override { - const QUrl root = QUrl::fromLocalFile(rootPath()); + QUrl root = QUrl::fromLocalFile(rootPath()); // this disables reordering items inside the model // by rejecting drops if the file is already inside the folder if (data->hasUrls()) { @@ -98,8 +92,8 @@ using SharedIconCachePtr = std::shared_ptr; class ThumbnailingResult : public QObject { Q_OBJECT public slots: - void emitResultsReady(const QString& path) { emit resultsReady(path); } - void emitResultsFailed(const QString& path) { emit resultsFailed(path); } + inline void emitResultsReady(const QString& path) { emit resultsReady(path); } + inline void emitResultsFailed(const QString& path) { emit resultsFailed(path); } signals: void resultsReady(const QString& path); void resultsFailed(const QString& path); @@ -107,32 +101,32 @@ class ThumbnailingResult : public QObject { class ThumbnailRunnable : public QRunnable { public: - ThumbnailRunnable(QString path, SharedIconCachePtr cache) : m_path(std::move(path)), m_cache(std::move(cache)) {} - void run() override + ThumbnailRunnable(QString path, SharedIconCachePtr cache) { - const QFileInfo info(m_path); - if (info.isDir()) { + m_path = path; + m_cache = cache; + } + void run() + { + QFileInfo info(m_path); + if (info.isDir()) return; - } - if (info.suffix().compare("png", Qt::CaseInsensitive) != 0) { + if ((info.suffix().compare("png", Qt::CaseInsensitive) != 0)) return; - } - if (!m_cache->stale(m_path)) { + if (!m_cache->stale(m_path)) return; - } - const QImage image(m_path); + QImage image(m_path); if (image.isNull()) { m_resultEmitter.emitResultsFailed(m_path); qDebug() << "Error loading screenshot (perhaps too large?):" + m_path; return; } QImage small; - if (image.width() > image.height()) { + if (image.width() > image.height()) small = image.scaledToWidth(512).scaledToWidth(256, Qt::SmoothTransformation); - } else { + else small = image.scaledToHeight(512).scaledToHeight(256, Qt::SmoothTransformation); - } - const QPoint offset((256 - small.width()) / 2, (256 - small.height()) / 2); + QPoint offset((256 - small.width()) / 2, (256 - small.height()) / 2); QImage square(QSize(256, 256), QImage::Format_ARGB32); square.fill(Qt::transparent); @@ -140,7 +134,7 @@ class ThumbnailRunnable : public QRunnable { painter.drawImage(offset, small); painter.end(); - const QIcon icon(QPixmap::fromImage(square)); + QIcon icon(QPixmap::fromImage(square)); m_cache->add(m_path, icon); m_resultEmitter.emitResultsReady(m_path); } @@ -154,62 +148,59 @@ class ThumbnailRunnable : public QRunnable { class FilterModel : public QIdentityProxyModel { Q_OBJECT public: - explicit FilterModel(QObject* parent = nullptr) : QIdentityProxyModel(parent) + explicit FilterModel(QObject* parent = 0) : QIdentityProxyModel(parent) { m_thumbnailingPool.setMaxThreadCount(4); m_thumbnailCache = std::make_shared(); m_thumbnailCache->add("placeholder", QIcon::fromTheme("screenshot-placeholder")); connect(&watcher, &QFileSystemWatcher::fileChanged, this, &FilterModel::fileChanged); } - ~FilterModel() override + virtual ~FilterModel() { m_thumbnailingPool.clear(); - if (!m_thumbnailingPool.waitForDone(500)) { + if (!m_thumbnailingPool.waitForDone(500)) qDebug() << "Thumbnail pool took longer than 500ms to finish"; - } } - QVariant data(const QModelIndex& proxyIndex, const int role = Qt::DisplayRole) const override // NOLINT(*-default-arguments) + virtual QVariant data(const QModelIndex& proxyIndex, int role = Qt::DisplayRole) const { - const auto* model = sourceModel(); - if (!model) { - return {}; - } + auto model = sourceModel(); + if (!model) + return QVariant(); if (role == Qt::DisplayRole || role == Qt::EditRole) { - const QVariant result = model->data(mapToSource(proxyIndex), role); + QVariant result = sourceModel()->data(mapToSource(proxyIndex), role); static const QRegularExpression s_removeChars("\\.png$"); return result.toString().remove(s_removeChars); } if (role == Qt::DecorationRole) { - const QVariant result = model->data(mapToSource(proxyIndex), QFileSystemModel::FilePathRole); - const QString filePath = result.toString(); + QVariant result = sourceModel()->data(mapToSource(proxyIndex), QFileSystemModel::FilePathRole); + QString filePath = result.toString(); + QIcon temp; if (!watched.contains(filePath)) { - const_cast(watcher).addPath(filePath); - const_cast&>(watched).insert(filePath); + ((QFileSystemWatcher&)watcher).addPath(filePath); + ((QSet&)watched).insert(filePath); } - if (QIcon temp; m_thumbnailCache->get(filePath, temp)) { + if (m_thumbnailCache->get(filePath, temp)) { return temp; } if (!m_failed.contains(filePath)) { - const_cast(this)->thumbnailImage(filePath); + ((FilterModel*)this)->thumbnailImage(filePath); } return (m_thumbnailCache->get("placeholder")); } - return model->data(mapToSource(proxyIndex), role); + return sourceModel()->data(mapToSource(proxyIndex), role); } - bool setData(const QModelIndex& index, const QVariant& value, const int role = Qt::EditRole) override // NOLINT(*-default-arguments) + virtual bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) { - auto* model = sourceModel(); - if (!model) { + auto model = sourceModel(); + if (!model) return false; - } - if (role != Qt::EditRole) { + if (role != Qt::EditRole) return false; - } // FIXME: this is a workaround for a bug in QFileSystemModel, where it doesn't // sort after renames { - static_cast(model)->setNameFilterDisables(true); - static_cast(model)->setNameFilterDisables(false); + ((QFileSystemModel*)model)->setNameFilterDisables(true); + ((QFileSystemModel*)model)->setNameFilterDisables(false); } return model->setData(mapToSource(index), value.toString() + ".png", role); } @@ -217,15 +208,15 @@ class FilterModel : public QIdentityProxyModel { private: void thumbnailImage(QString path) { - auto* runnable = new ThumbnailRunnable(std::move(path), m_thumbnailCache); + auto runnable = new ThumbnailRunnable(path, m_thumbnailCache); connect(&runnable->m_resultEmitter, &ThumbnailingResult::resultsReady, this, &FilterModel::thumbnailReady); connect(&runnable->m_resultEmitter, &ThumbnailingResult::resultsFailed, this, &FilterModel::thumbnailFailed); m_thumbnailingPool.start(runnable); } private slots: - void thumbnailReady(const QString& /*path*/) { emit layoutChanged(); } - void thumbnailFailed(const QString& path) { m_failed.insert(path); } - void fileChanged(const QString& filepath) + void thumbnailReady(QString path) { emit layoutChanged(); } + void thumbnailFailed(QString path) { m_failed.insert(path); } + void fileChanged(QString filepath) { m_thumbnailCache->setStale(filepath); // reinsert the path... @@ -246,12 +237,13 @@ class FilterModel : public QIdentityProxyModel { class CenteredEditingDelegate : public QStyledItemDelegate { public: - explicit CenteredEditingDelegate(QObject* parent = nullptr) : QStyledItemDelegate(parent) {} - ~CenteredEditingDelegate() override = default; - QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const override + explicit CenteredEditingDelegate(QObject* parent = 0) : QStyledItemDelegate(parent) {} + virtual ~CenteredEditingDelegate() {} + virtual QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const { - auto* widget = QStyledItemDelegate::createEditor(parent, option, index); - if (auto* foo = dynamic_cast(widget)) { + auto widget = QStyledItemDelegate::createEditor(parent, option, index); + auto foo = dynamic_cast(widget); + if (foo) { foo->setAlignment(Qt::AlignHCenter); foo->setFrame(true); foo->setMaximumWidth(192); @@ -260,11 +252,10 @@ class CenteredEditingDelegate : public QStyledItemDelegate { } }; -ScreenshotsPage::ScreenshotsPage(QString path, QWidget* parent) - : QMainWindow(parent), ui(new Ui::ScreenshotsPage), m_folder(std::move(path)) +ScreenshotsPage::ScreenshotsPage(QString path, QWidget* parent) : QMainWindow(parent), ui(new Ui::ScreenshotsPage) { - m_model = std::make_shared(); - m_filterModel = std::make_shared(); + m_model.reset(new ScreenshotsFSModel()); + m_filterModel.reset(new FilterModel()); m_filterModel->setSourceModel(m_model.get()); m_model->setFilter(QDir::Files); m_model->setReadOnly(false); @@ -275,6 +266,7 @@ ScreenshotsPage::ScreenshotsPage(QString path, QWidget* parent) constexpr int file_modified_column_index = 3; m_model->sort(file_modified_column_index, Qt::DescendingOrder); + m_folder = path; m_valid = FS::ensureFolderPathExists(m_folder); ui->setupUi(this); @@ -291,19 +283,18 @@ ScreenshotsPage::ScreenshotsPage(QString path, QWidget* parent) ui->listView->setEditTriggers(QAbstractItemView::NoEditTriggers); ui->listView->setItemDelegate(new CenteredEditingDelegate(this)); ui->listView->setContextMenuPolicy(Qt::CustomContextMenu); - connect(ui->listView, &QListView::customContextMenuRequested, this, &ScreenshotsPage::showContextMenu); + connect(ui->listView, &QListView::customContextMenuRequested, this, &ScreenshotsPage::ShowContextMenu); connect(ui->listView, &QAbstractItemView::activated, this, &ScreenshotsPage::onItemActivated); } bool ScreenshotsPage::eventFilter(QObject* obj, QEvent* evt) { - if (obj != ui->listView) { + if (obj != ui->listView) return QWidget::eventFilter(obj, evt); - } if (evt->type() != QEvent::KeyPress) { return QWidget::eventFilter(obj, evt); } - const auto* keyEvent = static_cast(evt); + QKeyEvent* keyEvent = static_cast(evt); if (keyEvent->matches(QKeySequence::Copy)) { on_actionCopy_File_s_triggered(); @@ -333,11 +324,11 @@ ScreenshotsPage::~ScreenshotsPage() delete ui; } -void ScreenshotsPage::showContextMenu(const QPoint& pos) +void ScreenshotsPage::ShowContextMenu(const QPoint& pos) { - auto* menu = ui->toolBar->createContextMenu(this, tr("Context menu")); + auto menu = ui->toolBar->createContextMenu(this, tr("Context menu")); - if (ui->listView->selectionModel()->selectedIndexes().size() > 1) { + if (ui->listView->selectionModel()->selectedRows().size() > 1) { menu->removeAction(ui->actionCopy_Image); } @@ -352,75 +343,66 @@ QMenu* ScreenshotsPage::createPopupMenu() return filteredMenu; } -void ScreenshotsPage::onItemActivated(QModelIndex index) const +void ScreenshotsPage::onItemActivated(QModelIndex index) { - if (!index.isValid()) { + if (!index.isValid()) return; - } - const auto info = m_model->fileInfo(index); + auto info = m_model->fileInfo(index); DesktopServices::openPath(info); } -void ScreenshotsPage::onCurrentSelectionChanged(const QItemSelection& /*selected*/) const +void ScreenshotsPage::onCurrentSelectionChanged(const QItemSelection& selected) { - const auto selected = ui->listView->selectionModel()->selectedIndexes(); - bool allReadable = !selected.isEmpty(); bool allWritable = !selected.isEmpty(); - for (auto index : selected) { - if (!index.isValid()) { + for (auto index : selected.indexes()) { + if (!index.isValid()) break; - } auto info = m_model->fileInfo(index); - if (!info.isReadable()) { + if (!info.isReadable()) allReadable = false; - } - if (!info.isWritable()) { + if (!info.isWritable()) allWritable = false; - } } ui->actionUpload->setEnabled(allReadable); - ui->actionCopy_Image->setEnabled(allReadable && selected.size() == 1); + ui->actionCopy_Image->setEnabled(allReadable); ui->actionCopy_File_s->setEnabled(allReadable); ui->actionDelete->setEnabled(allWritable); ui->actionRename->setEnabled(allWritable); } -void ScreenshotsPage::on_actionView_Folder_triggered() const +void ScreenshotsPage::on_actionView_Folder_triggered() { DesktopServices::openPath(m_folder, true); } void ScreenshotsPage::on_actionUpload_triggered() { - auto selection = ui->listView->selectionModel()->selectedIndexes(); - if (selection.isEmpty()) { + auto selection = ui->listView->selectionModel()->selectedRows(); + if (selection.isEmpty()) return; - } QString text; - const QUrl baseUrl(BuildConfig.IMGUR_BASE_URL); - if (selection.size() > 1) { + QUrl baseUrl(BuildConfig.IMGUR_BASE_URL); + if (selection.size() > 1) text = tr("You are about to upload %1 screenshots to %2.\n" "You should double-check for personal information.\n\n" "Are you sure?") .arg(QString::number(selection.size()), baseUrl.host()); - } else { + else text = tr("You are about to upload the selected screenshot to %1.\n" "You should double-check for personal information.\n\n" "Are you sure?") .arg(baseUrl.host()); - } auto response = CustomMessageBox::selectable(this, "Confirm Upload", text, QMessageBox::Warning, QMessageBox::Yes | QMessageBox::No, QMessageBox::No) ->exec(); - if (response != QMessageBox::Yes) { + if (response != QMessageBox::Yes) return; - } QList uploaded; auto job = NetJob::Ptr(new NetJob("Screenshot Upload", APPLICATION->network())); @@ -434,7 +416,7 @@ void ScreenshotsPage::on_actionUpload_triggered() auto screenshot = std::make_shared(info); job->addNetAction(ImgurUpload::make(screenshot)); - connect(job.get(), &Task::failed, [this](const QString& reason) { + connect(job.get(), &Task::failed, [this](QString reason) { CustomMessageBox::selectable(this, tr("Failed to upload screenshots!"), reason, QMessageBox::Critical)->show(); }); connect(job.get(), &Task::aborted, [this] { @@ -475,7 +457,7 @@ void ScreenshotsPage::on_actionUpload_triggered() task.addTask(job); task.addTask(albumTask); - connect(&task, &Task::failed, [this](const QString& reason) { + connect(&task, &Task::failed, [this](QString reason) { CustomMessageBox::selectable(this, tr("Failed to upload screenshots!"), reason, QMessageBox::Critical)->show(); }); connect(&task, &Task::aborted, [this] { @@ -503,24 +485,24 @@ void ScreenshotsPage::on_actionUpload_triggered() m_uploadActive = false; } -void ScreenshotsPage::on_actionCopy_Image_triggered() const +void ScreenshotsPage::on_actionCopy_Image_triggered() { - auto selection = ui->listView->selectionModel()->selectedIndexes(); + auto selection = ui->listView->selectionModel()->selectedRows(); if (selection.size() < 1) { return; } // You can only copy one image to the clipboard. In the case of multiple selected files, only the first one gets copied. - const auto item = selection.first(); - const auto info = m_model->fileInfo(item); - const QImage image(info.absoluteFilePath()); + auto item = selection[0]; + auto info = m_model->fileInfo(item); + QImage image(info.absoluteFilePath()); Q_ASSERT(!image.isNull()); QApplication::clipboard()->setImage(image, QClipboard::Clipboard); } -void ScreenshotsPage::on_actionCopy_File_s_triggered() const +void ScreenshotsPage::on_actionCopy_File_s_triggered() { - auto selection = ui->listView->selectionModel()->selectedIndexes(); + auto selection = ui->listView->selectionModel()->selectedRows(); if (selection.size() < 1) { // Don't do anything so we don't empty the users clipboard return; @@ -531,7 +513,7 @@ void ScreenshotsPage::on_actionCopy_File_s_triggered() const auto info = m_model->fileInfo(item); buf += "file:///" + info.absoluteFilePath() + "\r\n"; } - auto* mimeData = new QMimeData(); + QMimeData* mimeData = new QMimeData(); mimeData->setData("text/uri-list", buf.toLocal8Bit()); QApplication::clipboard()->setMimeData(mimeData); } @@ -540,43 +522,39 @@ void ScreenshotsPage::on_actionDelete_triggered() { auto selected = ui->listView->selectionModel()->selectedIndexes(); - const qsizetype count = selected.size(); + int count = ui->listView->selectionModel()->selectedRows().size(); QString text; - if (count > 1) { + if (count > 1) text = tr("You are about to delete %1 screenshots.\n" "This may be permanent and they will be gone from the folder.\n\n" "Are you sure?") .arg(count); - } else { - text = - tr("You are about to delete the selected screenshot.\n" - "This may be permanent and it will be gone from the folder.\n\n" - "Are you sure?"); - } + else + text = tr("You are about to delete the selected screenshot.\n" + "This may be permanent and it will be gone from the folder.\n\n" + "Are you sure?") + .arg(count); - const auto response = + auto response = CustomMessageBox::selectable(this, tr("Confirm Deletion"), text, QMessageBox::Warning, QMessageBox::Yes | QMessageBox::No)->exec(); - if (response != QMessageBox::Yes) { + if (response != QMessageBox::Yes) return; - } for (auto item : selected) { - if (FS::trash(m_model->filePath(item))) { + if (FS::trash(m_model->filePath(item))) continue; - } m_model->remove(item); } } -void ScreenshotsPage::on_actionRename_triggered() const +void ScreenshotsPage::on_actionRename_triggered() { auto selection = ui->listView->selectionModel()->selectedIndexes(); - if (selection.isEmpty()) { + if (selection.isEmpty()) return; - } - ui->listView->edit(selection.first()); + ui->listView->edit(selection[0]); // TODO: mass renaming } @@ -586,8 +564,8 @@ void ScreenshotsPage::openedImpl() m_valid = FS::ensureFolderPathExists(m_folder); } if (m_valid) { - const QString path = QDir(m_folder).absolutePath(); - const auto idx = m_model->setRootPath(path); + QString path = QDir(m_folder).absolutePath(); + auto idx = m_model->setRootPath(path); if (idx.isValid()) { ui->listView->setModel(m_filterModel.get()); connect(ui->listView->selectionModel(), &QItemSelectionModel::selectionChanged, this, @@ -599,7 +577,7 @@ void ScreenshotsPage::openedImpl() } } - const auto setting_name = QString("WideBarVisibility_%1").arg(id()); + auto const setting_name = QString("WideBarVisibility_%1").arg(id()); m_wide_bar_setting = APPLICATION->settings()->getOrRegisterSetting(setting_name); ui->toolBar->setVisibilityState(QByteArray::fromBase64(m_wide_bar_setting->get().toString().toUtf8())); diff --git a/launcher/ui/pages/instance/ScreenshotsPage.h b/launcher/ui/pages/instance/ScreenshotsPage.h index 7d1cf4fcc..0b068aa0a 100644 --- a/launcher/ui/pages/instance/ScreenshotsPage.h +++ b/launcher/ui/pages/instance/ScreenshotsPage.h @@ -78,14 +78,14 @@ class ScreenshotsPage : public QMainWindow, public BasePage { private slots: void on_actionUpload_triggered(); - void on_actionCopy_Image_triggered() const; - void on_actionCopy_File_s_triggered() const; + void on_actionCopy_Image_triggered(); + void on_actionCopy_File_s_triggered(); void on_actionDelete_triggered(); - void on_actionRename_triggered() const; - void on_actionView_Folder_triggered() const; - void onItemActivated(QModelIndex) const; - void onCurrentSelectionChanged(const QItemSelection& selected) const; - void showContextMenu(const QPoint& pos); + void on_actionRename_triggered(); + void on_actionView_Folder_triggered(); + void onItemActivated(QModelIndex); + void onCurrentSelectionChanged(const QItemSelection& selected); + void ShowContextMenu(const QPoint& pos); private: Ui::ScreenshotsPage* ui; diff --git a/launcher/ui/pages/instance/ShaderPackPage.cpp b/launcher/ui/pages/instance/ShaderPackPage.cpp index a29564abc..3120d9013 100644 --- a/launcher/ui/pages/instance/ShaderPackPage.cpp +++ b/launcher/ui/pages/instance/ShaderPackPage.cpp @@ -61,9 +61,9 @@ ShaderPackPage::ShaderPackPage(MinecraftInstance* instance, ShaderPackFolderMode connect(ui->actionUpdateItem, &QAction::triggered, this, &ShaderPackPage::updateShaderPacks); ui->actionsToolbar->insertActionBefore(ui->actionAddItem, ui->actionUpdateItem); - auto* updateMenu = new QMenu(this); + auto updateMenu = new QMenu(this); - auto* update = updateMenu->addAction(ui->actionUpdateItem->text()); + auto update = updateMenu->addAction(ui->actionUpdateItem->text()); connect(update, &QAction::triggered, this, &ShaderPackPage::updateShaderPacks); updateMenu->addAction(ui->actionResetItemMetadata); @@ -78,9 +78,8 @@ ShaderPackPage::ShaderPackPage(MinecraftInstance* instance, ShaderPackFolderMode void ShaderPackPage::downloadShaderPack() { - if (m_instance->typeName() != "Minecraft") { + if (m_instance->typeName() != "Minecraft") return; // this is a null instance or a legacy instance - } m_downloadDialog = new ResourceDownload::ShaderPackDownloadDialog(this, m_model, m_instance); connect(this, &QObject::destroyed, m_downloadDialog, &QDialog::close); @@ -91,9 +90,9 @@ void ShaderPackPage::downloadShaderPack() void ShaderPackPage::downloadDialogFinished(int result) { - if (result != 0) { - auto* tasks = new ConcurrentTask("Download Shader Packs", APPLICATION->settings()->get("NumberOfConcurrentDownloads").toInt()); - connect(tasks, &Task::failed, [this, tasks](const QString& reason) { + if (result) { + auto tasks = new ConcurrentTask("Download Shader Packs", APPLICATION->settings()->get("NumberOfConcurrentDownloads").toInt()); + connect(tasks, &Task::failed, [this, tasks](QString reason) { CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->show(); tasks->deleteLater(); }); @@ -103,9 +102,8 @@ void ShaderPackPage::downloadDialogFinished(int result) }); connect(tasks, &Task::succeeded, [this, tasks]() { QStringList warnings = tasks->warnings(); - if (warnings.count()) { + if (warnings.count()) CustomMessageBox::selectable(this, tr("Warnings"), warnings.join('\n'), QMessageBox::Warning)->show(); - } tasks->deleteLater(); }); @@ -124,16 +122,14 @@ void ShaderPackPage::downloadDialogFinished(int result) m_model->update(); } - if (m_downloadDialog) { + if (m_downloadDialog) m_downloadDialog->deleteLater(); - } } void ShaderPackPage::updateShaderPacks() { - if (m_instance->typeName() != "Minecraft") { + if (m_instance->typeName() != "Minecraft") return; // this is a null instance or a legacy instance - } if (APPLICATION->settings()->get("ModMetadataDisabled").toBool()) { QMessageBox::critical(this, tr("Error"), tr("Shader pack updates are unavailable when metadata is disabled!")); @@ -148,29 +144,27 @@ void ShaderPackPage::updateShaderPacks() QMessageBox::Warning, QMessageBox::Yes | QMessageBox::No, QMessageBox::No) ->exec(); - if (response != QMessageBox::Yes) { + if (response != QMessageBox::Yes) return; - } } auto selection = m_filterModel->mapSelectionToSource(ui->treeView->selectionModel()->selection()).indexes(); - auto modsList = m_model->selectedResources(selection); - bool useAll = modsList.empty(); - if (useAll) { - modsList = m_model->allResources(); - } + auto mods_list = m_model->selectedResources(selection); + bool use_all = mods_list.empty(); + if (use_all) + mods_list = m_model->allResources(); - ResourceUpdateDialog updateDialog(this, m_instance, m_model, modsList, false); - updateDialog.checkCandidates(); + ResourceUpdateDialog update_dialog(this, m_instance, m_model, mods_list, false); + update_dialog.checkCandidates(); - if (updateDialog.aborted()) { + if (update_dialog.aborted()) { CustomMessageBox::selectable(this, tr("Aborted"), tr("The shader pack updater was aborted!"), QMessageBox::Warning)->show(); return; } - if (updateDialog.noUpdates()) { - QString message{ tr("'%1' is up-to-date! :)").arg(modsList.front()->name()) }; - if (modsList.size() > 1) { - if (useAll) { + if (update_dialog.noUpdates()) { + QString message{ tr("'%1' is up-to-date! :)").arg(mods_list.front()->name()) }; + if (mods_list.size() > 1) { + if (use_all) { message = tr("All shader packs are up-to-date! :)"); } else { message = tr("All selected shader packs are up-to-date! :)"); @@ -180,9 +174,9 @@ void ShaderPackPage::updateShaderPacks() return; } - if (updateDialog.exec() != 0) { - auto* tasks = new ConcurrentTask("Download Shader Packs", APPLICATION->settings()->get("NumberOfConcurrentDownloads").toInt()); - connect(tasks, &Task::failed, [this, tasks](const QString& reason) { + if (update_dialog.exec()) { + auto tasks = new ConcurrentTask("Download Shader Packs", APPLICATION->settings()->get("NumberOfConcurrentDownloads").toInt()); + connect(tasks, &Task::failed, [this, tasks](QString reason) { CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->show(); tasks->deleteLater(); }); @@ -198,7 +192,7 @@ void ShaderPackPage::updateShaderPacks() tasks->deleteLater(); }); - for (const auto& task : updateDialog.getTasks()) { + for (auto task : update_dialog.getTasks()) { tasks->addTask(task); } @@ -214,9 +208,8 @@ void ShaderPackPage::deleteShaderPackMetadata() { auto selection = m_filterModel->mapSelectionToSource(ui->treeView->selectionModel()->selection()).indexes(); auto selectionCount = m_model->selectedShaderPacks(selection).length(); - if (selectionCount == 0) { + if (selectionCount == 0) return; - } if (selectionCount > 1) { auto response = CustomMessageBox::selectable(this, tr("Confirm Removal"), tr("You are about to remove the metadata for %1 shader packs.\n" @@ -225,9 +218,8 @@ void ShaderPackPage::deleteShaderPackMetadata() QMessageBox::Warning, QMessageBox::Yes | QMessageBox::No, QMessageBox::No) ->exec(); - if (response != QMessageBox::Yes) { + if (response != QMessageBox::Yes) return; - } } m_model->deleteMetadata(selection); @@ -235,9 +227,8 @@ void ShaderPackPage::deleteShaderPackMetadata() void ShaderPackPage::changeShaderPackVersion() { - if (m_instance->typeName() != "Minecraft") { + if (m_instance->typeName() != "Minecraft") return; // this is a null instance or a legacy instance - } if (APPLICATION->settings()->get("ModMetadataDisabled").toBool()) { QMessageBox::critical(this, tr("Error"), tr("Shader pack updates are unavailable when metadata is disabled!")); @@ -246,17 +237,15 @@ void ShaderPackPage::changeShaderPackVersion() const QModelIndexList rows = ui->treeView->selectionModel()->selectedRows(); - if (rows.count() != 1) { + if (rows.count() != 1) return; - } Resource& resource = m_model->at(m_filterModel->mapToSource(rows[0]).row()); - if (resource.metadata() == nullptr) { + if (resource.metadata() == nullptr) return; - } - m_downloadDialog = new ResourceDownload::ShaderPackDownloadDialog(this, m_model, m_instance, true); + m_downloadDialog = new ResourceDownload::ShaderPackDownloadDialog(this, m_model, m_instance); connect(this, &QObject::destroyed, m_downloadDialog, &QDialog::close); connect(m_downloadDialog, &QDialog::finished, this, &ShaderPackPage::downloadDialogFinished); diff --git a/launcher/ui/pages/instance/TexturePackPage.cpp b/launcher/ui/pages/instance/TexturePackPage.cpp index 01325e3f6..ec0486fe4 100644 --- a/launcher/ui/pages/instance/TexturePackPage.cpp +++ b/launcher/ui/pages/instance/TexturePackPage.cpp @@ -60,9 +60,9 @@ TexturePackPage::TexturePackPage(MinecraftInstance* instance, TexturePackFolderM connect(ui->actionUpdateItem, &QAction::triggered, this, &TexturePackPage::updateTexturePacks); ui->actionsToolbar->insertActionBefore(ui->actionAddItem, ui->actionUpdateItem); - auto* updateMenu = new QMenu(this); + auto updateMenu = new QMenu(this); - auto* update = updateMenu->addAction(ui->actionUpdateItem->text()); + auto update = updateMenu->addAction(ui->actionUpdateItem->text()); connect(update, &QAction::triggered, this, &TexturePackPage::updateTexturePacks); updateMenu->addAction(ui->actionResetItemMetadata); @@ -81,15 +81,14 @@ void TexturePackPage::updateFrame(const QModelIndex& current, [[maybe_unused]] c { auto sourceCurrent = m_filterModel->mapToSource(current); int row = sourceCurrent.row(); - auto& rp = m_model->at(row); + auto& rp = static_cast(m_model->at(row)); ui->frame->updateWithTexturePack(rp); } void TexturePackPage::downloadTexturePacks() { - if (m_instance->typeName() != "Minecraft") { + if (m_instance->typeName() != "Minecraft") return; // this is a null instance or a legacy instance - } m_downloadDialog = new ResourceDownload::TexturePackDownloadDialog(this, m_model, m_instance); connect(this, &QObject::destroyed, m_downloadDialog, &QDialog::close); @@ -99,9 +98,9 @@ void TexturePackPage::downloadTexturePacks() void TexturePackPage::downloadDialogFinished(int result) { - if (result != 0) { - auto* tasks = new ConcurrentTask("Download Texture Packs", APPLICATION->settings()->get("NumberOfConcurrentDownloads").toInt()); - connect(tasks, &Task::failed, [this, tasks](const QString& reason) { + if (result) { + auto tasks = new ConcurrentTask("Download Texture Packs", APPLICATION->settings()->get("NumberOfConcurrentDownloads").toInt()); + connect(tasks, &Task::failed, [this, tasks](QString reason) { CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->show(); tasks->deleteLater(); }); @@ -111,9 +110,8 @@ void TexturePackPage::downloadDialogFinished(int result) }); connect(tasks, &Task::succeeded, [this, tasks]() { QStringList warnings = tasks->warnings(); - if (warnings.count()) { + if (warnings.count()) CustomMessageBox::selectable(this, tr("Warnings"), warnings.join('\n'), QMessageBox::Warning)->show(); - } tasks->deleteLater(); }); @@ -132,16 +130,14 @@ void TexturePackPage::downloadDialogFinished(int result) m_model->update(); } - if (m_downloadDialog) { + if (m_downloadDialog) m_downloadDialog->deleteLater(); - } } void TexturePackPage::updateTexturePacks() { - if (m_instance->typeName() != "Minecraft") { + if (m_instance->typeName() != "Minecraft") return; // this is a null instance or a legacy instance - } if (APPLICATION->settings()->get("ModMetadataDisabled").toBool()) { QMessageBox::critical(this, tr("Error"), tr("Texture pack updates are unavailable when metadata is disabled!")); @@ -156,29 +152,27 @@ void TexturePackPage::updateTexturePacks() QMessageBox::Warning, QMessageBox::Yes | QMessageBox::No, QMessageBox::No) ->exec(); - if (response != QMessageBox::Yes) { + if (response != QMessageBox::Yes) return; - } } auto selection = m_filterModel->mapSelectionToSource(ui->treeView->selectionModel()->selection()).indexes(); - auto modsList = m_model->selectedResources(selection); - bool useAll = modsList.empty(); - if (useAll) { - modsList = m_model->allResources(); - } + auto mods_list = m_model->selectedResources(selection); + bool use_all = mods_list.empty(); + if (use_all) + mods_list = m_model->allResources(); - ResourceUpdateDialog updateDialog(this, m_instance, m_model, modsList, false); - updateDialog.checkCandidates(); + ResourceUpdateDialog update_dialog(this, m_instance, m_model, mods_list, false); + update_dialog.checkCandidates(); - if (updateDialog.aborted()) { + if (update_dialog.aborted()) { CustomMessageBox::selectable(this, tr("Aborted"), tr("The texture pack updater was aborted!"), QMessageBox::Warning)->show(); return; } - if (updateDialog.noUpdates()) { - QString message{ tr("'%1' is up-to-date! :)").arg(modsList.front()->name()) }; - if (modsList.size() > 1) { - if (useAll) { + if (update_dialog.noUpdates()) { + QString message{ tr("'%1' is up-to-date! :)").arg(mods_list.front()->name()) }; + if (mods_list.size() > 1) { + if (use_all) { message = tr("All texture packs are up-to-date! :)"); } else { message = tr("All selected texture packs are up-to-date! :)"); @@ -188,9 +182,9 @@ void TexturePackPage::updateTexturePacks() return; } - if (updateDialog.exec() != 0) { - auto* tasks = new ConcurrentTask("Download Texture Packs", APPLICATION->settings()->get("NumberOfConcurrentDownloads").toInt()); - connect(tasks, &Task::failed, [this, tasks](const QString& reason) { + if (update_dialog.exec()) { + auto tasks = new ConcurrentTask("Download Texture Packs", APPLICATION->settings()->get("NumberOfConcurrentDownloads").toInt()); + connect(tasks, &Task::failed, [this, tasks](QString reason) { CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->show(); tasks->deleteLater(); }); @@ -206,7 +200,7 @@ void TexturePackPage::updateTexturePacks() tasks->deleteLater(); }); - for (const auto& task : updateDialog.getTasks()) { + for (auto task : update_dialog.getTasks()) { tasks->addTask(task); } @@ -222,9 +216,8 @@ void TexturePackPage::deleteTexturePackMetadata() { auto selection = m_filterModel->mapSelectionToSource(ui->treeView->selectionModel()->selection()).indexes(); auto selectionCount = m_model->selectedTexturePacks(selection).length(); - if (selectionCount == 0) { + if (selectionCount == 0) return; - } if (selectionCount > 1) { auto response = CustomMessageBox::selectable(this, tr("Confirm Removal"), tr("You are about to remove the metadata for %1 texture packs.\n" @@ -233,9 +226,8 @@ void TexturePackPage::deleteTexturePackMetadata() QMessageBox::Warning, QMessageBox::Yes | QMessageBox::No, QMessageBox::No) ->exec(); - if (response != QMessageBox::Yes) { + if (response != QMessageBox::Yes) return; - } } m_model->deleteMetadata(selection); @@ -243,9 +235,8 @@ void TexturePackPage::deleteTexturePackMetadata() void TexturePackPage::changeTexturePackVersion() { - if (m_instance->typeName() != "Minecraft") { + if (m_instance->typeName() != "Minecraft") return; // this is a null instance or a legacy instance - } if (APPLICATION->settings()->get("ModMetadataDisabled").toBool()) { QMessageBox::critical(this, tr("Error"), tr("Texture pack updates are unavailable when metadata is disabled!")); @@ -254,17 +245,15 @@ void TexturePackPage::changeTexturePackVersion() const QModelIndexList rows = ui->treeView->selectionModel()->selectedRows(); - if (rows.count() != 1) { + if (rows.count() != 1) return; - } Resource& resource = m_model->at(m_filterModel->mapToSource(rows[0]).row()); - if (resource.metadata() == nullptr) { + if (resource.metadata() == nullptr) return; - } - m_downloadDialog = new ResourceDownload::TexturePackDownloadDialog(this, m_model, m_instance, true); + m_downloadDialog = new ResourceDownload::TexturePackDownloadDialog(this, m_model, m_instance); connect(this, &QObject::destroyed, m_downloadDialog, &QDialog::close); connect(m_downloadDialog, &QDialog::finished, this, &TexturePackPage::downloadDialogFinished); diff --git a/launcher/ui/pages/instance/WorldListPage.cpp b/launcher/ui/pages/instance/WorldListPage.cpp index 71c370ab2..e56e9c731 100644 --- a/launcher/ui/pages/instance/WorldListPage.cpp +++ b/launcher/ui/pages/instance/WorldListPage.cpp @@ -121,7 +121,7 @@ void WorldListPage::openedImpl() ui->toolBar->removeAction(ui->actionJoin); } - const auto setting_name = QString("WideBarVisibility_%1").arg(id()); + auto const setting_name = QString("WideBarVisibility_%1").arg(id()); m_wide_bar_setting = APPLICATION->settings()->getOrRegisterSetting(setting_name); ui->toolBar->setVisibilityState(QByteArray::fromBase64(m_wide_bar_setting->get().toString().toUtf8())); @@ -259,12 +259,9 @@ void WorldListPage::on_actionData_Packs_triggered() dialog->setLayout(layout); - dialog->setAttribute(Qt::WA_DeleteOnClose); + dialog->exec(); - connect(dialog, &QDialog::finished, this, - [dialog]() { APPLICATION->settings()->set("DataPackDownloadGeometry", dialog->saveGeometry().toBase64()); }); - - dialog->open(); + APPLICATION->settings()->set("DataPackDownloadGeometry", dialog->saveGeometry().toBase64()); } void WorldListPage::on_actionReset_Icon_triggered() diff --git a/launcher/ui/pages/modplatform/CustomPage.cpp b/launcher/ui/pages/modplatform/CustomPage.cpp index f24abf9fb..87e126fd7 100644 --- a/launcher/ui/pages/modplatform/CustomPage.cpp +++ b/launcher/ui/pages/modplatform/CustomPage.cpp @@ -80,14 +80,14 @@ void CustomPage::openedImpl() void CustomPage::refresh() { - ui->versionList->loadList(true); + ui->versionList->loadList(); } void CustomPage::loaderRefresh() { if (ui->noneFilter->isChecked()) return; - ui->loaderVersionList->loadList(true); + ui->loaderVersionList->loadList(); } void CustomPage::filterChanged() diff --git a/launcher/ui/pages/modplatform/ModPage.cpp b/launcher/ui/pages/modplatform/ModPage.cpp index 1cdce5e33..706d35378 100644 --- a/launcher/ui/pages/modplatform/ModPage.cpp +++ b/launcher/ui/pages/modplatform/ModPage.cpp @@ -50,6 +50,7 @@ #include "ResourceDownloadTask.h" #include "minecraft/MinecraftInstance.h" +#include "minecraft/PackProfile.h" #include "ui/dialogs/ResourceDownloadDialog.h" @@ -62,14 +63,14 @@ ModPage::ModPage(ModDownloadDialog* dialog, BaseInstance& instance) : ResourcePa void ModPage::setFilterWidget(std::unique_ptr& widget) { - if (m_filter_widget) { + if (m_filter_widget) disconnect(m_filter_widget.get(), nullptr, nullptr, nullptr); - } - auto* old = m_ui->splitter->replaceWidget(0, widget.get()); + auto old = m_ui->splitter->replaceWidget(0, widget.get()); // because we replaced the widget we also need to delete it - - delete old; + if (old) { + delete old; + } m_filter_widget.swap(widget); @@ -111,13 +112,10 @@ QMap ModPage::urlHandlers() const /******** Make changes to the UI ********/ -void ModPage::addResourceToPage(ModPlatform::IndexedPack::Ptr pack, - ModPlatform::IndexedVersion& version, - ResourceFolderModel* baseModel, - QString downloadReason) +void ModPage::addResourceToPage(ModPlatform::IndexedPack::Ptr pack, ModPlatform::IndexedVersion& version, ResourceFolderModel* base_model) { - bool isIndexed = !APPLICATION->settings()->get("ModMetadataDisabled").toBool(); - m_model->addPack(pack, version, baseModel, isIndexed, downloadReason); + bool is_indexed = !APPLICATION->settings()->get("ModMetadataDisabled").toBool(); + m_model->addPack(pack, version, base_model, is_indexed); } } // namespace ResourceDownload diff --git a/launcher/ui/pages/modplatform/ModPage.h b/launcher/ui/pages/modplatform/ModPage.h index 7f75995a3..a69ee53f7 100644 --- a/launcher/ui/pages/modplatform/ModPage.h +++ b/launcher/ui/pages/modplatform/ModPage.h @@ -29,10 +29,10 @@ class ModPage : public ResourcePage { static T* create(ModDownloadDialog* dialog, BaseInstance& instance) { auto page = new T(dialog, instance); - auto* model = static_cast(page->getModel()); + auto model = static_cast(page->getModel()); - auto filterWidget = page->createFilterWidget(); - page->setFilterWidget(filterWidget); + auto filter_widget = page->createFilterWidget(); + page->setFilterWidget(filter_widget); model->setFilter(page->getFilter()); connect(model, &ResourceModel::versionListUpdated, page, &ResourcePage::versionListUpdated); @@ -43,21 +43,18 @@ class ModPage : public ResourcePage { } //: The plural version of 'mod' - QString resourcesString() const override { return tr("mods"); } + inline QString resourcesString() const override { return tr("mods"); } //: The singular version of 'mods' - QString resourceString() const override { return tr("mod"); } + inline QString resourceString() const override { return tr("mod"); } QMap urlHandlers() const override; - void addResourceToPage(ModPlatform::IndexedPack::Ptr /*unused*/, - ModPlatform::IndexedVersion& /*unused*/, - ResourceFolderModel* /*unused*/, - QString downloadReason = "standalone") override; + void addResourceToPage(ModPlatform::IndexedPack::Ptr, ModPlatform::IndexedVersion&, ResourceFolderModel*) override; virtual std::unique_ptr createFilterWidget() = 0; bool supportsFiltering() const override { return true; }; - auto getFilter() const -> std::shared_ptr { return m_filter; } + auto getFilter() const -> const std::shared_ptr { return m_filter; } void setFilterWidget(std::unique_ptr&); protected: diff --git a/launcher/ui/pages/modplatform/ResourceModel.cpp b/launcher/ui/pages/modplatform/ResourceModel.cpp index edd8564b6..e90eafbf2 100644 --- a/launcher/ui/pages/modplatform/ResourceModel.cpp +++ b/launcher/ui/pages/modplatform/ResourceModel.cpp @@ -12,11 +12,10 @@ #include #include #include -#include #include "Application.h" -#include "BuildConfig.h" #include "settings/SettingsObject.h" +#include "BuildConfig.h" #include "modplatform/ResourceAPI.h" #include "net/ApiDownload.h" @@ -30,7 +29,7 @@ namespace ResourceDownload { QHash ResourceModel::s_running_models; -ResourceModel::ResourceModel(ResourceAPI* api) : m_api(api) +ResourceModel::ResourceModel(ResourceAPI* api) : QAbstractListModel(), m_api(api) { s_running_models.insert(this, true); if (APPLICATION_DYN) { @@ -63,14 +62,14 @@ auto ResourceModel::data(const QModelIndex& index, int role) const -> QVariant } case Qt::DecorationRole: { if (APPLICATION_DYN) { - if (auto iconOrNone = const_cast(this)->getIcon(const_cast(index), pack->logoUrl); - iconOrNone.has_value()) { - return iconOrNone.value(); - } + if (auto icon_or_none = const_cast(this)->getIcon(const_cast(index), pack->logoUrl); + icon_or_none.has_value()) + return icon_or_none.value(); return QIcon::fromTheme("screenshot-placeholder"); + } else { + return {}; } - return {}; } case Qt::SizeHintRole: return QSize(0, 58); @@ -113,9 +112,8 @@ QHash ResourceModel::roleNames() const bool ResourceModel::setData(const QModelIndex& index, const QVariant& value, [[maybe_unused]] int role) { int pos = index.row(); - if (pos >= m_packs.size() || pos < 0 || !index.isValid()) { + if (pos >= m_packs.size() || pos < 0 || !index.isValid()) return false; - } m_packs[pos] = value.value(); emit dataChanged(index, index); @@ -130,51 +128,42 @@ QString ResourceModel::debugName() const void ResourceModel::fetchMore(const QModelIndex& parent) { - if (parent.isValid() || m_search_state == SearchState::Finished) { + if (parent.isValid() || m_search_state == SearchState::Finished) return; - } search(); } void ResourceModel::search() { - if (hasActiveSearchJob()) { + if (hasActiveSearchJob()) return; - } - if (m_search_state != SearchState::ResetRequested && m_search_term.startsWith("#")) { + if (m_search_term.startsWith("#")) { auto projectId = m_search_term.mid(1); if (!projectId.isEmpty()) { ResourceAPI::Callback callbacks; - callbacks.on_fail = [this](QString reason, int networkErrorCode) { - if (!s_running_models.constFind(this).value()) { + callbacks.on_fail = [this](QString reason, int) { + if (!s_running_models.constFind(this).value()) return; - } - if (networkErrorCode == 404) { - m_search_state = SearchState::ResetRequested; - } - searchRequestFailed(std::move(reason), networkErrorCode); + searchRequestFailed(reason, -1); }; callbacks.on_abort = [this] { - if (!s_running_models.constFind(this).value()) { + if (!s_running_models.constFind(this).value()) return; - } searchRequestAborted(); }; callbacks.on_succeed = [this](auto& pack) { - if (!s_running_models.constFind(this).value()) { + if (!s_running_models.constFind(this).value()) return; - } searchRequestForOneSucceeded(pack); }; auto project = std::make_shared(); project->addonId = projectId; - if (auto job = m_api->getProjectInfo({ project }, std::move(callbacks), false); job) { + if (auto job = m_api->getProjectInfo({ project }, std::move(callbacks)); job) runSearchJob(job); - } return; } } @@ -183,36 +172,31 @@ void ResourceModel::search() ResourceAPI::Callback> callbacks{}; callbacks.on_succeed = [this](auto& doc) { - if (!s_running_models.constFind(this).value()) { + if (!s_running_models.constFind(this).value()) return; - } searchRequestSucceeded(doc); }; - callbacks.on_fail = [this](QString reason, int networkErrorCode) { - if (!s_running_models.constFind(this).value()) { + callbacks.on_fail = [this](QString reason, int network_error_code) { + if (!s_running_models.constFind(this).value()) return; - } - searchRequestFailed(std::move(reason), networkErrorCode); + searchRequestFailed(reason, network_error_code); }; callbacks.on_abort = [this] { - if (!s_running_models.constFind(this).value()) { + if (!s_running_models.constFind(this).value()) return; - } searchRequestAborted(); }; - if (auto job = m_api->searchProjects(std::move(args), std::move(callbacks)); job) { + if (auto job = m_api->searchProjects(std::move(args), std::move(callbacks)); job) runSearchJob(job); - } } void ResourceModel::loadEntry(const QModelIndex& entry) { - const auto& pack = m_packs[entry.row()]; + auto const& pack = m_packs[entry.row()]; - if (!hasActiveInfoJob()) { + if (!hasActiveInfoJob()) m_current_info_job.clear(); - } if (!pack->versionsLoaded) { auto args{ createVersionsArguments(entry) }; @@ -220,24 +204,20 @@ void ResourceModel::loadEntry(const QModelIndex& entry) auto addonId = pack->addonId; // Use default if no callbacks are set - if (!callbacks.on_succeed) { + if (!callbacks.on_succeed) callbacks.on_succeed = [this, entry, addonId](auto& doc) { - if (!s_running_models.constFind(this).value()) { + if (!s_running_models.constFind(this).value()) return; - } versionRequestSucceeded(doc, addonId, entry); }; - } - if (!callbacks.on_fail) { - callbacks.on_fail = [](const QString& reason, int) { + if (!callbacks.on_fail) + callbacks.on_fail = [](QString reason, int) { QMessageBox::critical(nullptr, tr("Error"), tr("A network error occurred. Could not load project versions: %1").arg(reason)); }; - } - if (auto job = m_api->getProjectVersions(std::move(args), std::move(callbacks)); job) { + if (auto job = m_api->getProjectVersions(std::move(args), std::move(callbacks)); job) runInfoJob(job); - } } if (!pack->extraDataLoaded) { @@ -245,45 +225,41 @@ void ResourceModel::loadEntry(const QModelIndex& entry) ResourceAPI::Callback callbacks{}; callbacks.on_succeed = [this, entry](auto& newpack) { - if (!s_running_models.constFind(this).value()) { + if (!s_running_models.constFind(this).value()) return; - } infoRequestSucceeded(newpack, entry); }; - callbacks.on_fail = [this](const QString& reason, int) { - if (!s_running_models.constFind(this).value()) { + callbacks.on_fail = [this](QString reason, int) { + if (!s_running_models.constFind(this).value()) return; - } QMessageBox::critical(nullptr, tr("Error"), tr("A network error occurred. Could not load project info: %1").arg(reason)); }; callbacks.on_abort = [this] { - if (!s_running_models.constFind(this).value()) { + if (!s_running_models.constFind(this).value()) return; - } qCritical() << tr("The request was aborted for an unknown reason"); }; - if (auto job = m_api->getProjectInfo(std::move(args), std::move(callbacks)); job) { + if (auto job = m_api->getProjectInfo(std::move(args), std::move(callbacks)); job) runInfoJob(job); - } } } void ResourceModel::refresh() { - bool resetRequested = false; + bool reset_requested = false; if (hasActiveInfoJob()) { m_current_info_job.abort(); - resetRequested = true; + reset_requested = true; } if (hasActiveSearchJob()) { m_current_search_job->abort(); - resetRequested = true; + reset_requested = true; } - if (resetRequested) { + if (reset_requested) { m_search_state = SearchState::ResetRequested; return; } @@ -309,15 +285,13 @@ void ResourceModel::runSearchJob(Task::Ptr ptr) } void ResourceModel::runInfoJob(Task::Ptr ptr) { - if (!m_current_info_job.isRunning()) { + if (!m_current_info_job.isRunning()) m_current_info_job.clear(); - } - m_current_info_job.addTask(std::move(ptr)); + m_current_info_job.addTask(ptr); - if (!m_current_info_job.isRunning()) { + if (!m_current_info_job.isRunning()) m_current_info_job.run(); - } } std::optional ResourceModel::getCurrentSortingMethodByIndex() const @@ -325,12 +299,11 @@ std::optional ResourceModel::getCurrentSortingMethod std::optional sort{}; { // Find sorting method by ID - auto sortingMethods = getSortingMethods(); - auto method = std::find_if(sortingMethods.constBegin(), sortingMethods.constEnd(), - [this](const auto& e) { return m_current_sort_index == e.index; }); - if (method != sortingMethods.constEnd()) { + auto sorting_methods = getSortingMethods(); + auto method = std::find_if(sorting_methods.constBegin(), sorting_methods.constEnd(), + [this](auto const& e) { return m_current_sort_index == e.index; }); + if (method != sorting_methods.constEnd()) sort = *method; - } } return sort; @@ -339,47 +312,43 @@ std::optional ResourceModel::getCurrentSortingMethod std::optional ResourceModel::getIcon(QModelIndex& index, const QUrl& url) { QPixmap pixmap; - if (QPixmapCache::find(url.toString(), &pixmap)) { + if (QPixmapCache::find(url.toString(), &pixmap)) return { pixmap }; - } if (!m_current_icon_job) { m_current_icon_job.reset(new NetJob("IconJob", APPLICATION->network())); m_current_icon_job->setAskRetry(false); } - if (m_currently_running_icon_actions.contains(url)) { + if (m_currently_running_icon_actions.contains(url)) return {}; - } - if (m_failed_icon_actions.contains(url)) { + if (m_failed_icon_actions.contains(url)) return {}; - } - auto cacheEntry = APPLICATION->metacache()->resolveEntry( + auto cache_entry = APPLICATION->metacache()->resolveEntry( metaEntryBase(), QString("logos/%1").arg(QString(QCryptographicHash::hash(url.toEncoded(), QCryptographicHash::Algorithm::Sha1).toHex()))); - auto iconFetchAction = Net::ApiDownload::makeCached(url, cacheEntry); + auto icon_fetch_action = Net::ApiDownload::makeCached(url, cache_entry); - auto fullFilePath = cacheEntry->getFullPath(); - connect(iconFetchAction.get(), &Task::succeeded, this, [this, url, fullFilePath, index] { - auto icon = QIcon(fullFilePath); + auto full_file_path = cache_entry->getFullPath(); + connect(icon_fetch_action.get(), &Task::succeeded, this, [this, url, full_file_path, index] { + auto icon = QIcon(full_file_path); QPixmapCache::insert(url.toString(), icon.pixmap(icon.actualSize({ 64, 64 }))); m_currently_running_icon_actions.remove(url); emit dataChanged(index, index, { Qt::DecorationRole }); }); - connect(iconFetchAction.get(), &Task::failed, this, [this, url] { + connect(icon_fetch_action.get(), &Task::failed, this, [this, url] { m_currently_running_icon_actions.remove(url); m_failed_icon_actions.insert(url); }); m_currently_running_icon_actions.insert(url); - m_current_icon_job->addNetAction(iconFetchAction); - if (!m_current_icon_job->isRunning()) { + m_current_icon_job->addNetAction(icon_fetch_action); + if (!m_current_icon_job->isRunning()) QMetaObject::invokeMethod(m_current_icon_job.get(), &NetJob::start); - } return {}; } @@ -391,11 +360,11 @@ void ResourceModel::searchRequestSucceeded(QList& QList filteredNewList; for (auto pack : newList) { ModPlatform::IndexedPack::Ptr p; - if (auto sel = std::ranges::find_if(m_selected, - [&pack](const DownloadTaskPtr& i) { - const auto ipack = i->getPack(); - return ipack->provider == pack->provider && ipack->addonId == pack->addonId; - }); + if (auto sel = std::find_if(m_selected.begin(), m_selected.end(), + [&pack](const DownloadTaskPtr i) { + const auto ipack = i->getPack(); + return ipack->provider == pack->provider && ipack->addonId == pack->addonId; + }); sel != m_selected.end()) { p = sel->get()->getPack(); } else { @@ -414,9 +383,8 @@ void ResourceModel::searchRequestSucceeded(QList& } // When you have a Qt build with assertions turned on, proceeding here will abort the application - if (filteredNewList.size() == 0) { + if (filteredNewList.size() == 0) return; - } beginInsertRows(QModelIndex(), m_packs.size(), m_packs.size() + filteredNewList.size() - 1); m_packs.append(filteredNewList); @@ -432,16 +400,13 @@ void ResourceModel::searchRequestForOneSucceeded(ModPlatform::IndexedPack::Ptr p endInsertRows(); } -void ResourceModel::searchRequestFailed([[maybe_unused]] QString reason, int networkErrorCode) +void ResourceModel::searchRequestFailed([[maybe_unused]] QString reason, int network_error_code) { - switch (networkErrorCode) { + switch (network_error_code) { default: // Network error QMessageBox::critical(nullptr, tr("Error"), tr("A network error occurred. Could not load mods.")); break; - case 404: - // 404 Not Found, some APIs return this when nothing is found, no need to bother the user - break; case 409: // 409 Gone, notify user to update QMessageBox::critical(nullptr, tr("Error"), @@ -449,21 +414,13 @@ void ResourceModel::searchRequestFailed([[maybe_unused]] QString reason, int net break; } - if (m_search_state == SearchState::ResetRequested) { - clearData(); - - m_next_search_offset = 0; - search(); - } else { - m_search_state = SearchState::Finished; - } + m_search_state = SearchState::Finished; } void ResourceModel::searchRequestAborted() { - if (m_search_state != SearchState::ResetRequested) { + if (m_search_state != SearchState::ResetRequested) qCritical() << "Search task in" << debugName() << "aborted by an unknown reason!"; - } // Retry fetching clearData(); @@ -474,20 +431,19 @@ void ResourceModel::searchRequestAborted() void ResourceModel::versionRequestSucceeded(QVector& doc, QVariant pack, const QModelIndex& index) { - auto currentPack = data(index, Qt::UserRole).value(); + auto current_pack = data(index, Qt::UserRole).value(); // Check if the index is still valid for this resource or not - if (pack != currentPack->addonId) { + if (pack != current_pack->addonId) return; - } - currentPack->versions = doc; - currentPack->versionsLoaded = true; + current_pack->versions = doc; + current_pack->versionsLoaded = true; // Cache info :^) - QVariant newPack; - newPack.setValue(currentPack); - if (!setData(index, newPack, Qt::UserRole)) { + QVariant new_pack; + new_pack.setValue(current_pack); + if (!setData(index, new_pack, Qt::UserRole)) { qWarning() << "Failed to cache resource versions!"; return; } @@ -497,17 +453,16 @@ void ResourceModel::versionRequestSucceeded(QVector void ResourceModel::infoRequestSucceeded(ModPlatform::IndexedPack::Ptr pack, const QModelIndex& index) { - auto currentPack = data(index, Qt::UserRole).value(); + auto current_pack = data(index, Qt::UserRole).value(); // Check if the index is still valid for this resource or not - if (pack->addonId != currentPack->addonId) { + if (pack->addonId != current_pack->addonId) return; - } // Cache info :^) - QVariant newPack; - newPack.setValue(pack); - if (!setData(index, newPack, Qt::UserRole)) { + QVariant new_pack; + new_pack.setValue(pack); + if (!setData(index, new_pack, Qt::UserRole)) { qWarning() << "Failed to cache resource info!"; return; } @@ -518,16 +473,15 @@ void ResourceModel::infoRequestSucceeded(ModPlatform::IndexedPack::Ptr pack, con void ResourceModel::addPack(ModPlatform::IndexedPack::Ptr pack, ModPlatform::IndexedVersion& version, ResourceFolderModel* packs, - bool isIndexed, - QString downloadReason) + bool is_indexed) { version.is_currently_selected = true; - m_selected.append(makeShared(std::move(pack), version, packs, isIndexed, std::move(downloadReason))); + m_selected.append(makeShared(pack, version, packs, is_indexed)); } void ResourceModel::removePack(const QString& rem) { - auto pred = [&rem](const DownloadTaskPtr& i) { return rem == i->getName(); }; + auto pred = [&rem](const DownloadTaskPtr i) { return rem == i->getName(); }; #if QT_VERSION >= QT_VERSION_CHECK(6, 1, 0) m_selected.removeIf(pred); #else @@ -539,16 +493,15 @@ void ResourceModel::removePack(const QString& rem) ++it; } #endif - auto pack = std::ranges::find_if(m_packs, [&rem](const ModPlatform::IndexedPack::Ptr& i) { return rem == i->name; }); + auto pack = std::find_if(m_packs.begin(), m_packs.end(), [&rem](const ModPlatform::IndexedPack::Ptr i) { return rem == i->name; }); if (pack == m_packs.end()) { // ignore it if is not in the current search return; } if (!pack->get()->versionsLoaded) { return; } - for (auto& ver : pack->get()->versions) { + for (auto& ver : pack->get()->versions) ver.is_currently_selected = false; - } } bool ResourceModel::checkVersionFilters(const ModPlatform::IndexedVersion& v) diff --git a/launcher/ui/pages/modplatform/ResourceModel.h b/launcher/ui/pages/modplatform/ResourceModel.h index 9124c0e66..573ad8b75 100644 --- a/launcher/ui/pages/modplatform/ResourceModel.h +++ b/launcher/ui/pages/modplatform/ResourceModel.h @@ -36,16 +36,16 @@ class ResourceModel : public QAbstractListModel { ResourceModel(ResourceAPI* api); ~ResourceModel() override; - auto data(const QModelIndex& /*index*/, int role) const -> QVariant override; + auto data(const QModelIndex&, int role) const -> QVariant override; auto roleNames() const -> QHash override; bool setData(const QModelIndex& index, const QVariant& value, int role) override; virtual auto debugName() const -> QString; virtual auto metaEntryBase() const -> QString = 0; - int rowCount(const QModelIndex& parent) const override { return parent.isValid() ? 0 : static_cast(m_packs.size()); } - int columnCount(const QModelIndex& parent) const override { return parent.isValid() ? 0 : 1; } - auto flags(const QModelIndex& index) const -> Qt::ItemFlags override { return QAbstractListModel::flags(index); } + inline int rowCount(const QModelIndex& parent) const override { return parent.isValid() ? 0 : static_cast(m_packs.size()); } + inline int columnCount(const QModelIndex& parent) const override { return parent.isValid() ? 0 : 1; } + inline auto flags(const QModelIndex& index) const -> Qt::ItemFlags override { return QAbstractListModel::flags(index); } bool hasActiveSearchJob() const { return m_current_search_job && m_current_search_job->isRunning(); } bool hasActiveInfoJob() const { return m_current_info_job.isRunning(); } @@ -66,7 +66,7 @@ class ResourceModel : public QAbstractListModel { public slots: void fetchMore(const QModelIndex& parent) override; - bool canFetchMore(const QModelIndex& parent) const override + inline bool canFetchMore(const QModelIndex& parent) const override { return parent.isValid() ? false : m_search_state == SearchState::CanFetchMore; } @@ -94,8 +94,7 @@ class ResourceModel : public QAbstractListModel { void addPack(ModPlatform::IndexedPack::Ptr pack, ModPlatform::IndexedVersion& version, ResourceFolderModel* packs, - bool isIndexed = false, - QString downloadReason = "standalone"); + bool is_indexed = false); void removePack(const QString& rem); QList selectedPacks() { return m_selected; } diff --git a/launcher/ui/pages/modplatform/ResourcePage.cpp b/launcher/ui/pages/modplatform/ResourcePage.cpp index 8baa0bbec..98aa650e0 100644 --- a/launcher/ui/pages/modplatform/ResourcePage.cpp +++ b/launcher/ui/pages/modplatform/ResourcePage.cpp @@ -39,14 +39,12 @@ #include "ResourcePage.h" #include "modplatform/ModIndex.h" +#include "ui/dialogs/CustomMessageBox.h" #include "ui_ResourcePage.h" #include #include #include -#include -#include -#include #include "Markdown.h" @@ -57,8 +55,8 @@ namespace ResourceDownload { -ResourcePage::ResourcePage(ResourceDownloadDialog* parent, BaseInstance& baseInstance) - : QWidget(parent), m_baseInstance(baseInstance), m_ui(new Ui::ResourcePage), m_parentDialog(parent), m_fetchProgress(this, false) +ResourcePage::ResourcePage(ResourceDownloadDialog* parent, BaseInstance& base_instance) + : QWidget(parent), m_baseInstance(base_instance), m_ui(new Ui::ResourcePage), m_parentDialog(parent), m_fetchProgress(this, false) { m_ui->setupUi(this); @@ -81,7 +79,7 @@ ResourcePage::ResourcePage(ResourceDownloadDialog* parent, BaseInstance& baseIns m_ui->verticalLayout->insertWidget(1, &m_fetchProgress); - auto* delegate = new ProjectItemDelegate(this); + auto delegate = new ProjectItemDelegate(this); m_ui->packView->setItemDelegate(delegate); m_ui->packView->installEventFilter(this); m_ui->packView->viewport()->installEventFilter(this); @@ -95,7 +93,8 @@ ResourcePage::ResourcePage(ResourceDownloadDialog* parent, BaseInstance& baseIns ResourcePage::~ResourcePage() { delete m_ui; - delete m_model; + if (m_model) + delete m_model; } void ResourcePage::retranslate() @@ -115,19 +114,10 @@ void ResourcePage::openedImpl() m_ui->resourceSelectionButton->setText(tr("Select %1 for download").arg(resourceString())); updateSelectionButton(); - if (!m_suppressInitialSearch) { - triggerSearch(); - } else { - m_suppressInitialSearch = false; - } + triggerSearch(); m_ui->searchEdit->setFocus(); } -void ResourcePage::setSuppressInitialSearch(bool suppress) -{ - m_suppressInitialSearch = suppress; -} - auto ResourcePage::eventFilter(QObject* watched, QEvent* event) -> bool { if (event->type() == QEvent::KeyPress) { @@ -137,13 +127,12 @@ auto ResourcePage::eventFilter(QObject* watched, QEvent* event) -> bool triggerSearch(); keyEvent->accept(); return true; - } - if (m_searchTimer.isActive()) { - m_searchTimer.stop(); - } - - m_searchTimer.start(350); + } else { + if (m_searchTimer.isActive()) + m_searchTimer.stop(); + m_searchTimer.start(350); + } } else if (watched == m_ui->packView) { // stop the event from going to the confirm button if (keyEvent->key() == Qt::Key_Return) { @@ -169,7 +158,7 @@ QString ResourcePage::getSearchTerm() const return m_ui->searchEdit->text(); } -void ResourcePage::setSearchTerm(const QString& term) +void ResourcePage::setSearchTerm(QString term) { m_ui->searchEdit->setText(term); } @@ -179,11 +168,10 @@ void ResourcePage::addSortings() Q_ASSERT(m_model); auto sorts = m_model->getSortingMethods(); - std::ranges::sort(sorts, [](const auto& l, const auto& r) { return l.index < r.index; }); + std::sort(sorts.begin(), sorts.end(), [](auto const& l, auto const& r) { return l.index < r.index; }); - for (auto&& sorting : sorts) { + for (auto&& sorting : sorts) m_ui->sortByBox->addItem(sorting.readable_name, QVariant(sorting.index)); - } } bool ResourcePage::setCurrentPack(ModPlatform::IndexedPack::Ptr pack) @@ -200,26 +188,24 @@ ModPlatform::IndexedPack::Ptr ResourcePage::getCurrentPack() const void ResourcePage::updateUi(const QModelIndex& index) { - if (index != m_ui->packView->currentIndex()) { + if (index != m_ui->packView->currentIndex()) return; - } - auto currentPack = getCurrentPack(); - if (!currentPack) { + auto current_pack = getCurrentPack(); + if (!current_pack) { m_ui->packDescription->setHtml({}); m_ui->packDescription->flush(); return; } QString text = ""; - QString name = currentPack->name; + QString name = current_pack->name; - if (currentPack->websiteUrl.isEmpty()) { + if (current_pack->websiteUrl.isEmpty()) text = name; - } else { - text = "websiteUrl + "\">" + name + ""; - } + else + text = "websiteUrl + "\">" + name + ""; - if (!currentPack->authors.empty()) { + if (!current_pack->authors.empty()) { auto authorToStr = [](ModPlatform::ModpackAuthor& author) -> QString { if (author.url.isEmpty()) { return author.name; @@ -227,53 +213,49 @@ void ResourcePage::updateUi(const QModelIndex& index) return QString("%2").arg(author.url, author.name); }; QStringList authorStrs; - for (auto& author : currentPack->authors) { + for (auto& author : current_pack->authors) { authorStrs.push_back(authorToStr(author)); } text += "
" + tr(" by ") + authorStrs.join(", "); } - if (currentPack->extraDataLoaded) { - if (currentPack->extraData.status == "archived") { + if (current_pack->extraDataLoaded) { + if (current_pack->extraData.status == "archived") { text += "

" + tr("This project has been archived. It will not receive any further updates unless the author decides " "to unarchive the project."); } - if (!currentPack->extraData.donate.isEmpty()) { + if (!current_pack->extraData.donate.isEmpty()) { text += "

" + tr("Donate information: "); auto donateToStr = [](ModPlatform::DonationData& donate) -> QString { return QString("%2").arg(donate.url, donate.platform); }; QStringList donates; - for (auto& donate : currentPack->extraData.donate) { + for (auto& donate : current_pack->extraData.donate) { donates.append(donateToStr(donate)); } text += donates.join(", "); } - if (!currentPack->extraData.issuesUrl.isEmpty() || !currentPack->extraData.sourceUrl.isEmpty() || - !currentPack->extraData.wikiUrl.isEmpty() || !currentPack->extraData.discordUrl.isEmpty()) { + if (!current_pack->extraData.issuesUrl.isEmpty() || !current_pack->extraData.sourceUrl.isEmpty() || + !current_pack->extraData.wikiUrl.isEmpty() || !current_pack->extraData.discordUrl.isEmpty()) { text += "

" + tr("External links:") + "
"; } - if (!currentPack->extraData.issuesUrl.isEmpty()) { - text += "- " + tr("Issues: %1").arg(currentPack->extraData.issuesUrl) + "
"; - } - if (!currentPack->extraData.wikiUrl.isEmpty()) { - text += "- " + tr("Wiki: %1").arg(currentPack->extraData.wikiUrl) + "
"; - } - if (!currentPack->extraData.sourceUrl.isEmpty()) { - text += "- " + tr("Source code: %1").arg(currentPack->extraData.sourceUrl) + "
"; - } - if (!currentPack->extraData.discordUrl.isEmpty()) { - text += "- " + tr("Discord: %1").arg(currentPack->extraData.discordUrl) + "
"; - } + if (!current_pack->extraData.issuesUrl.isEmpty()) + text += "- " + tr("Issues: %1").arg(current_pack->extraData.issuesUrl) + "
"; + if (!current_pack->extraData.wikiUrl.isEmpty()) + text += "- " + tr("Wiki: %1").arg(current_pack->extraData.wikiUrl) + "
"; + if (!current_pack->extraData.sourceUrl.isEmpty()) + text += "- " + tr("Source code: %1").arg(current_pack->extraData.sourceUrl) + "
"; + if (!current_pack->extraData.discordUrl.isEmpty()) + text += "- " + tr("Discord: %1").arg(current_pack->extraData.discordUrl) + "
"; } text += "
"; m_ui->packDescription->setHtml(StringUtils::htmlListPatch( - text + (currentPack->extraData.body.isEmpty() ? currentPack->description : markdownToHTML(currentPack->extraData.body)))); + text + (current_pack->extraData.body.isEmpty() ? current_pack->description : markdownToHTML(current_pack->extraData.body)))); m_ui->packDescription->flush(); } @@ -285,15 +267,14 @@ void ResourcePage::updateSelectionButton() } m_ui->resourceSelectionButton->setEnabled(true); - if (auto currentPack = getCurrentPack(); currentPack) { - if (currentPack->versionsLoaded && currentPack->versions.empty()) { + if (auto current_pack = getCurrentPack(); current_pack) { + if (current_pack->versionsLoaded && current_pack->versions.empty()) { m_ui->resourceSelectionButton->setEnabled(false); qWarning() << tr("No version available for the selected pack"); - } else if (!currentPack->isVersionSelected(m_selectedVersionIndex)) { + } else if (!current_pack->isVersionSelected(m_selectedVersionIndex)) m_ui->resourceSelectionButton->setText(tr("Select %1 for download").arg(resourceString())); - } else { + else m_ui->resourceSelectionButton->setText(tr("Deselect %1 for download").arg(resourceString())); - } } else { qWarning() << "Tried to update the selected button but there is not a pack selected"; } @@ -302,20 +283,19 @@ void ResourcePage::updateSelectionButton() void ResourcePage::versionListUpdated(const QModelIndex& index) { if (index == m_ui->packView->currentIndex()) { - auto currentPack = getCurrentPack(); + auto current_pack = getCurrentPack(); m_ui->versionSelectionBox->blockSignals(true); m_ui->versionSelectionBox->clear(); m_ui->versionSelectionBox->blockSignals(false); - if (currentPack) { - auto installedVersion = m_model->getInstalledPackVersion(currentPack); + if (current_pack) { + auto installedVersion = m_model->getInstalledPackVersion(current_pack); - for (int i = 0; i < currentPack->versions.size(); i++) { - auto& version = currentPack->versions[i]; - if (!m_model->checkVersionFilters(version)) { + for (int i = 0; i < current_pack->versions.size(); i++) { + auto& version = current_pack->versions[i]; + if (!m_model->checkVersionFilters(version)) continue; - } auto versionText = version.version; if (version.version_type.isValid()) { @@ -336,9 +316,8 @@ void ResourcePage::versionListUpdated(const QModelIndex& index) if (m_enableQueue.contains(index.row())) { m_enableQueue.remove(index.row()); onResourceToggle(index); - } else { + } else updateSelectionButton(); - } } else if (m_enableQueue.contains(index.row())) { m_enableQueue.remove(index.row()); onResourceToggle(index); @@ -351,30 +330,27 @@ void ResourcePage::onSelectionChanged(QModelIndex curr, [[maybe_unused]] QModelI return; } - auto currentPack = getCurrentPack(); + auto current_pack = getCurrentPack(); - bool requestLoad = false; - if (!currentPack || !currentPack->versionsLoaded) { + bool request_load = false; + if (!current_pack || !current_pack->versionsLoaded) { m_ui->resourceSelectionButton->setText(tr("Loading versions...")); m_ui->resourceSelectionButton->setEnabled(false); - requestLoad = true; + request_load = true; } else { versionListUpdated(curr); } - if (currentPack && !currentPack->extraDataLoaded) { - requestLoad = true; - } + if (current_pack && !current_pack->extraDataLoaded) + request_load = true; // we are already requesting this - if (m_enableQueue.contains(curr.row())) { - requestLoad = false; - } + if (m_enableQueue.contains(curr.row())) + request_load = false; - if (requestLoad) { + if (request_load) m_model->loadEntry(curr); - } updateUi(curr); } @@ -387,21 +363,18 @@ void ResourcePage::onVersionSelectionChanged(int index) void ResourcePage::addResourceToDialog(ModPlatform::IndexedPack::Ptr pack, ModPlatform::IndexedVersion& version) { - m_parentDialog->addResource(std::move(pack), version); + m_parentDialog->addResource(pack, version); } -void ResourcePage::removeResourceFromDialog(const QString& packName) +void ResourcePage::removeResourceFromDialog(const QString& pack_name) { - m_parentDialog->removeResource(packName); + m_parentDialog->removeResource(pack_name); } -void ResourcePage::addResourceToPage(ModPlatform::IndexedPack::Ptr pack, - ModPlatform::IndexedVersion& ver, - ResourceFolderModel* baseModel, - QString downloadReason) +void ResourcePage::addResourceToPage(ModPlatform::IndexedPack::Ptr pack, ModPlatform::IndexedVersion& ver, ResourceFolderModel* base_model) { - bool isIndexed = !APPLICATION->settings()->get("ModMetadataDisabled").toBool(); - m_model->addPack(std::move(pack), ver, baseModel, isIndexed, std::move(downloadReason)); + bool is_indexed = !APPLICATION->settings()->get("ModMetadataDisabled").toBool(); + m_model->addPack(pack, ver, base_model, is_indexed); } void ResourcePage::modelReset() @@ -416,25 +389,22 @@ void ResourcePage::removeResourceFromPage(const QString& name) void ResourcePage::onResourceSelected() { - if (m_selectedVersionIndex < 0) { + if (m_selectedVersionIndex < 0) return; - } - auto currentPack = getCurrentPack(); - if (!currentPack || !currentPack->versionsLoaded || currentPack->versions.size() < m_selectedVersionIndex) { + auto current_pack = getCurrentPack(); + if (!current_pack || !current_pack->versionsLoaded || current_pack->versions.size() < m_selectedVersionIndex) return; - } - auto& version = currentPack->versions[m_selectedVersionIndex]; + auto& version = current_pack->versions[m_selectedVersionIndex]; Q_ASSERT(!version.downloadUrl.isNull()); - if (version.is_currently_selected) { - removeResourceFromDialog(currentPack->name); - } else { - addResourceToDialog(currentPack, version); - } + if (version.is_currently_selected) + removeResourceFromDialog(current_pack->name); + else + addResourceToDialog(current_pack, version); // Save the modified pack (and prevent warning in release build) - [[maybe_unused]] bool set = setCurrentPack(currentPack); + [[maybe_unused]] bool set = setCurrentPack(current_pack); Q_ASSERT(set); updateSelectionButton(); @@ -449,28 +419,26 @@ void ResourcePage::onResourceToggle(const QModelIndex& index) auto pack = m_model->data(index, Qt::UserRole).value(); if (pack->versionsLoaded) { - if (pack->isAnyVersionSelected()) { + if (pack->isAnyVersionSelected()) removeResourceFromDialog(pack->name); - } else { + else { auto version = std::find_if(pack->versions.begin(), pack->versions.end(), [this](const ModPlatform::IndexedVersion& version) { return m_model->checkVersionFilters(version); }); if (version == pack->versions.end()) { - auto* errorMessage = new QMessageBox( + auto errorMessage = new QMessageBox( QMessageBox::Warning, tr("No versions available"), tr("No versions for '%1' are available.\nThe author likely blocked third-party launchers.").arg(pack->name), QMessageBox::Ok, this); errorMessage->open(); - } else { + } else addResourceToDialog(pack, *version); - } } - if (isSelected) { + if (isSelected) updateSelectionButton(); - } // force update QVariant variant; @@ -482,9 +450,8 @@ void ResourcePage::onResourceToggle(const QModelIndex& index) // we can't be sure that this hasn't already been requested... // but this does the job well enough and there's not much point preventing edgecases - if (!isSelected) { + if (!isSelected) m_model->loadEntry(index); - } } } @@ -515,13 +482,13 @@ void ResourcePage::openUrl(const QUrl& url) const QString slug = match.captured(1); // ensure the user isn't opening the same mod - if (auto currentPack = getCurrentPack(); currentPack && slug != currentPack->slug) { + if (auto current_pack = getCurrentPack(); current_pack && slug != current_pack->slug) { m_parentDialog->selectPage(page); - auto* newPage = m_parentDialog->selectedPage(); + auto newPage = m_parentDialog->selectedPage(); QLineEdit* searchEdit = newPage->m_ui->searchEdit; - auto* model = newPage->m_model; + auto model = newPage->m_model; QListView* view = newPage->m_ui->packView; auto jump = [url, slug, model, view] { @@ -542,11 +509,10 @@ void ResourcePage::openUrl(const QUrl& url) searchEdit->setText(slug); newPage->triggerSearch(); - if (model->hasActiveSearchJob()) { + if (model->hasActiveSearchJob()) connect(model->activeSearchJob().get(), &Task::finished, jump); - } else { + else jump(); - } return; } @@ -556,7 +522,7 @@ void ResourcePage::openUrl(const QUrl& url) QDesktopServices::openUrl(url); } -void ResourcePage::openProject(const QVariant& projectID) +void ResourcePage::openProject(QVariant projectID) { m_ui->sortByBox->hide(); m_ui->searchEdit->hide(); @@ -565,16 +531,16 @@ void ResourcePage::openProject(const QVariant& projectID) m_ui->resourceSelectionButton->hide(); m_doNotJumpToMod = true; - auto* buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this); + auto buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this); - auto* okBtn = buttonBox->button(QDialogButtonBox::Ok); + auto okBtn = buttonBox->button(QDialogButtonBox::Ok); okBtn->setDefault(true); okBtn->setAutoDefault(true); okBtn->setText(tr("Reinstall")); okBtn->setShortcut(tr("Ctrl+Return")); okBtn->setEnabled(false); - auto* cancelBtn = buttonBox->button(QDialogButtonBox::Cancel); + auto cancelBtn = buttonBox->button(QDialogButtonBox::Cancel); cancelBtn->setDefault(false); cancelBtn->setAutoDefault(false); cancelBtn->setText(tr("Cancel")); @@ -601,10 +567,9 @@ void ResourcePage::openProject(const QVariant& projectID) m_ui->searchEdit->setText("#" + projectID.toString()); triggerSearch(); - if (m_model->hasActiveSearchJob()) { + if (m_model->hasActiveSearchJob()) connect(m_model->activeSearchJob().get(), &Task::finished, jump); - } else { + else jump(); - } } } // namespace ResourceDownload diff --git a/launcher/ui/pages/modplatform/ResourcePage.h b/launcher/ui/pages/modplatform/ResourcePage.h index 03895dcd4..6e219bf22 100644 --- a/launcher/ui/pages/modplatform/ResourcePage.h +++ b/launcher/ui/pages/modplatform/ResourcePage.h @@ -9,6 +9,7 @@ #include "ResourceDownloadTask.h" #include "modplatform/ModIndex.h" +#include "modplatform/ResourceAPI.h" #include "ui/pages/BasePage.h" #include "ui/pages/modplatform/ResourceModel.h" @@ -43,9 +44,9 @@ class ResourcePage : public QWidget, public BasePage { virtual auto debugName() const -> QString = 0; //: The plural version of 'resource' - virtual QString resourcesString() const { return tr("resources"); } + virtual inline QString resourcesString() const { return tr("resources"); } //: The singular version of 'resources' - virtual QString resourceString() const { return tr("resource"); } + virtual inline QString resourceString() const { return tr("resource"); } /* Features this resource's page supports */ virtual bool supportsFiltering() const = 0; @@ -57,7 +58,7 @@ class ResourcePage : public QWidget, public BasePage { /** Get the current term in the search bar. */ auto getSearchTerm() const -> QString; /** Programatically set the term in the search bar. */ - void setSearchTerm(const QString&); + void setSearchTerm(QString); bool setCurrentPack(ModPlatform::IndexedPack::Ptr); auto getCurrentPack() const -> ModPlatform::IndexedPack::Ptr; @@ -75,26 +76,21 @@ class ResourcePage : public QWidget, public BasePage { virtual void versionListUpdated(const QModelIndex& index); void addResourceToDialog(ModPlatform::IndexedPack::Ptr, ModPlatform::IndexedVersion&); - void removeResourceFromDialog(const QString& packName); + void removeResourceFromDialog(const QString& pack_name); virtual void removeResourceFromPage(const QString& name); - virtual void addResourceToPage(ModPlatform::IndexedPack::Ptr, - ModPlatform::IndexedVersion&, - ResourceFolderModel*, - QString downloadReason = "standalone"); + virtual void addResourceToPage(ModPlatform::IndexedPack::Ptr, ModPlatform::IndexedVersion&, ResourceFolderModel*); virtual void modelReset(); QList selectedPacks() { return m_model->selectedPacks(); } bool hasSelectedPacks() { return !(m_model->selectedPacks().isEmpty()); } - virtual void openProject(const QVariant& projectID); - - void setSuppressInitialSearch(bool suppress); + virtual void openProject(QVariant projectID); protected slots: virtual void triggerSearch() = 0; - void onSelectionChanged(QModelIndex curr, QModelIndex prev); + void onSelectionChanged(QModelIndex first, QModelIndex second); void onVersionSelectionChanged(int index); void onResourceSelected(); void onResourceToggle(const QModelIndex& index); @@ -122,9 +118,6 @@ class ResourcePage : public QWidget, public BasePage { bool m_doNotJumpToMod = false; QSet m_enableQueue; - - private: - bool m_suppressInitialSearch = false; }; } // namespace ResourceDownload diff --git a/launcher/ui/pages/modplatform/ShaderPackPage.cpp b/launcher/ui/pages/modplatform/ShaderPackPage.cpp index ec5fe7967..99c50352a 100644 --- a/launcher/ui/pages/modplatform/ShaderPackPage.cpp +++ b/launcher/ui/pages/modplatform/ShaderPackPage.cpp @@ -36,18 +36,18 @@ QMap ShaderPackResourcePage::urlHandlers() const { QMap map; map.insert(QRegularExpression::anchoredPattern("(?:www\\.)?modrinth\\.com\\/shaders\\/([^\\/]+)\\/?"), "modrinth"); - map.insert(QRegularExpression::anchoredPattern(R"((?:www\.)?curseforge\.com\/minecraft\/customization\/([^\/]+)\/?)"), "curseforge"); - map.insert(QRegularExpression::anchoredPattern(R"(minecraft\.curseforge\.com\/projects\/([^\/]+)\/?)"), "curseforge"); + map.insert(QRegularExpression::anchoredPattern("(?:www\\.)?curseforge\\.com\\/minecraft\\/customization\\/([^\\/]+)\\/?"), + "curseforge"); + map.insert(QRegularExpression::anchoredPattern("minecraft\\.curseforge\\.com\\/projects\\/([^\\/]+)\\/?"), "curseforge"); return map; } void ShaderPackResourcePage::addResourceToPage(ModPlatform::IndexedPack::Ptr pack, ModPlatform::IndexedVersion& version, - ResourceFolderModel* baseModel, - QString downloadReason) + ResourceFolderModel* base_model) { - bool isIndexed = !APPLICATION->settings()->get("ModMetadataDisabled").toBool(); - m_model->addPack(pack, version, baseModel, isIndexed, downloadReason); + bool is_indexed = !APPLICATION->settings()->get("ModMetadataDisabled").toBool(); + m_model->addPack(pack, version, base_model, is_indexed); } } // namespace ResourceDownload diff --git a/launcher/ui/pages/modplatform/ShaderPackPage.h b/launcher/ui/pages/modplatform/ShaderPackPage.h index 37e3cadef..92ddd9f8a 100644 --- a/launcher/ui/pages/modplatform/ShaderPackPage.h +++ b/launcher/ui/pages/modplatform/ShaderPackPage.h @@ -23,7 +23,7 @@ class ShaderPackResourcePage : public ResourcePage { static T* create(ShaderPackDownloadDialog* dialog, BaseInstance& instance) { auto page = new T(dialog, instance); - auto* model = static_cast(page->getModel()); + auto model = static_cast(page->getModel()); connect(model, &ResourceModel::versionListUpdated, page, &ResourcePage::versionListUpdated); connect(model, &ResourceModel::projectInfoUpdated, page, &ResourcePage::updateUi); @@ -33,20 +33,17 @@ class ShaderPackResourcePage : public ResourcePage { } //: The plural version of 'shader pack' - QString resourcesString() const override { return tr("shader packs"); } + inline QString resourcesString() const override { return tr("shader packs"); } //: The singular version of 'shader packs' - QString resourceString() const override { return tr("shader pack"); } + inline QString resourceString() const override { return tr("shader pack"); } bool supportsFiltering() const override { return false; }; - void addResourceToPage(ModPlatform::IndexedPack::Ptr /*unused*/, - ModPlatform::IndexedVersion& /*unused*/, - ResourceFolderModel* /*unused*/, - QString downloadReason = "standalone") override; + void addResourceToPage(ModPlatform::IndexedPack::Ptr, ModPlatform::IndexedVersion&, ResourceFolderModel*) override; QMap urlHandlers() const override; - auto helpPage() const -> QString override { return "shaderpack-platform"; } + inline auto helpPage() const -> QString override { return "shaderpack-platform"; } protected: ShaderPackResourcePage(ShaderPackDownloadDialog* dialog, BaseInstance& instance); diff --git a/launcher/ui/pages/modplatform/flame/FlameModel.cpp b/launcher/ui/pages/modplatform/flame/FlameModel.cpp index 861dd9f22..5d968d65a 100644 --- a/launcher/ui/pages/modplatform/flame/FlameModel.cpp +++ b/launcher/ui/pages/modplatform/flame/FlameModel.cpp @@ -165,20 +165,12 @@ void ListModel::fetchMore(const QModelIndex& parent) void ListModel::performPaginatedSearch() { static const FlameAPI api; - - // activate search by id only for numerical values because all CurseForge ids are numerical - static const QRegularExpression s_projectIdExpr("^\\#[0-9]+$"); - if (m_searchState != ResetRequested && s_projectIdExpr.match(m_currentSearchTerm).hasMatch()) { + if (m_currentSearchTerm.startsWith("#")) { auto projectId = m_currentSearchTerm.mid(1); if (!projectId.isEmpty()) { ResourceAPI::Callback callbacks; - callbacks.on_fail = [this](QString reason, int network_error_code) { - if (network_error_code == 404) { - m_searchState = ResetRequested; - } - searchRequestFailed(reason); - }; + callbacks.on_fail = [this](QString reason, int) { searchRequestFailed(reason); }; callbacks.on_succeed = [this](auto& pack) { searchRequestForOneSucceeded(pack); }; callbacks.on_abort = [this] { qCritical() << "Search task aborted by an unknown reason!"; @@ -186,7 +178,7 @@ void ListModel::performPaginatedSearch() }; auto project = std::make_shared(); project->addonId = projectId; - if (auto job = api.getProjectInfo({ project }, std::move(callbacks), false); job) { + if (auto job = api.getProjectInfo({ project }, std::move(callbacks)); job) { m_jobPtr = job; m_jobPtr->start(); } diff --git a/launcher/ui/pages/modplatform/flame/FlameResourcePages.cpp b/launcher/ui/pages/modplatform/flame/FlameResourcePages.cpp index acdce29b6..99a57f2bf 100644 --- a/launcher/ui/pages/modplatform/flame/FlameResourcePages.cpp +++ b/launcher/ui/pages/modplatform/flame/FlameResourcePages.cpp @@ -41,7 +41,7 @@ #include #include #include "modplatform/flame/FlameAPI.h" -#include "../ui_ResourcePage.h" +#include "ui_ResourcePage.h" #include "FlameResourceModels.h" #include "ui/dialogs/ResourceDownloadDialog.h" diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp b/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp index 03518c3af..05cd2970c 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp @@ -135,26 +135,20 @@ void ModpackListModel::performPaginatedSearch() return; static const ModrinthAPI api; - // Modrinth ids are not limited to numbers and can be any length - if (m_searchState != ResetRequested && m_currentSearchTerm.startsWith("#")) { + if (m_currentSearchTerm.startsWith("#")) { auto projectId = m_currentSearchTerm.mid(1); if (!projectId.isEmpty()) { ResourceAPI::Callback callbacks; - callbacks.on_fail = [this](QString reason, int network_error_code) { - if (network_error_code == 404) { - m_searchState = ResetRequested; - } - searchRequestFailed(reason, network_error_code); - }; + callbacks.on_fail = [this](QString reason, int) { searchRequestFailed(reason); }; callbacks.on_succeed = [this](auto& pack) { searchRequestForOneSucceeded(pack); }; callbacks.on_abort = [this] { qCritical() << "Search task aborted by an unknown reason!"; - searchRequestFailed("Aborted", 0); + searchRequestFailed("Aborted"); }; auto project = std::make_shared(); project->addonId = projectId; - if (auto job = api.getProjectInfo({ project }, std::move(callbacks), false); job) { + if (auto job = api.getProjectInfo({ project }, std::move(callbacks)); job) { m_jobPtr = job; m_jobPtr->start(); } @@ -167,10 +161,10 @@ void ModpackListModel::performPaginatedSearch() ResourceAPI::Callback> callbacks{}; callbacks.on_succeed = [this](auto& doc) { searchRequestFinished(doc); }; - callbacks.on_fail = [this](QString reason, int network_error_code) { searchRequestFailed(reason, network_error_code); }; + callbacks.on_fail = [this](QString reason, int) { searchRequestFailed(reason); }; callbacks.on_abort = [this] { qCritical() << "Search task aborted by an unknown reason!"; - searchRequestFailed("Aborted", 0); + searchRequestFailed("Aborted"); }; auto netJob = api.searchProjects({ ModPlatform::ResourceType::Modpack, m_nextSearchOffset, m_currentSearchTerm, sort, m_filter->loaders, @@ -322,12 +316,13 @@ void ModpackListModel::searchRequestForOneSucceeded(ModPlatform::IndexedPack::Pt endInsertRows(); } -void ModpackListModel::searchRequestFailed(QString reason, int network_error_code) +void ModpackListModel::searchRequestFailed(QString) { - if (network_error_code == -1) { - // Unknown error in network stack + auto failed_action = dynamic_cast(m_jobPtr.get())->getFailedActions().at(0); + if (failed_action->replyStatusCode() == -1) { + // Network error QMessageBox::critical(nullptr, tr("Error"), tr("A network error occurred. Could not load modpacks.")); - } else if (network_error_code == 409) { + } else if (failed_action->replyStatusCode() == 409) { // 409 Gone, notify user to update QMessageBox::critical(nullptr, tr("Error"), //: %1 refers to the launcher itself diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthModel.h b/launcher/ui/pages/modplatform/modrinth/ModrinthModel.h index 3e0fc1686..96f6fd128 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthModel.h +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthModel.h @@ -85,7 +85,7 @@ class ModpackListModel : public QAbstractListModel { public slots: void searchRequestFinished(QList& doc_all); - void searchRequestFailed(QString reason, int network_error_code); + void searchRequestFailed(QString reason); void searchRequestForOneSucceeded(ModPlatform::IndexedPack::Ptr); protected slots: diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.cpp b/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.cpp index a1a7390bb..c290b6715 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.cpp +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.cpp @@ -38,7 +38,7 @@ #include "ModrinthResourcePages.h" #include "ui/pages/modplatform/DataPackModel.h" -#include "../ui_ResourcePage.h" +#include "ui_ResourcePage.h" #include "modplatform/modrinth/ModrinthAPI.h" diff --git a/launcher/ui/widgets/EnvironmentVariables.cpp b/launcher/ui/widgets/EnvironmentVariables.cpp index 33bb00c63..9387ef2e2 100644 --- a/launcher/ui/widgets/EnvironmentVariables.cpp +++ b/launcher/ui/widgets/EnvironmentVariables.cpp @@ -104,7 +104,7 @@ QMap EnvironmentVariables::value() const QMap result; QTreeWidgetItem* item = ui->list->topLevelItem(0); for (int i = 1; item != nullptr; item = ui->list->topLevelItem(i++)) - result[item->text(0).trimmed()] = item->text(1).trimmed(); + result[item->text(0)] = item->text(1); return result; } diff --git a/launcher/ui/widgets/InfoFrame.cpp b/launcher/ui/widgets/InfoFrame.cpp index 3bf9fef82..354211439 100644 --- a/launcher/ui/widgets/InfoFrame.cpp +++ b/launcher/ui/widgets/InfoFrame.cpp @@ -87,7 +87,7 @@ void InfoFrame::updateWithMod(const Mod& m) QString name = ""; QString link = m.homepage(); if (m.name().isEmpty()) - name = m.internalId(); + name = m.internal_id(); else name = renderColorCodes(m.name()); diff --git a/launcher/ui/widgets/JavaSettingsWidget.ui b/launcher/ui/widgets/JavaSettingsWidget.ui index 03d632ad9..14638cf4e 100644 --- a/launcher/ui/widgets/JavaSettingsWidget.ui +++ b/launcher/ui/widgets/JavaSettingsWidget.ui @@ -392,10 +392,7 @@ autodownloadJavaCheckBox javaTestBtn javaDownloadBtn - minMemSpinBox maxMemSpinBox - permGenSpinBox - lowMemWarningCheckBox jvmArgsTextBox
diff --git a/launcher/ui/widgets/LanguageSelectionWidget.cpp b/launcher/ui/widgets/LanguageSelectionWidget.cpp index 3f35df7b0..a32f7034d 100644 --- a/launcher/ui/widgets/LanguageSelectionWidget.cpp +++ b/launcher/ui/widgets/LanguageSelectionWidget.cpp @@ -63,7 +63,7 @@ void LanguageSelectionWidget::retranslate() QString text = tr("Don't see your language or the quality is poor?
Help us with translations!") .arg(BuildConfig.TRANSLATIONS_URL); helpUsLabel->setText(text); - formatCheckbox->setText(tr("Use system regional standards")); + formatCheckbox->setText(tr("Use system locales")); } void LanguageSelectionWidget::languageRowChanged(const QModelIndex& current, const QModelIndex& previous) diff --git a/launcher/ui/widgets/MinecraftSettingsWidget.ui b/launcher/ui/widgets/MinecraftSettingsWidget.ui index a063f9660..80fb8530d 100644 --- a/launcher/ui/widgets/MinecraftSettingsWidget.ui +++ b/launcher/ui/widgets/MinecraftSettingsWidget.ui @@ -858,71 +858,32 @@ It is most likely you will need to change the path - please refer to the mod's w openGlobalSettingsButton settingsTabs scrollArea - - - windowSizeGroupBox maximizedCheckBox - windowWidthSpinBox windowHeightSpinBox + windowWidthSpinBox closeAfterLaunchCheck quitAfterGameStopCheck - - - consoleSettingsBox showConsoleCheck showConsoleErrorCheck autoCloseConsoleCheck - - - globalDataPacksGroupBox - dataPacksPathEdit - dataPacksPathBrowse - - --> - gameTimeGroupBox showGameTime recordGameTime showGlobalGameTime showGameTimeWithoutDays - - instanceAccountGroupBox instanceAccountSelector - - serverJoinGroupBox serverJoinAddressButton serverJoinAddress worldJoinButton worldsCb - - - loaderGroup - neoForge - forge - fabric - quilt - liteLoader - babric - btaBabric - legacyFabric - ornithe - rift - javaScrollArea scrollArea_2 - - - legacySettingsGroupBox onlineFixes - - - nativeWorkaroundsGroupBox useNativeGLFWCheck lineEditGLFWPath useNativeOpenALCheck lineEditOpenALPath - enableFeralGamemodeCheck enableMangoHud useDiscreteGpuCheck diff --git a/launcher/ui/widgets/PageContainer.cpp b/launcher/ui/widgets/PageContainer.cpp index ad43e95e4..58b092275 100644 --- a/launcher/ui/widgets/PageContainer.cpp +++ b/launcher/ui/widgets/PageContainer.cpp @@ -49,7 +49,6 @@ #include #include #include -#include #include "settings/SettingsObject.h" @@ -60,43 +59,40 @@ class PageEntryFilterModel : public QSortFilterProxyModel { public: - explicit PageEntryFilterModel(QObject* parent = nullptr) : QSortFilterProxyModel(parent) {} + explicit PageEntryFilterModel(QObject* parent = 0) : QSortFilterProxyModel(parent) {} protected: - bool filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const override + bool filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const { const QString pattern = filterRegularExpression().pattern(); - auto* const model = static_cast(sourceModel()); - auto* const page = model->pages().at(sourceRow); - if (!page->shouldDisplay()) { + const auto model = static_cast(sourceModel()); + const auto page = model->pages().at(sourceRow); + if (!page->shouldDisplay()) return false; - } // Regular contents check, then check page-filter. return QSortFilterProxyModel::filterAcceptsRow(sourceRow, sourceParent); } }; -PageContainer::PageContainer(BasePageProvider* pageProvider, QString defaultId, QWidget* parent) - : QWidget(parent) - , m_proxyModel(new PageEntryFilterModel(this)) - , m_model(new PageModel(this)) +PageContainer::PageContainer(BasePageProvider* pageProvider, QString defaultId, QWidget* parent) : QWidget(parent) { createUI(); useSidebarStyle(true); + m_model = new PageModel(this); + m_proxyModel = new PageEntryFilterModel(this); int counter = 0; auto pages = pageProvider->getPages(); - for (auto* page : pages) { - auto* widget = dynamic_cast(page); + for (auto page : pages) { + auto widget = dynamic_cast(page); widget->setParent(this); page->stackIndex = m_pageStack->addWidget(widget); page->listIndex = counter; page->setParentContainer(this); counter++; - page->updateExtraInfo = [this](const QString& id, const QString& info) { - if (m_currentPage && id == m_currentPage->id()) { + page->updateExtraInfo = [this](QString id, QString info) { + if (m_currentPage && id == m_currentPage->id()) m_header->setText(m_currentPage->displayName() + info); - } }; } m_model->setPages(pages); @@ -112,13 +108,13 @@ PageContainer::PageContainer(BasePageProvider* pageProvider, QString defaultId, connect(m_pageList->selectionModel(), &QItemSelectionModel::currentRowChanged, this, &PageContainer::currentChanged); m_pageStack->setStackingMode(QStackedLayout::StackOne); m_pageList->setFocus(); - selectPage(std::move(defaultId)); + selectPage(defaultId); } bool PageContainer::selectPage(QString pageId) { // now find what we want to have selected... - auto* page = m_model->findPageEntryById(pageId); + auto page = m_model->findPageEntryById(pageId); QModelIndex index; if (page) { index = m_proxyModel->mapFromSource(m_model->index(page->listIndex)); @@ -170,12 +166,11 @@ void PageContainer::createUI() QFont headerLabelFont = m_header->font(); headerLabelFont.setBold(true); const int pointSize = headerLabelFont.pointSize(); - if (pointSize > 0) { + if (pointSize > 0) headerLabelFont.setPointSize(pointSize + 2); - } m_header->setFont(headerLabelFont); - auto* headerHLayout = new QHBoxLayout; + QHBoxLayout* headerHLayout = new QHBoxLayout; const int leftMargin = APPLICATION->style()->pixelMetric(QStyle::PM_LayoutLeftMargin); headerHLayout->addSpacerItem(new QSpacerItem(leftMargin, 0, QSizePolicy::Fixed, QSizePolicy::Ignored)); headerHLayout->addWidget(m_header); @@ -195,13 +190,11 @@ void PageContainer::createUI() void PageContainer::retranslate() { - if (m_currentPage) { + if (m_currentPage) m_header->setText(m_currentPage->displayName()); - } - for (auto* page : m_model->pages()) { + for (auto page : m_model->pages()) page->retranslate(); - } } void PageContainer::addButtons(QWidget* buttons) @@ -243,23 +236,22 @@ void PageContainer::help() { if (m_currentPage) { QString pageId = m_currentPage->helpPage(); - if (pageId.isEmpty()) { + if (pageId.isEmpty()) return; - } DesktopServices::openUrl(QUrl(BuildConfig.HELP_URL.arg(pageId))); } } void PageContainer::currentChanged(const QModelIndex& current) { - int selectedIndex = current.isValid() ? m_proxyModel->mapToSource(current).row() : -1; + int selected_index = current.isValid() ? m_proxyModel->mapToSource(current).row() : -1; - auto* selected = m_model->pages().at(selectedIndex); + auto* selected = m_model->pages().at(selected_index); auto* previous = m_currentPage; emit selectedPageChanged(previous, selected); - showPage(selectedIndex); + showPage(selected_index); } bool PageContainer::prepareToClose() @@ -275,10 +267,9 @@ bool PageContainer::prepareToClose() bool PageContainer::saveAll() { - for (auto* page : m_model->pages()) { - if (!page->apply()) { + for (auto page : m_model->pages()) { + if (!page->apply()) return false; - } } return true; } diff --git a/launcher/ui/widgets/PageContainer.h b/launcher/ui/widgets/PageContainer.h index 2ca5e6f08..2c7ca9e39 100644 --- a/launcher/ui/widgets/PageContainer.h +++ b/launcher/ui/widgets/PageContainer.h @@ -56,8 +56,8 @@ class QGridLayout; class PageContainer : public QWidget, public BasePageContainer { Q_OBJECT public: - explicit PageContainer(BasePageProvider* pageProvider, QString defaultId = QString(), QWidget* parent = nullptr); - ~PageContainer() override = default; + explicit PageContainer(BasePageProvider* pageProvider, QString defaultId = QString(), QWidget* parent = 0); + virtual ~PageContainer() {} void addButtons(QWidget* buttons); void addButtons(QLayout* buttons); diff --git a/launcher/ui/widgets/ProjectItem.cpp b/launcher/ui/widgets/ProjectItem.cpp index 1c4fa3596..2fd5c97c2 100644 --- a/launcher/ui/widgets/ProjectItem.cpp +++ b/launcher/ui/widgets/ProjectItem.cpp @@ -47,31 +47,30 @@ void ProjectItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem& o painter->setOpacity(0.4); // Fade out the entire item } // The default icon size will be a square (and height is usually the lower value). - auto icon_width = rect.height(); + auto icon_width = rect.height(), icon_height = rect.height(); int icon_x_margin = (rect.height() - icon_width) / 2; + int icon_y_margin = (rect.height() - icon_height) / 2; if (!opt.icon.isNull()) { // Icon painting - auto icon_height = 0; { auto icon_size = opt.decorationSize; icon_width = icon_size.width(); icon_height = icon_size.height(); - icon_x_margin = (rect.height() - icon_height) / 2; // use same margins for consistency + icon_y_margin = (rect.height() - icon_height) / 2; + icon_x_margin = icon_y_margin; // use same margins for consistency } // Centralize icon with a margin to separate from the other elements int x = rect.x() + icon_x_margin; - int y = rect.y() + icon_x_margin; + int y = rect.y() + icon_y_margin; - if (opt.features & QStyleOptionViewItem::HasCheckIndicator) { + if (opt.features & QStyleOptionViewItem::HasCheckIndicator) rect.translate(icon_x_margin / 2, 0); - } // Prevent 'scaling null pixmap' warnings - if (icon_width > 0 && icon_height > 0) { + if (icon_width > 0 && icon_height > 0) opt.icon.paint(painter, x, y, icon_width, icon_height); - } } // Change the rect so that funther painting is easier @@ -143,7 +142,7 @@ void ProjectItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem& o description_y -= opt.fontMetrics.height(); // On the bottom, aligned to the left after the icon, and featuring at most two lines of text (with some margin space to spare) - painter->drawText(description_x, description_y, remaining_width, num_lines * opt.fontMetrics.height(), Qt::TextWordWrap, + painter->drawText(description_x, description_y, remaining_width, cut_text.size() * opt.fontMetrics.height(), Qt::TextWordWrap, description); } diff --git a/launcher/ui/widgets/VersionSelectWidget.cpp b/launcher/ui/widgets/VersionSelectWidget.cpp index 01b876146..040355f4b 100644 --- a/launcher/ui/widgets/VersionSelectWidget.cpp +++ b/launcher/ui/widgets/VersionSelectWidget.cpp @@ -127,9 +127,9 @@ void VersionSelectWidget::closeEvent(QCloseEvent* event) QWidget::closeEvent(event); } -void VersionSelectWidget::loadList(bool forceReload) +void VersionSelectWidget::loadList() { - m_load_task = m_vlist->getLoadTask(forceReload); + m_load_task = m_vlist->getLoadTask(); connect(m_load_task.get(), &Task::succeeded, this, &VersionSelectWidget::onTaskSucceeded); connect(m_load_task.get(), &Task::failed, this, &VersionSelectWidget::onTaskFailed); connect(m_load_task.get(), &Task::progress, this, &VersionSelectWidget::changeProgress); diff --git a/launcher/ui/widgets/VersionSelectWidget.h b/launcher/ui/widgets/VersionSelectWidget.h index ee9dbead7..c66d7e98e 100644 --- a/launcher/ui/widgets/VersionSelectWidget.h +++ b/launcher/ui/widgets/VersionSelectWidget.h @@ -57,7 +57,7 @@ class VersionSelectWidget : public QWidget { void initialize(BaseVersionList* vlist, bool forceLoad = false); //! Starts a task that loads the list. - void loadList(bool forceReload = false); + void loadList(); bool hasVersions() const; BaseVersion::Ptr selectedVersion() const; diff --git a/launcher/updater/PrismExternalUpdater.cpp b/launcher/updater/PrismExternalUpdater.cpp index 00f8404cf..a4e34e10a 100644 --- a/launcher/updater/PrismExternalUpdater.cpp +++ b/launcher/updater/PrismExternalUpdater.cpp @@ -21,8 +21,9 @@ */ #include "PrismExternalUpdater.h" - #include +#include +#include #include #include #include @@ -57,18 +58,19 @@ PrismExternalUpdater::PrismExternalUpdater(QWidget* parent, const QString& appDi { priv->appDir = QDir(appDir); priv->dataDir = QDir(dataDir); - auto settingsFile = priv->dataDir.absoluteFilePath("prismlauncher_update.cfg"); - priv->settings = std::make_unique(settingsFile, QSettings::Format::IniFormat); + auto settings_file = priv->dataDir.absoluteFilePath("prismlauncher_update.cfg"); + priv->settings = std::make_unique(settings_file, QSettings::Format::IniFormat); priv->allowBeta = priv->settings->value("allow_beta", false).toBool(); priv->autoCheck = priv->settings->value("auto_check", true).toBool(); - bool intervalOk = false; + bool interval_ok = false; // default once per day - priv->updateInterval = priv->settings->value("update_interval", 86400).toInt(&intervalOk); - if (!intervalOk) { + priv->updateInterval = priv->settings->value("update_interval", 86400).toInt(&interval_ok); + if (!interval_ok) { priv->updateInterval = 86400; } - if (const auto lastCheck = priv->settings->value("last_check"); !lastCheck.isNull() && lastCheck.isValid()) { - priv->lastCheck = QDateTime::fromString(lastCheck.toString(), Qt::ISODate); + auto last_check = priv->settings->value("last_check"); + if (!last_check.isNull() && last_check.isValid()) { + priv->lastCheck = QDateTime::fromString(last_check.toString(), Qt::ISODate); } priv->parent = parent; connectTimer(); @@ -93,10 +95,9 @@ void PrismExternalUpdater::checkForUpdates() checkForUpdates(true); } -void PrismExternalUpdater::checkForUpdates(bool triggeredByUser) const +void PrismExternalUpdater::checkForUpdates(bool triggeredByUser) { QProgressDialog progress(tr("Checking for updates..."), "", 0, 0, priv->parent); - progress.setMinimumDuration(0); // Appear immediately without waiting progress.setCancelButton(nullptr); progress.adjustSize(); if (triggeredByUser) { @@ -105,15 +106,15 @@ void PrismExternalUpdater::checkForUpdates(bool triggeredByUser) const QCoreApplication::processEvents(); QProcess proc; - auto exeName = QStringLiteral("%1_updater").arg(BuildConfig.LAUNCHER_APP_BINARY_NAME); -#ifdef Q_OS_WIN32 - exeName.append(".exe"); + auto exe_name = QStringLiteral("%1_updater").arg(BuildConfig.LAUNCHER_APP_BINARY_NAME); +#if defined Q_OS_WIN32 + exe_name.append(".exe"); auto env = QProcessEnvironment::systemEnvironment(); env.insert("__COMPAT_LAYER", "RUNASINVOKER"); proc.setProcessEnvironment(env); #else - exeName = QString("bin/%1").arg(exeName); + exe_name = QString("bin/%1").arg(exe_name); #endif QStringList args = { "--check-only", "--dir", priv->dataDir.absolutePath(), "--debug" }; @@ -121,8 +122,9 @@ void PrismExternalUpdater::checkForUpdates(bool triggeredByUser) const args.append("--pre-release"); } - proc.start(priv->appDir.absoluteFilePath(exeName), args); - if (auto resultStart = proc.waitForStarted(5000); !resultStart) { + proc.start(priv->appDir.absoluteFilePath(exe_name), args); + auto result_start = proc.waitForStarted(5000); + if (!result_start) { auto err = proc.error(); qDebug() << "Failed to start updater after 5 seconds." << "reason:" << err << proc.errorString(); @@ -140,7 +142,8 @@ void PrismExternalUpdater::checkForUpdates(bool triggeredByUser) const } QCoreApplication::processEvents(); - if (auto resultFinished = proc.waitForFinished(60000); !resultFinished) { + auto result_finished = proc.waitForFinished(60000); + if (!result_finished) { proc.kill(); auto err = proc.error(); auto output = proc.readAll(); @@ -160,15 +163,15 @@ void PrismExternalUpdater::checkForUpdates(bool triggeredByUser) const return; } - auto exitCode = proc.exitCode(); + auto exit_code = proc.exitCode(); - auto stdOutput = proc.readAllStandardOutput(); - auto stdError = proc.readAllStandardError(); + auto std_output = proc.readAllStandardOutput(); + auto std_error = proc.readAllStandardError(); - progress.cancel(); + progress.hide(); QCoreApplication::processEvents(); - switch (exitCode) { + switch (exit_code) { case 0: // no update available if (triggeredByUser) { @@ -183,10 +186,10 @@ void PrismExternalUpdater::checkForUpdates(bool triggeredByUser) const case 1: // there was an error { - qDebug() << "Updater subprocess error" << qPrintable(stdError); + qDebug() << "Updater subprocess error" << qPrintable(std_error); auto msgBox = QMessageBox(QMessageBox::Warning, tr("Update Check Error"), tr("There was an error running the update check."), QMessageBox::Ok, priv->parent); - msgBox.setDetailedText(QString(stdError)); + msgBox.setDetailedText(QString(std_error)); msgBox.setMinimumWidth(460); msgBox.adjustSize(); msgBox.exec(); @@ -195,27 +198,28 @@ void PrismExternalUpdater::checkForUpdates(bool triggeredByUser) const case 100: // update available { - auto [firstLine, remainder1] = StringUtils::splitFirst(stdOutput, '\n'); - auto [secondLine, remainder2] = StringUtils::splitFirst(remainder1, '\n'); - auto [thirdLine, releaseNotes] = StringUtils::splitFirst(remainder2, '\n'); - auto versionName = StringUtils::splitFirst(firstLine, ": ").second.trimmed(); - auto versionTag = StringUtils::splitFirst(secondLine, ": ").second.trimmed(); - auto releaseTimestamp = QDateTime::fromString(StringUtils::splitFirst(thirdLine, ": ").second.trimmed(), Qt::ISODate); - qDebug() << "Update available:" << versionName << versionTag << releaseTimestamp; - qDebug() << "Update release notes:" << releaseNotes; + auto [first_line, remainder1] = StringUtils::splitFirst(std_output, '\n'); + auto [second_line, remainder2] = StringUtils::splitFirst(remainder1, '\n'); + auto [third_line, release_notes] = StringUtils::splitFirst(remainder2, '\n'); + auto version_name = StringUtils::splitFirst(first_line, ": ").second.trimmed(); + auto version_tag = StringUtils::splitFirst(second_line, ": ").second.trimmed(); + auto release_timestamp = QDateTime::fromString(StringUtils::splitFirst(third_line, ": ").second.trimmed(), Qt::ISODate); + qDebug() << "Update available:" << version_name << version_tag << release_timestamp; + qDebug() << "Update release notes:" << release_notes; - offerUpdate(versionName, versionTag, releaseNotes, triggeredByUser); + offerUpdate(version_name, version_tag, release_notes); } break; default: // unknown error code { - qDebug() << "Updater exited with unknown code" << exitCode; - auto msgBox = QMessageBox(QMessageBox::Information, tr("Unknown Update Error"), - tr("The updater exited with an unknown condition.\nExit Code: %1").arg(QString::number(exitCode)), - QMessageBox::Ok, priv->parent); - auto detailTxt = tr("StdOut: %1\nStdErr: %2").arg(QString(stdOutput)).arg(QString(stdError)); - msgBox.setDetailedText(detailTxt); + qDebug() << "Updater exited with unknown code" << exit_code; + auto msgBox = + QMessageBox(QMessageBox::Information, tr("Unknown Update Error"), + tr("The updater exited with an unknown condition.\nExit Code: %1").arg(QString::number(exit_code)), + QMessageBox::Ok, priv->parent); + auto detail_txt = tr("StdOut: %1\nStdErr: %2").arg(QString(std_output)).arg(QString(std_error)); + msgBox.setDetailedText(detail_txt); msgBox.setMinimumWidth(460); msgBox.adjustSize(); msgBox.exec(); @@ -265,7 +269,7 @@ void PrismExternalUpdater::setBetaAllowed(bool allowed) priv->settings->sync(); } -void PrismExternalUpdater::resetAutoCheckTimer() const +void PrismExternalUpdater::resetAutoCheckTimer() { if (priv->autoCheck && priv->updateInterval > 0) { auto now = QDateTime::currentDateTime(); @@ -273,9 +277,9 @@ void PrismExternalUpdater::resetAutoCheckTimer() const qint64 timeoutMs = 0; if (priv->lastCheck.isValid()) { - const qint64 diff = priv->lastCheck.secsTo(now); - const qint64 secsLeft = std::max(priv->updateInterval - diff, 0); - timeoutMs = secsLeft * 1000; + qint64 diff = priv->lastCheck.secsTo(now); + qint64 secs_left = std::max(priv->updateInterval - diff, 0); + timeoutMs = secs_left * 1000; } timeoutMs = std::min(timeoutMs, static_cast(INT_MAX)); @@ -299,70 +303,69 @@ void PrismExternalUpdater::disconnectTimer() disconnect(&priv->updateTimer, &QTimer::timeout, this, &PrismExternalUpdater::autoCheckTimerFired); } -void PrismExternalUpdater::autoCheckTimerFired() const +void PrismExternalUpdater::autoCheckTimerFired() { qDebug() << "Auto update Timer fired"; checkForUpdates(false); } -void PrismExternalUpdater::offerUpdate(const QString& versionName, - const QString& versionTag, - const QString& releaseNotes, - const bool triggeredByUser) const +void PrismExternalUpdater::offerUpdate(const QString& version_name, const QString& version_tag, const QString& release_notes) { priv->settings->beginGroup("skip"); - auto shouldSkip = !triggeredByUser && priv->settings->value(versionTag, false).toBool(); + auto should_skip = priv->settings->value(version_tag, false).toBool(); priv->settings->endGroup(); - if (shouldSkip) { - if (triggeredByUser) { - auto msgBox = QMessageBox(QMessageBox::Information, tr("No Update Available"), tr("There are no new updates available."), - QMessageBox::Ok, priv->parent); - msgBox.setMinimumWidth(460); - msgBox.adjustSize(); - msgBox.exec(); - } + if (should_skip) { + auto msgBox = QMessageBox(QMessageBox::Information, tr("No Update Available"), tr("There are no new updates available."), + QMessageBox::Ok, priv->parent); + msgBox.setMinimumWidth(460); + msgBox.adjustSize(); + msgBox.exec(); return; } - UpdateAvailableDialog dlg(BuildConfig.printableVersionString(), versionName, releaseNotes); + UpdateAvailableDialog dlg(BuildConfig.printableVersionString(), version_name, release_notes); auto result = dlg.exec(); qDebug() << "offer dlg result" << result; - - priv->settings->beginGroup("skip"); - if (result == UpdateAvailableDialog::Skip) { - priv->settings->setValue(versionTag, true); - } else { - if (result == UpdateAvailableDialog::Install) { - performUpdate(versionTag); + switch (result) { + case UpdateAvailableDialog::Install: { + performUpdate(version_tag); + return; + } + case UpdateAvailableDialog::Skip: { + priv->settings->beginGroup("skip"); + priv->settings->setValue(version_tag, true); + priv->settings->endGroup(); + priv->settings->sync(); + return; + } + default: { + return; } - priv->settings->remove(versionTag); } - priv->settings->endGroup(); - priv->settings->sync(); } -void PrismExternalUpdater::performUpdate(const QString& versionTag) const +void PrismExternalUpdater::performUpdate(const QString& version_tag) { QProcess proc; - auto exeName = QStringLiteral("%1_updater").arg(BuildConfig.LAUNCHER_APP_BINARY_NAME); -#ifdef Q_OS_WIN32 - exeName.append(".exe"); + auto exe_name = QStringLiteral("%1_updater").arg(BuildConfig.LAUNCHER_APP_BINARY_NAME); +#if defined Q_OS_WIN32 + exe_name.append(".exe"); auto env = QProcessEnvironment::systemEnvironment(); env.insert("__COMPAT_LAYER", "RUNASINVOKER"); proc.setProcessEnvironment(env); #else - exeName = QString("bin/%1").arg(exeName); + exe_name = QString("bin/%1").arg(exe_name); #endif - QStringList args = { "--dir", priv->dataDir.absolutePath(), "--install-version", versionTag }; + QStringList args = { "--dir", priv->dataDir.absolutePath(), "--install-version", version_tag }; if (priv->allowBeta) { args.append("--pre-release"); } - proc.setProgram(priv->appDir.absoluteFilePath(exeName)); + proc.setProgram(priv->appDir.absoluteFilePath(exe_name)); proc.setArguments(args); auto result = proc.startDetached(); if (!result) { diff --git a/launcher/updater/PrismExternalUpdater.h b/launcher/updater/PrismExternalUpdater.h index b3f284b33..b88676028 100644 --- a/launcher/updater/PrismExternalUpdater.h +++ b/launcher/updater/PrismExternalUpdater.h @@ -22,10 +22,12 @@ #pragma once +#include + #include "ExternalUpdater.h" /*! - * An implementation for the updater on Windows and linux that uses out external updater. + * An implementation for the updater on windows and linux that uses out external updater. */ class PrismExternalUpdater : public ExternalUpdater { @@ -39,7 +41,7 @@ class PrismExternalUpdater : public ExternalUpdater { * Check for updates manually, showing the user a progress bar and an alert if no updates are found. */ void checkForUpdates() override; - void checkForUpdates(bool triggeredByUser) const; + void checkForUpdates(bool triggeredByUser); /*! * Indicates whether or not to check for updates automatically. @@ -60,7 +62,7 @@ class PrismExternalUpdater : public ExternalUpdater { * Set whether or not to check for updates automatically. * * The update schedule cycle will be reset in a short delay after the property’s new value is set. This is to allow - * reverting this property without kicking off a schedule change immediately. + * reverting this property without kicking off a schedule change immediately." */ void setAutomaticallyChecksForUpdates(bool check) override; @@ -68,7 +70,7 @@ class PrismExternalUpdater : public ExternalUpdater { * Set the current automatic update check interval in seconds. * * The update schedule cycle will be reset in a short delay after the property’s new value is set. This is to allow - * reverting this property without kicking off a schedule change immediately. + * reverting this property without kicking off a schedule change immediately." */ void setUpdateCheckInterval(double seconds) override; @@ -77,15 +79,15 @@ class PrismExternalUpdater : public ExternalUpdater { */ void setBetaAllowed(bool allowed) override; - void resetAutoCheckTimer() const; + void resetAutoCheckTimer(); void disconnectTimer(); void connectTimer(); - void offerUpdate(const QString& versionName, const QString& versionTag, const QString& releaseNotes, bool triggeredByUser) const; - void performUpdate(const QString& versionTag) const; + void offerUpdate(const QString& version_name, const QString& version_tag, const QString& release_notes); + void performUpdate(const QString& version_tag); public slots: - void autoCheckTimerFired() const; + void autoCheckTimerFired(); private: class Private; diff --git a/launcher/updater/prismupdater/PrismUpdater.cpp b/launcher/updater/prismupdater/PrismUpdater.cpp index 6ad60a7c7..11e92efcd 100644 --- a/launcher/updater/prismupdater/PrismUpdater.cpp +++ b/launcher/updater/prismupdater/PrismUpdater.cpp @@ -1160,6 +1160,8 @@ void PrismUpdaterApp::downloadReleasePage(const QString& api_url, int page) m_current_task.reset(download); connect(download.get(), &Net::Download::finished, this, [this]() { qDebug() << "Download" << m_current_task->getUid().toString() << "finished"; + m_current_task.reset(); + m_current_url = ""; }); QCoreApplication::processEvents(); diff --git a/nix/unwrapped.nix b/nix/unwrapped.nix index 829a4843c..478eb7b3e 100644 --- a/nix/unwrapped.nix +++ b/nix/unwrapped.nix @@ -3,12 +3,12 @@ stdenv, cmake, cmark, + extra-cmake-modules, gamemode, jdk17, kdePackages, libnbtplusplus, ninja, - pkg-config, qrencode, self, stripJavaArchivesHook, @@ -35,13 +35,6 @@ let ] else "unknown"; - - # Remove once https://github.com/NixOS/nixpkgs/pull/518987 lands - extra-cmake-modules = kdePackages.extra-cmake-modules.overrideAttrs (prevAttrs: { - meta = prevAttrs.meta // { - platforms = lib.platforms.all; - }; - }); in stdenv.mkDerivation { @@ -72,7 +65,6 @@ stdenv.mkDerivation { cmake ninja extra-cmake-modules - pkg-config jdk17 stripJavaArchivesHook ]; diff --git a/nix/wrapper.nix b/nix/wrapper.nix index 23fc04d9f..00752a8c4 100644 --- a/nix/wrapper.nix +++ b/nix/wrapper.nix @@ -6,7 +6,6 @@ glfw3-minecraft, jdk17, jdk21, - jdk25, jdk8, kdePackages, lib, @@ -35,7 +34,6 @@ controllerSupport ? stdenv.hostPlatform.isLinux, gamemodeSupport ? stdenv.hostPlatform.isLinux, jdks ? [ - jdk25 jdk21 jdk17 jdk8 diff --git a/program_info/win_install.nsi.in b/program_info/win_install.nsi.in index 83335ce9d..ba6b7e061 100644 --- a/program_info/win_install.nsi.in +++ b/program_info/win_install.nsi.in @@ -4,7 +4,6 @@ !include "x64.nsh" -AllowSkipFiles off Unicode true Name "@Launcher_DisplayName@" diff --git a/renovate.json b/renovate.json index 856b2e91c..0a74c6de7 100644 --- a/renovate.json +++ b/renovate.json @@ -4,7 +4,7 @@ "config:recommended" ], "labels": [ - "area: actions", + "area: CI", "complexity: low", "priority: low", "type: robot", diff --git a/tests/ResourceFolderModel_test.cpp b/tests/ResourceFolderModel_test.cpp index 26fe5ab16..145e6b3d7 100644 --- a/tests/ResourceFolderModel_test.cpp +++ b/tests/ResourceFolderModel_test.cpp @@ -217,8 +217,8 @@ class ResourceFolderModelTest : public QObject { auto& res_1 = model.at(0).type() != ResourceType::FOLDER ? model.at(0) : model.at(1); auto& res_2 = model.at(0).type() == ResourceType::FOLDER ? model.at(0) : model.at(1); - auto id_1 = res_1.internalId(); - auto id_2 = res_2.internalId(); + auto id_1 = res_1.internal_id(); + auto id_2 = res_2.internal_id(); bool initial_enabled_res_2 = res_2.enabled(); bool initial_enabled_res_1 = res_1.enabled(); @@ -236,12 +236,12 @@ class ResourceFolderModelTest : public QObject { qDebug() << "res_1 got successfully toggled again."; QVERIFY(res_1.enabled() == initial_enabled_res_1); - QVERIFY(res_1.internalId() == id_1); + QVERIFY(res_1.internal_id() == id_1); qDebug() << "res_1 got back to its initial state."; QVERIFY(!res_2.enable(initial_enabled_res_2 ? EnableAction::ENABLE : EnableAction::DISABLE)); QVERIFY(res_2.enabled() == initial_enabled_res_2); - QVERIFY(res_2.internalId() == id_2); + QVERIFY(res_2.internal_id() == id_2); } }; diff --git a/vcpkg.json b/vcpkg.json index 942e6d9e4..5fd336fff 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -26,6 +26,7 @@ ] }, "tomlplusplus", - "zlib" + "zlib", + "vulkan-headers" ] }